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 ...
随机推荐
- kettle下载地址
kettle 4.4和4.2 版本是好的,版本6.6和8.2 版本有bug Kettle下载和安装: 1.官网各个版本下载地址:https://sourceforge.net/projects/pen ...
- python的logging的配置
在python项目中,开发环境是windows环境,发布环境是linux系统. import logging import logging.handlers import platform impor ...
- 盒模型中padding、border、margin的区别
在CSS中,规定了一种基本设计模型——盒模型(也叫框模型),如图所示: 其中包含了四部分内容:element/元素(即图中文字).padding/内边框(图中两个红色边框之间白色部分).border/ ...
- MySQL密码正确却无法本地登录,ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: YES)
MySQL密码正确却无法本地登录 报错如下: ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password ...
- Fiddler 抓包工具详解
Fiddler是一个蛮好用的抓包工具,可以将网络传输发送与接受的数据包进行截获.重发.编辑.转存等操作.也可以用来检测网络安全.反正好处多多,举之不尽呀!当年学习的时候也蛮费劲,一些蛮实用隐藏的小功能 ...
- 使用Harbor搭建Docker私有仓库
ip:192.168.0.145 环境设置 防火墙,selinux等,可以使用本章开头的那个shell脚本 其他主机的hosts文件也都添加上 ip hub.aaa.com windows系统的hos ...
- 安装 node.js npm,cnpm
参考:https://blog.csdn.net/suiyuehuimou/article/details/74143436 https://www.liaoxuefeng.com/wiki/0014 ...
- MongoDB查询操作 返回指定字段(C#官方驱动)
首先,MongoDB中返回指定的字段的查询方法如下: db.person.find({Name:"小丑"},{Age:1,Sex:1}) 该语句表示:查询person表中name为 ...
- Qt之QTableWidget
学习QTableWidget就要首先看看QTableView控件(控件也是有”家世“的!就像研究人一样一样的),因为QTableWidget继承于类QTableView. 两者主要区别是QTableV ...
- netty 自定义协议
netty 自定义协议 netty 是什么呢? 相信很多人都被人问过这个问题.如果快速准确的回复这个问题呢?网络编程框架,netty可以让你快速和简单的开发出一个高性能的网络应用.netty是一个网络 ...