说明 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. javaagent使用指南

    今天打算写一下 Javaagent,一开始我对它的概念也比较陌生,后来在别人口中听到 字节码插桩,bTrace,Arthas后面才逐渐了解到Java还提供了这么个工具. JVM启动前静态Instrum ...

  2. GWAS Catalog数据库简介

    GWAS Catalog The NHGRI-EBI Catalog of published genome-wide association studies EBI负责维护的一个收集已发表的GWAS ...

  3. 【深入学习linux】VMware新建虚拟机教程

    新建虚拟机 1. 点击创建新的虚拟机 2.进入新建向导,选择典型安装,点击下一步 3.为什么不选择第二个选项是因为系统会默认帮助我们安装一个简单配置,这里我们需要学习配置安装所以选择第三项,然后点击下 ...

  4. C++多线程下出现内存越界问题总结

    工作中遇到这样一个问题,某个多级流水多线程的程序,在压力测试下会偶现segmentation fault11错误,错误出现在运行类函数的地方,而后排查后发现是由于多线程争抢导致类被析构后才走入判断,导 ...

  5. web服务器请求代理方式

    1 通信数据转发程序:代理.网关.隧道 代理:是一种有转发功能的应用程序,他扮演了位于服务器和客户端“中间人”的角色,接收客户端发送的请求并转发给服务器:同时也接收服务器返回的响应并转发给客户端. 使 ...

  6. meta name="location" 标签的使用

    在进行一些操作的时候,我们可能会用到这个标签来什么,地理位置,不错的网站优化标签. <meta name="location" content="province= ...

  7. LeetCode_405. Convert a Number to Hexadecimal

    405. Convert a Number to Hexadecimal Easy Given an integer, write an algorithm to convert it to hexa ...

  8. jenkins中启用tag标签

    参照里面的第9步: https://www.cnblogs.com/effortsing/p/10468840.html

  9. [LeetCode] 460. LFU Cache 最近最不常用页面置换缓存器

    Design and implement a data structure for Least Frequently Used (LFU) cache. It should support the f ...

  10. [LeetCode] 666. Path Sum IV 二叉树的路径和 IV

    If the depth of a tree is smaller than 5, then this tree can be represented by a list of three-digit ...