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 ...
随机推荐
- python3连接oracle数据库
声明:python,cx_Oracle和instantclient的版本应一致 我这里使用的版本是python3.6 64位 ,cx_Oracle-5.3-11g.win-amd64-py3.6-2和 ...
- Python 命名规范总结
Python推荐命名规范: 模块名和包名采用小写字母并且以下划线分隔单词的形式: 如:browser_driver 类名或异常名采用每个单词首字母大写的方式: 如:BasePage, Keyboard ...
- [翻译] 深入浅出Go语言调度器:第一部分 - 系统调度器
目录 译者序 序 介绍 系统调度器 执行指令 Figure 1 Listing 1 Listing 2 Listing 3 线程状态 任务侧重 上下文切换 少即是多 寻找平衡 缓存行 Figure 2 ...
- Elastic Search快速上手(4):细节补充
模糊搜索 可以进行模糊搜索: GET job/type1/_search { "query":{ "fuzzy":{ "title":{ & ...
- NIO总结-----Buffer
Java NIO中的Buffer用于和NIO通道进行交互.如你所知,数据是从通道读入缓冲区,从缓冲区写入到通道中的. 缓冲区本质上是一块可以写入数据,然后可以从中读取数据的内存.这块内存被包装成NIO ...
- 怎样写一个 "Hello, World!"
第一步: 打开浏览器, 按 F12 键或 Ctrl + Shift + J. 注意: 1. 打开的这个界面是浏览器的开发者工具界面. 2. 顶部有许多Tab栏, 如: Elements / Co ...
- svg使用
Vue.component('XSvg', () => import('./abc-svg')) <x-svg icon-name="personl ...
- c#将电脑时间同步到网络时间
最近遇到个项目,需要控制软件使用时间,由于电脑不联网可以修改时间,故需要联网使电脑同步网络时间 网上寻找了很多解决方案,代码如下: //Forproc_Win32.cs//对常用Win32 API函数 ...
- Spring切面编程Aspect之@Before和@Around用法
查看dao层使用的sql import java.util.Arrays; import org.apache.commons.lang.ArrayUtils; import org.aspectj. ...
- Spring Data JPA 大纲归纳
第一天: springdatajpa day1:orm思想和hibernate以及jpa的概述和jpa的基本操作 day2:springdatajpa的运行原理以及基本操作 day3:多表操作,复杂查 ...