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

项目简介

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

Spring Security 配置

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

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

自定义UsernamePasswordAuthenticationFilter

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

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

自定义FilterSecurityInterceptor

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

获取资源权限

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

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

编写认证提供者

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

Authentication authenticate(Authentication authentication)
throws AuthenticationException;

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

用户是否有获取资源权限

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

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

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

/**
* 判断用户是否有访问资源权限
* @param authentication 用户Auth
* @param object FilterInvocation对象
* @param configAttributes 资源所需权限
* @throws AccessDeniedException 无权限Exception
* @throws InsufficientAuthenticationException
*/
public void decide(Authentication authentication, Object object,
Collection<ConfigAttribute> configAttributes)
throws AccessDeniedException, InsufficientAuthenticationException {
if(access){
//允许通过
return;
}
//不允许角色访问
throw new AccessDeniedException("NO ALLOW");
}

JAVA 源码片

WebSecurityConfig

@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private AuthTokenFilter authTokenFilter;
@Autowired
private ApiPermissionSecurityFilter securityFilter;
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/auth/**").permitAll()
.anyRequest().authenticated().and()
//证书 认证 自动登陆
.addFilterBefore(authTokenFilter, UsernamePasswordAuthenticationFilter.class)
//登陆以及权限控制Filter
.addFilterBefore(securityFilter, FilterSecurityInterceptor.class)
.csrf().disable()
//基于Token 不需要Session
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
;
}
}

AuthTokenFilter (自定义UsernamePasswordAuthenticationFilter)

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

ApiPermissionSecurityFilter

@Component
public class ApiPermissionSecurityFilter extends AbstractSecurityInterceptor implements Filter {
@Autowired
private ApiInvocationSecurityMetadataSourceService apiInvocationSecurityMetadataSourceService;
@Autowired
private ApiAccessDecisionManager apiAccessDecisionManager;
@Autowired
private AuthenticationManager authenticationManager; @PostConstruct
public void init(){
super.setAuthenticationManager(authenticationManager);
super.setAccessDecisionManager(apiAccessDecisionManager);
} public void doFilter( ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException{
FilterInvocation fi = new FilterInvocation( request, response, chain );
invoke(fi);
} public Class<? extends Object> getSecureObjectClass(){
return FilterInvocation.class;
} 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 SecurityMetadataSource obtainSecurityMetadataSource(){
return this.apiInvocationSecurityMetadataSourceService;
}
public void destroy(){
}
public void init( FilterConfig filterconfig ) throws ServletException{
}
}

ApiInvocationSecurityMetadataSourceService

/**
* 资源-权限控制对象
* Created by liang on 2017/3/17.
*/
@Component
public class ApiInvocationSecurityMetadataSourceService implements
FilterInvocationSecurityMetadataSource {
//缓存 英文名-权限
private static LoadingCache<String, Collection<ConfigAttribute>> permitMap = null;
//缓存 英文名-ODCINFO信息对象
private static LoadingCache<String, OdcInfo> odcInfoMap = null;
@PostConstruct
private void init() {
//资源启动时初始化 资源和角色权限
//缓存 英文名-权限 初始化
//缓存 英文名-ODCINFO
} @Override
public Collection<ConfigAttribute> getAttributes(Object object) throws IllegalArgumentException {
FilterInvocation filterInvocation = (FilterInvocation) object;
//TODO 干你想干事情,下面是获取路径所具有的资源
return permitMap.get(getHttpRequest().getRequestURI());
} @Override
public Collection<ConfigAttribute> getAllConfigAttributes() {
return new ArrayList<ConfigAttribute>();
} @Override
public boolean supports(Class<?> aClass) {
//很重要,不然不起作用
return true;
}
}

ApiAccessDecisionManager

@Component
public class ApiAccessDecisionManager implements AccessDecisionManager {
/**
* 判断用户是否有访问资源权限
* @param authentication 用户Auth
* @param object FilterInvocation对象
* @param configAttributes 资源所需权限
* @throws AccessDeniedException 无权限Exception
*/
public void decide(Authentication authentication, Object object,
Collection<ConfigAttribute> configAttributes)
throws AccessDeniedException {
if(access){
//允许通过
return;
}
//不允许角色访问
throw new AccessDeniedException("NO ALLOW");
} public boolean supports( ConfigAttribute attribute ){
return true;
} public boolean supports(Class<?> clazz){
return true;
}
}

作者: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. postgres csv日志和查看用户权限

    最近在使用postgres 时遇到的2个问题,顺便记录一下查到的比较好的资料. 怀疑postgres在执行SQL时报错,程序日志中有无明确异常信息.通过查看csv日志来确定是否SQL真的是执行时报错. ...

  2. Kubernetes组件-CronJob(定时任务)

    ⒈简介: Kubernetes的Job资源在创建时会立即运行pod.但是许多批处理任务需要在特定的时间运行,或者在指定的时间间隔内重复运行.在Linux和类UNIX操作系统中,这些任务通常被称为cro ...

  3. Java HttpServletRequest中getAttribute()方法和getParameter()区别

    一.ServletRequest接口 HttpServletRequest接口继承了ServletRequest接口,实现类通常代表一个实际的Http Request. Servlet容器负责创建一个 ...

  4. 关于阮一峰老师es6(第三版)中管道机制代码的理解浅析

    最近正在学习阮一峰老师的es6(第三版)教材,在学到第七章<函数的扩展>中的箭头函数嵌套时,文中提到了一个关于“管道机制”的示例,文中源代码如下: //es6(第三版)教材中的管道机制源代 ...

  5. 组合:abc三个字符的所有组合

    求所有组合也就是abc各个位是否选取的问题,第一位2中可能,第二位2种...所以一共有2^n种.用0表示不取,1表示选取,这样可以用110这样的形式表示ab.abc一共的表示形式从0到2^3-1.然后 ...

  6. 6.AOP配置与应用(xml的方式)

    xml 配置 AOP 1.将 拦截其器对象 初始化到容器中 2.<aop:config> <aop:aspect.... <aop:pointcut <aop:befor ...

  7. 1.IOC原理模拟

    Spring两大核心功能,IOC(Inverse  of  Control)  和 AOP(Aspect-Oriented-Programming) IOC原理模拟: 有这样一个beans.xml: ...

  8. GitHub新手使用篇

    如何使用GitHub 未完结 目录: ISSUE总汇总: Issue1:GitHub的注册和使用? 答:(1)注册GitHub :https://github.com/.需要填用户名.邮箱.密码,值得 ...

  9. SURF算法源代码OPENSURF分析

    SURF算法源代码分析 平台:win x64 + VS2015专业版 +opencv2.4.11 配置类似参考OPENSIFT,参考我的另一篇博客:https://www.cnblogs.com/Al ...

  10. 05_Redis_List命令

    一:Redis 列表(List) -- LinkedList Redis列表是简单的字符串列表,按照插入顺序排序.你可以添加一个元素到列表的头部(左边)或者尾部(右边):一个列表最多可以包含 232 ...