说明 springboot 版本 2.0.3
源码地址:点击跳转

系列

  这篇讲解如何自定义鉴权过程,实现根据数据库查询出的 url 和 method 是否匹配当前请求的 url 和 method 来决定有没有权限。security 鉴权过程如下:

一、 重写 metadataSource 类

  1. 编写 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;
}
}
  1. 编写 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;
}
}
  1. 编写 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)自定义鉴权的更多相关文章

  1. springboot+security整合(2)自定义校验

    说明 springboot 版本 2.0.3源码地址:点击跳转 系列 springboot+security 整合(1) springboot+security 整合(2) springboot+se ...

  2. SpringBoot整合SpringSecurityOauth2实现鉴权-动态权限

    写在前面 思考:为什么需要鉴权呢? 系统开发好上线后,API接口会暴露在互联网上会存在一定的安全风险,例如:爬虫.恶意访问等.因此,我们需要对非开放API接口进行用户鉴权,鉴权通过之后再允许调用. 准 ...

  3. springboot+security整合(1)

    说明 springboot 版本 2.0.3源码地址:点击跳转 系列 springboot+security 整合(1) springboot+security 整合(2) springboot+se ...

  4. Shiro(4)默认鉴权与自定义鉴权

    =========默认鉴权======== 过滤链中定义: <!-- 过滤链定义 --> <property name="filterChainDefinitions&qu ...

  5. Spring Cloud注册中心Eureka设置访问权限并自定义鉴权页面

    原文:https://blog.csdn.net/a823007573/article/details/88971496 使用Spring Security实现鉴权 1. 导入Spring Secur ...

  6. 使用SpringSecurity Oauth2.0实现自定义鉴权中心

    Oauth2.0是什么不在赘述,本文主要介绍如何使用SpringSecurity Oauth2.0实现自定义的用户校验 1.鉴权中心服务 首先,列举一下我们需要用到的依赖,本文采用的是数据库保存用户信 ...

  7. 「快学springboot」集成Spring Security实现鉴权功能

    Spring Security介绍 Spring Security是Spring全家桶中的处理身份和权限问题的一员.Spring Security可以根据使用者的需要定制相关的角色身份和身份所具有的权 ...

  8. Spring Security 接口认证鉴权入门实践指南

    目录 前言 SpringBoot 示例 SpringBoot pom.xml SpringBoot application.yml SpringBoot IndexController SpringB ...

  9. springboot oauth 鉴权之——授权码authorization_code鉴权

    近期一直在研究鉴权方面的各种案例,这几天有空,写一波总结及经验. 第一步:什么是 OAuth鉴权 OAuth2是工业标准的授权协议.OAuth2取代了在2006创建的原始OAuthTM协议所做的工作. ...

随机推荐

  1. Redis配置讲解及实战

    前言 Redis是一个开源的内存k-v数据库,同时也可用作缓存,消息队列.支持多种数据类型,如字符串,列表,字典,集合,有序集合. 演示环境 $ uname -a Darwin Darwin Kern ...

  2. mysql事务回滚机制概述

    应用场景:   银行取钱,从ATM机取钱,分为以下几个步骤       1 登陆ATM机,输入密码:    2 连接数据库,验证密码:    3 验证成功,获得用户信息,比如存款余额等:    4 用 ...

  3. ngxtop安装和使用

    监控nginx的请求信息,总共收到了多少个请求,有哪些成功的,有哪些失败的 ngxtop安装 1.安装python-pip 1) yum install epel-release 出现如下错误:No ...

  4. 026_如何在MAC下输入主要国家货币符号?

    由于出国旅游啥的经常会记录一些东西,不避免的会遇到各种货币符号 一. 人民币: ¥(sogo输入法切换到中文模式,然后"shift键 + 4"即可) 美元: $(sogo输入法切换 ...

  5. 纯CSS样式实现数字加减按钮的最佳方案

    前言: 对于数字加减按钮的实现,以前用过不少方案,诸如: 1.使用背景图片——这种效果比较好,缺点是样式控制有点复杂了,还需要使用图片: 2.直接使用“+”“-”——这种方法简单粗暴,最容易实现,缺点 ...

  6. 【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 ...

  7. [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 ...

  8. 自定义电脑IP地址

    一台电脑有了ip地址才能上网,ip就是电脑的标识,在互联网中就是其中的一份子. 默认情况下电脑会自动获取IP地址,当无法自动获取或与网络IP地址相冲突时,就要自行设置电脑静态IP地址. 如下图步骤:

  9. spring中最重要的一些Aware接口

    附上关于这节的spring官方文档: ApplicationContextAware and BeanNameAware aware接口在spring中无处不在,它是用来感知spring的ioc co ...

  10. Java设计模式--代理模式+动态代理+CGLib代理

    静态代理 抽象主题角色:声明真实主题和代理主题的共同接口. 代理主题角色:代理主题内部含有对真实主题的引用,从而在任何时候操作真实主题对象:代理主题提供一个与真实主题相同的接口,以便在任何时候都可以代 ...