转载于:https://www.jianshu.com/p/6b8fb59b614b

项目简介

基于Spring Cloud 的项目,Spring Cloud是在Spring Boot上搭建的所以按照Spring Boot的方式来写

Spring Security 配置

继承 WebSecurityConfigurerAdapter ,重写configure(HttpSecurity http)配置相关权限以及重写拦截器

  1. http.authorizeRequests()
  2. .antMatchers("/auth/**").permitAll()
  3. .anyRequest().authenticated().and()
  4. //证书 认证 自动登陆
  5. .addFilterBefore(authTokenFilter, UsernamePasswordAuthenticationFilter.class)
  6. //登陆以及权限控制Filter
  7. ......
  8. ;

自定义UsernamePasswordAuthenticationFilter

自定义 UsernamePasswordAuthenticationFilter 实现自动登陆
创建Authentication 模拟登陆

  1. Authentication authentication = new UsernamePasswordAuthenticationToken(auth, token);
  2. SecurityContextHolder.getContext().setAuthentication(authentication);;

自定义FilterSecurityInterceptor

Spring Security 是通过这个过滤器来实现 Http资源安全过滤的。

获取资源权限

FilterSecurityInterceptor继承自 AbstractSecurityInterceptor ,源码中的其中beforeInvocation方法的一段代码是:

  1. Collection<ConfigAttribute> attributes = this.obtainSecurityMetadataSource()
  2. .getAttributes(object);
这个方法是来获取资源权限 ,可以重写SecurityMetadataSource obtainSecurityMetadataSource(){}方法来实现,传入一个FilterInvocation对象,返回一个Collection<ConfigAttribute>对象。
这个对象中可以获取到request, response等内置对象,可以通过一下代码来匹配
  1. RequestMatcher requestMatcher = new AntPathRequestMatcher("/manager/**");
  2. if(requestMatcher.matches(request)){
  3. return RESOURCE
  4. }
  5.  
  6. ConfigAttribute 可以通过new SecurityConfig((String)input) 来创建

编写认证提供者

重写 AuthenticationManager 实现,用户登陆可以放这里面

  1. Authentication authenticate(Authentication authentication)
  2. throws AuthenticationException;

用来生成Authentication, 原始的够用的话直接注入设置就好。

用户是否有获取资源权限

AbstructSecurityIntercepter 中的一下方法来判断用户权限是否可以拥有该资源

  1. this.accessDecisionManager.decide(authenticated, object, attributes);

为了达到自定义控制的目的,我们需要实现AccessDecisionManager接口,来重写这个方法,如果判断不通过 decide方法可以抛出AccessDeniedException,来阻止用户访问

  1. /**
  2. * 判断用户是否有访问资源权限
  3. * @param authentication 用户Auth
  4. * @param object FilterInvocation对象
  5. * @param configAttributes 资源所需权限
  6. * @throws AccessDeniedException 无权限Exception
  7. * @throws InsufficientAuthenticationException
  8. */
  9. public void decide(Authentication authentication, Object object,
  10. Collection<ConfigAttribute> configAttributes)
  11. throws AccessDeniedException, InsufficientAuthenticationException {
  12. if(access){
  13. //允许通过
  14. return;
  15. }
  16. //不允许角色访问
  17. throw new AccessDeniedException("NO ALLOW");
  18. }

JAVA 源码片

WebSecurityConfig

  1. @Configuration
  2. public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
  3. @Autowired
  4. private AuthTokenFilter authTokenFilter;
  5. @Autowired
  6. private ApiPermissionSecurityFilter securityFilter;
  7. protected void configure(HttpSecurity http) throws Exception {
  8. http.authorizeRequests()
  9. .antMatchers("/auth/**").permitAll()
  10. .anyRequest().authenticated().and()
  11. //证书 认证 自动登陆
  12. .addFilterBefore(authTokenFilter, UsernamePasswordAuthenticationFilter.class)
  13. //登陆以及权限控制Filter
  14. .addFilterBefore(securityFilter, FilterSecurityInterceptor.class)
  15. .csrf().disable()
  16. //基于Token 不需要Session
  17. .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
  18. ;
  19. }
  20. }

AuthTokenFilter (自定义UsernamePasswordAuthenticationFilter)

  1. @Component
  2. public class AuthTokenFilter extends OncePerRequestFilter {
  3. @Override
  4. protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
  5. String auth = request.getHeader("Authorization");
  6. //用户登陆,暂不设置权限
  7. Token token = new Token(auth, null);
  8. Authentication authentication = new UsernamePasswordAuthenticationToken(auth, token);
  9. SecurityContextHolder.getContext().setAuthentication(authentication);
  10. filterChain.doFilter(request, response);
  11. }
  12. }

ApiPermissionSecurityFilter

  1. @Component
  2. public class ApiPermissionSecurityFilter extends AbstractSecurityInterceptor implements Filter {
  3. @Autowired
  4. private ApiInvocationSecurityMetadataSourceService apiInvocationSecurityMetadataSourceService;
  5. @Autowired
  6. private ApiAccessDecisionManager apiAccessDecisionManager;
  7. @Autowired
  8. private AuthenticationManager authenticationManager;
  9.  
  10. @PostConstruct
  11. public void init(){
  12. super.setAuthenticationManager(authenticationManager);
  13. super.setAccessDecisionManager(apiAccessDecisionManager);
  14. }
  15.  
  16. public void doFilter( ServletRequest request, ServletResponse response, FilterChain chain)
  17. throws IOException, ServletException{
  18. FilterInvocation fi = new FilterInvocation( request, response, chain );
  19. invoke(fi);
  20. }
  21.  
  22. public Class<? extends Object> getSecureObjectClass(){
  23. return FilterInvocation.class;
  24. }
  25.  
  26. public void invoke( FilterInvocation fi ) throws IOException, ServletException{
  27. InterceptorStatusToken token = super.beforeInvocation(fi);
  28. try{
  29. fi.getChain().doFilter(fi.getRequest(), fi.getResponse());
  30. }finally{
  31. super.afterInvocation(token, null);
  32. }
  33. }
  34.  
  35. @Override
  36. public SecurityMetadataSource obtainSecurityMetadataSource(){
  37. return this.apiInvocationSecurityMetadataSourceService;
  38. }
  39. public void destroy(){
  40. }
  41. public void init( FilterConfig filterconfig ) throws ServletException{
  42. }
  43. }

ApiInvocationSecurityMetadataSourceService

  1. /**
  2. * 资源-权限控制对象
  3. * Created by liang on 2017/3/17.
  4. */
  5. @Component
  6. public class ApiInvocationSecurityMetadataSourceService implements
  7. FilterInvocationSecurityMetadataSource {
  8. //缓存 英文名-权限
  9. private static LoadingCache<String, Collection<ConfigAttribute>> permitMap = null;
  10. //缓存 英文名-ODCINFO信息对象
  11. private static LoadingCache<String, OdcInfo> odcInfoMap = null;
  12. @PostConstruct
  13. private void init() {
  14. //资源启动时初始化 资源和角色权限
  15. //缓存 英文名-权限 初始化
  16. //缓存 英文名-ODCINFO
  17. }
  18.  
  19. @Override
  20. public Collection<ConfigAttribute> getAttributes(Object object) throws IllegalArgumentException {
  21. FilterInvocation filterInvocation = (FilterInvocation) object;
  22. //TODO 干你想干事情,下面是获取路径所具有的资源
  23. return permitMap.get(getHttpRequest().getRequestURI());
  24. }
  25.  
  26. @Override
  27. public Collection<ConfigAttribute> getAllConfigAttributes() {
  28. return new ArrayList<ConfigAttribute>();
  29. }
  30.  
  31. @Override
  32. public boolean supports(Class<?> aClass) {
  33. //很重要,不然不起作用
  34. return true;
  35. }
  36. }

ApiAccessDecisionManager

  1. @Component
  2. public class ApiAccessDecisionManager implements AccessDecisionManager {
  3. /**
  4. * 判断用户是否有访问资源权限
  5. * @param authentication 用户Auth
  6. * @param object FilterInvocation对象
  7. * @param configAttributes 资源所需权限
  8. * @throws AccessDeniedException 无权限Exception
  9. */
  10. public void decide(Authentication authentication, Object object,
  11. Collection<ConfigAttribute> configAttributes)
  12. throws AccessDeniedException {
  13. if(access){
  14. //允许通过
  15. return;
  16. }
  17. //不允许角色访问
  18. throw new AccessDeniedException("NO ALLOW");
  19. }
  20.  
  21. public boolean supports( ConfigAttribute attribute ){
  22. return true;
  23. }
  24.  
  25. public boolean supports(Class<?> clazz){
  26. return true;
  27. }
  28. }

作者:libertinus
链接:https://www.jianshu.com/p/6b8fb59b614b
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

Spring Security 自定义 登陆 权限验证的更多相关文章

  1. (二)spring Security 自定义登录页面与校验用户

    文章目录 配置 security 配置下 MVC 自定义登录页面 自定义一个登陆成功欢迎页面 效果图 小结: 使用 Spring Boot 的快速创建项目功能,勾选上本篇博客需要的功能:web,sec ...

  2. 登陆模块,这个是很重要的模块,有shiro和spring security专门的权限认证框架

    登陆模块,这个是很重要的模块,有shiro和spring security专门的权限认证框架

  3. Struts2 自定义拦截器实例—登陆权限验证

    实现一个登陆权限验证的功能 message.jsp: <body> message:${message } </body> login.jsp: <% request.g ...

  4. Spring Security 自定义登录认证(二)

    一.前言 本篇文章将讲述Spring Security自定义登录认证校验用户名.密码,自定义密码加密方式,以及在前后端分离的情况下认证失败或成功处理返回json格式数据 温馨小提示:Spring Se ...

  5. Spring Security 动态url权限控制(三)

    一.前言 本篇文章将讲述Spring Security 动态分配url权限,未登录权限控制,登录过后根据登录用户角色授予访问url权限 基本环境 spring-boot 2.1.8 mybatis-p ...

  6. spring security自定义指南

    序 本文主要研究一下几种自定义spring security的方式 主要方式 自定义UserDetailsService 自定义passwordEncoder 自定义filter 自定义Authent ...

  7. Spring Security实现RBAC权限管理

    Spring Security实现RBAC权限管理 一.简介 在企业应用中,认证和授权是非常重要的一部分内容,业界最出名的两个框架就是大名鼎鼎的 Shiro和Spring Security.由于Spr ...

  8. 解决Spring Security自定义filter重复执行问题

    今天做项目的时候,发现每次拦截器日志都会打两遍,很纳闷,怀疑是Filter被执行了两遍.结果debug之后发现还真是!记录一下这个神奇的BUG! 问题描述 项目中使用的是Spring-security ...

  9. Spring Security 自定义登录页面

    SpringMVC + Spring Security,自定义登录页面登录验证 学习参考:http://www.mkyong.com/spring-security/spring-security-f ...

随机推荐

  1. python3连接oracle数据库

    声明:python,cx_Oracle和instantclient的版本应一致 我这里使用的版本是python3.6 64位 ,cx_Oracle-5.3-11g.win-amd64-py3.6-2和 ...

  2. Python 命名规范总结

    Python推荐命名规范: 模块名和包名采用小写字母并且以下划线分隔单词的形式: 如:browser_driver 类名或异常名采用每个单词首字母大写的方式: 如:BasePage, Keyboard ...

  3. [翻译] 深入浅出Go语言调度器:第一部分 - 系统调度器

    目录 译者序 序 介绍 系统调度器 执行指令 Figure 1 Listing 1 Listing 2 Listing 3 线程状态 任务侧重 上下文切换 少即是多 寻找平衡 缓存行 Figure 2 ...

  4. Elastic Search快速上手(4):细节补充

    模糊搜索 可以进行模糊搜索: GET job/type1/_search { "query":{ "fuzzy":{ "title":{ & ...

  5. NIO总结-----Buffer

    Java NIO中的Buffer用于和NIO通道进行交互.如你所知,数据是从通道读入缓冲区,从缓冲区写入到通道中的. 缓冲区本质上是一块可以写入数据,然后可以从中读取数据的内存.这块内存被包装成NIO ...

  6. 怎样写一个 "Hello, World!"

    第一步: 打开浏览器, 按 F12 键或 Ctrl + Shift + J.   注意:  1. 打开的这个界面是浏览器的开发者工具界面. 2. 顶部有许多Tab栏, 如: Elements / Co ...

  7. svg使用

    Vue.component('XSvg', () => import('./abc-svg'))    <x-svg             icon-name="personl ...

  8. c#将电脑时间同步到网络时间

    最近遇到个项目,需要控制软件使用时间,由于电脑不联网可以修改时间,故需要联网使电脑同步网络时间 网上寻找了很多解决方案,代码如下: //Forproc_Win32.cs//对常用Win32 API函数 ...

  9. Spring切面编程Aspect之@Before和@Around用法

    查看dao层使用的sql import java.util.Arrays; import org.apache.commons.lang.ArrayUtils; import org.aspectj. ...

  10. Spring Data JPA 大纲归纳

    第一天: springdatajpa day1:orm思想和hibernate以及jpa的概述和jpa的基本操作 day2:springdatajpa的运行原理以及基本操作 day3:多表操作,复杂查 ...