Spring Security 自定义 登陆 权限验证
转载于: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 自定义 登陆 权限验证的更多相关文章
- (二)spring Security 自定义登录页面与校验用户
文章目录 配置 security 配置下 MVC 自定义登录页面 自定义一个登陆成功欢迎页面 效果图 小结: 使用 Spring Boot 的快速创建项目功能,勾选上本篇博客需要的功能:web,sec ...
- 登陆模块,这个是很重要的模块,有shiro和spring security专门的权限认证框架
登陆模块,这个是很重要的模块,有shiro和spring security专门的权限认证框架
- Struts2 自定义拦截器实例—登陆权限验证
实现一个登陆权限验证的功能 message.jsp: <body> message:${message } </body> login.jsp: <% request.g ...
- Spring Security 自定义登录认证(二)
一.前言 本篇文章将讲述Spring Security自定义登录认证校验用户名.密码,自定义密码加密方式,以及在前后端分离的情况下认证失败或成功处理返回json格式数据 温馨小提示:Spring Se ...
- Spring Security 动态url权限控制(三)
一.前言 本篇文章将讲述Spring Security 动态分配url权限,未登录权限控制,登录过后根据登录用户角色授予访问url权限 基本环境 spring-boot 2.1.8 mybatis-p ...
- spring security自定义指南
序 本文主要研究一下几种自定义spring security的方式 主要方式 自定义UserDetailsService 自定义passwordEncoder 自定义filter 自定义Authent ...
- Spring Security实现RBAC权限管理
Spring Security实现RBAC权限管理 一.简介 在企业应用中,认证和授权是非常重要的一部分内容,业界最出名的两个框架就是大名鼎鼎的 Shiro和Spring Security.由于Spr ...
- 解决Spring Security自定义filter重复执行问题
今天做项目的时候,发现每次拦截器日志都会打两遍,很纳闷,怀疑是Filter被执行了两遍.结果debug之后发现还真是!记录一下这个神奇的BUG! 问题描述 项目中使用的是Spring-security ...
- Spring Security 自定义登录页面
SpringMVC + Spring Security,自定义登录页面登录验证 学习参考:http://www.mkyong.com/spring-security/spring-security-f ...
随机推荐
- [转载]ASP.NET Core文件上传与下载(多种上传方式)
ASP.NET Core文件上传与下载(多种上传方式) 前言 前段时间项目上线,实在太忙,最近终于开始可以研究研究ASP.NET Core了. 打算写个系列,但是还没想好目录,今天先来一篇,后面在 ...
- 如何判断你的windows系统是32位还是64位?
[学习笔记] 如 何判断你的windows系统是32位还是64位? java -version时,如果没有64就是32位的.eclipse.ini中如果没有64,就是32位的.但是我们的ini文件里面 ...
- 最大流Dinic(模板)
#define IOS ios_base::sync_with_stdio(0); cin.tie(0); #include <cstdio>//sprintf islower isupp ...
- 序列化,os,sys,hashlib,collections
序列化,os,sys,hashlib,collections 1.序列化 什么是序列化?序列化的本质就是将一种数据结构(如字典,列表)等转换成一个特殊的序列(字符串或者bytes)的过程就叫做序列化. ...
- python+selenium+chrome实现自动登录百度
#python3.4+selenium3.5+chrome版本 63.0.3239.132+chrome驱动chromedriver.exe #实现自动登录百度 from selenium impor ...
- 关于greenlet的一些问题
今天测试关于协程方面的代码发现我安装了greenlet模块缺导入不进.如图: 后来找了半天才发现原来greenlet被整进了gevent包中,如下导入就可以成功: 但这个greenlet没有了swit ...
- DVWA漏洞演练平台 - 文件上传
DVWA(Damn Vulnerable Web Application)是一个用来进行安全脆弱性鉴定的PHP/MySQL Web应用,旨在为安全专业人员测试自己的专业技能和工具提供合法的环境,帮助w ...
- svg使用
Vue.component('XSvg', () => import('./abc-svg')) <x-svg icon-name="personl ...
- MVC部分视图的使用(Html.Partial/RenderPartial、Html.Action/RenderAction、RenderPage)
ASP.NET MVC 里页面往往会有许多重用的地方,可以进行封装重用. 使用部分视图有以下优点: 1. 可以简写代码. 2. 页面代码更加清晰.更好维护. 在视图里有多种方法可以 加载部分视图,包括 ...
- 【原创】编程基础之Jekins
Jenkins 2.164.2 官方:https://jenkins.io 一 简介 Build great things at any scale The leading open source a ...