springboot+security整合(3)自定义鉴权
说明 springboot 版本 2.0.3
源码地址:点击跳转
系列
这篇讲解如何自定义鉴权过程,实现根据数据库查询出的 url 和 method 是否匹配当前请求的 url 和 method 来决定有没有权限。security 鉴权过程如下:

一、 重写 metadataSource 类
- 编写 MyGranteAuthority 类,让权限包含 url 和 method 两个部分。
public class MyGrantedAuthority implements GrantedAuthority {
private String method;
private String url;
public MyGrantedAuthority(String method, String url) {
this.method = method;
this.url = url;
}
@Override
public String getAuthority() {
return url;
}
public String getMethod() {
return method;
}
public String getUrl() {
return url;
}
@Override
public boolean equals(Object obj) {
if(this==obj) return true;
if(obj==null||getClass()!= obj.getClass()) return false;
MyGrantedAuthority grantedAuthority = (MyGrantedAuthority)obj;
if(this.method.equals(grantedAuthority.getMethod())&&this.url.equals(grantedAuthority.getUrl()))
return true;
return false;
}
}
- 编写 MyConfigAttribute 类,实现 ConfigAttribute 接口,代码如下:
public class MyConfigAttribute implements ConfigAttribute {
private HttpServletRequest httpServletRequest;
private MyGrantedAuthority myGrantedAuthority;
public MyConfigAttribute(HttpServletRequest httpServletRequest) {
this.httpServletRequest = httpServletRequest;
}
public MyConfigAttribute(HttpServletRequest httpServletRequest, MyGrantedAuthority myGrantedAuthority) {
this.httpServletRequest = httpServletRequest;
this.myGrantedAuthority = myGrantedAuthority;
}
public HttpServletRequest getHttpServletRequest() {
return httpServletRequest;
}
@Override
public String getAttribute() {
return myGrantedAuthority.getUrl();
}
public MyGrantedAuthority getMyGrantedAuthority() {
return myGrantedAuthority;
}
}
- 编写 MySecurityMetadataSource 类,获取当前 url 所需要的权限
@Component
public class MySecurityMetadataSource implements FilterInvocationSecurityMetadataSource {
private Logger log = LoggerFactory.getLogger(this.getClass());
@Autowired
private JurisdictionMapper jurisdictionMapper;
private List<Jurisdiction> jurisdictions;
private void loadResource() {
this.jurisdictions = jurisdictionMapper.selectAllPermission();
}
@Override
public Collection<ConfigAttribute> getAttributes(Object object) throws IllegalArgumentException {
if (jurisdictions == null) this.loadResource();
HttpServletRequest request = ((FilterInvocation) object).getRequest();
Set<ConfigAttribute> allConfigAttribute = new HashSet<>();
AntPathRequestMatcher matcher;
for (Jurisdiction jurisdiction : jurisdictions) {
//使用AntPathRequestMatcher比较可让url支持ant风格,例如/user/*/a
//*匹配一个或多个字符,**匹配任意字符或目录
matcher = new AntPathRequestMatcher(jurisdiction.getUrl(), jurisdiction.getMethod());
if (matcher.matches(request)) {
ConfigAttribute configAttribute = new MyConfigAttribute(request,new MyGrantedAuthority(jurisdiction.getMethod(),jurisdiction.getUrl()));
allConfigAttribute.add(configAttribute);
//这里是获取到一个权限就返回,根据校验规则也可获取多个然后返回
return allConfigAttribute;
}
}
//未匹配到,说明无需权限验证
return null;
}
@Override
public Collection<ConfigAttribute> getAllConfigAttributes() {
return null;
}
@Override
public boolean supports(Class<?> clazz) {
return FilterInvocation.class.isAssignableFrom(clazz);
}
}
二、 编写 MyAccessDecisionManager 类
实现 AccessDecisionManager 接口以实现权限判断,直接 return 说明验证通过,如不通过需要抛出对应错误,代码如下:
@Component
public class MyAccessDecisionManager implements AccessDecisionManager{
private Logger log = LoggerFactory.getLogger(this.getClass());
@Override
public void decide(Authentication authentication, Object object, Collection<ConfigAttribute> configAttributes)
throws AccessDeniedException, InsufficientAuthenticationException {
//无需验证放行
if(configAttributes==null || configAttributes.size()==0)
return;
if(!authentication.isAuthenticated()){
throw new InsufficientAuthenticationException("未登录");
}
Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();
for(ConfigAttribute attribute : configAttributes){
MyConfigAttribute urlConfigAttribute = (MyConfigAttribute)attribute;
for(GrantedAuthority authority: authorities){
MyGrantedAuthority myGrantedAuthority = (MyGrantedAuthority)authority;
if(urlConfigAttribute.getMyGrantedAuthority().equals(myGrantedAuthority))
return;
}
}
throw new AccessDeniedException("无权限");
}
@Override
public boolean supports(ConfigAttribute attribute) {
return true;
}
@Override
public boolean supports(Class<?> clazz) {
return true;
}
}
三、 编写 MyFilterSecurityInterceptor 类
该类继承 AbstractSecurityInterceptor 类,实现 Filter 接口,代码如下:
@Component
public class MyFilterSecurityInterceptor extends AbstractSecurityInterceptor implements Filter {
//注入上面编写的两个类
@Autowired
private MySecurityMetadataSource mySecurityMetadataSource;
@Autowired
public void setMyAccessDecisionManager(MyAccessDecisionManager myAccessDecisionManager) {
super.setAccessDecisionManager(myAccessDecisionManager);
}
@Override
public void init(FilterConfig arg0) throws ServletException {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
FilterInvocation fi = new FilterInvocation(request, response, chain);
invoke(fi);
}
public void invoke(FilterInvocation fi) throws IOException, ServletException {
//这里进行权限验证
InterceptorStatusToken token = super.beforeInvocation(fi);
try {
fi.getChain().doFilter(fi.getRequest(), fi.getResponse());
} finally {
super.afterInvocation(token, null);
}
}
@Override
public void destroy() {
}
@Override
public Class<?> getSecureObjectClass() {
return FilterInvocation.class;
}
@Override
public SecurityMetadataSource obtainSecurityMetadataSource() {
return this.mySecurityMetadataSource;
}
}
四、 加入到 security 的过滤器链中
.addFilterBefore(urlFilterSecurityInterceptor,FilterSecurityInterceptor.class)
完成
本篇原创发布于:https://www.tapme.top/blog/detail/2018-08-22-10-38
springboot+security整合(3)自定义鉴权的更多相关文章
- springboot+security整合(2)自定义校验
说明 springboot 版本 2.0.3源码地址:点击跳转 系列 springboot+security 整合(1) springboot+security 整合(2) springboot+se ...
- SpringBoot整合SpringSecurityOauth2实现鉴权-动态权限
写在前面 思考:为什么需要鉴权呢? 系统开发好上线后,API接口会暴露在互联网上会存在一定的安全风险,例如:爬虫.恶意访问等.因此,我们需要对非开放API接口进行用户鉴权,鉴权通过之后再允许调用. 准 ...
- springboot+security整合(1)
说明 springboot 版本 2.0.3源码地址:点击跳转 系列 springboot+security 整合(1) springboot+security 整合(2) springboot+se ...
- Shiro(4)默认鉴权与自定义鉴权
=========默认鉴权======== 过滤链中定义: <!-- 过滤链定义 --> <property name="filterChainDefinitions&qu ...
- Spring Cloud注册中心Eureka设置访问权限并自定义鉴权页面
原文:https://blog.csdn.net/a823007573/article/details/88971496 使用Spring Security实现鉴权 1. 导入Spring Secur ...
- 使用SpringSecurity Oauth2.0实现自定义鉴权中心
Oauth2.0是什么不在赘述,本文主要介绍如何使用SpringSecurity Oauth2.0实现自定义的用户校验 1.鉴权中心服务 首先,列举一下我们需要用到的依赖,本文采用的是数据库保存用户信 ...
- 「快学springboot」集成Spring Security实现鉴权功能
Spring Security介绍 Spring Security是Spring全家桶中的处理身份和权限问题的一员.Spring Security可以根据使用者的需要定制相关的角色身份和身份所具有的权 ...
- Spring Security 接口认证鉴权入门实践指南
目录 前言 SpringBoot 示例 SpringBoot pom.xml SpringBoot application.yml SpringBoot IndexController SpringB ...
- springboot oauth 鉴权之——授权码authorization_code鉴权
近期一直在研究鉴权方面的各种案例,这几天有空,写一波总结及经验. 第一步:什么是 OAuth鉴权 OAuth2是工业标准的授权协议.OAuth2取代了在2006创建的原始OAuthTM协议所做的工作. ...
随机推荐
- Redis配置讲解及实战
前言 Redis是一个开源的内存k-v数据库,同时也可用作缓存,消息队列.支持多种数据类型,如字符串,列表,字典,集合,有序集合. 演示环境 $ uname -a Darwin Darwin Kern ...
- mysql事务回滚机制概述
应用场景: 银行取钱,从ATM机取钱,分为以下几个步骤 1 登陆ATM机,输入密码: 2 连接数据库,验证密码: 3 验证成功,获得用户信息,比如存款余额等: 4 用 ...
- ngxtop安装和使用
监控nginx的请求信息,总共收到了多少个请求,有哪些成功的,有哪些失败的 ngxtop安装 1.安装python-pip 1) yum install epel-release 出现如下错误:No ...
- 026_如何在MAC下输入主要国家货币符号?
由于出国旅游啥的经常会记录一些东西,不避免的会遇到各种货币符号 一. 人民币: ¥(sogo输入法切换到中文模式,然后"shift键 + 4"即可) 美元: $(sogo输入法切换 ...
- 纯CSS样式实现数字加减按钮的最佳方案
前言: 对于数字加减按钮的实现,以前用过不少方案,诸如: 1.使用背景图片——这种效果比较好,缺点是样式控制有点复杂了,还需要使用图片: 2.直接使用“+”“-”——这种方法简单粗暴,最容易实现,缺点 ...
- 【Git】The authenticity of host '192.168.1.1 (192.168.1.1)' can't be established.
背景,在服务器用www用户身份 执行拉取命令报错 sudo -u www git pull 原因分析: 在新生成密钥之后,在.ssh文件夹中少了known_hosts文件 解决办法: Are you ...
- [LeetCode] 750. Number Of Corner Rectangles 边角矩形的数量
Given a grid where each entry is only 0 or 1, find the number of corner rectangles. A corner rectang ...
- 自定义电脑IP地址
一台电脑有了ip地址才能上网,ip就是电脑的标识,在互联网中就是其中的一份子. 默认情况下电脑会自动获取IP地址,当无法自动获取或与网络IP地址相冲突时,就要自行设置电脑静态IP地址. 如下图步骤:
- spring中最重要的一些Aware接口
附上关于这节的spring官方文档: ApplicationContextAware and BeanNameAware aware接口在spring中无处不在,它是用来感知spring的ioc co ...
- Java设计模式--代理模式+动态代理+CGLib代理
静态代理 抽象主题角色:声明真实主题和代理主题的共同接口. 代理主题角色:代理主题内部含有对真实主题的引用,从而在任何时候操作真实主题对象:代理主题提供一个与真实主题相同的接口,以便在任何时候都可以代 ...