为什么80%的码农都做不了架构师?>>>   

本文就来介绍一下如何使用SwitchUserFilter进行账户切换

filter顺序

spring security内置的各种filter:

Alias Filter Class Namespace Element or Attribute
CHANNEL_FILTER ChannelProcessingFilter http/intercept-url@requires-channel
SECURITY_CONTEXT_FILTER SecurityContextPersistenceFilter http
CONCURRENT_SESSION_FILTER ConcurrentSessionFilter session-management/concurrency-control
HEADERS_FILTER HeaderWriterFilter http/headers
CSRF_FILTER CsrfFilter http/csrf
LOGOUT_FILTER LogoutFilter http/logout
X509_FILTER X509AuthenticationFilter http/x509
PRE_AUTH_FILTER AbstractPreAuthenticatedProcessingFilter Subclasses N/A
CAS_FILTER CasAuthenticationFilter N/A
FORM_LOGIN_FILTER UsernamePasswordAuthenticationFilter http/form-login
BASIC_AUTH_FILTER BasicAuthenticationFilter http/http-basic
SERVLET_API_SUPPORT_FILTER SecurityContextHolderAwareRequestFilter http/@servlet-api-provision
JAAS_API_SUPPORT_FILTER JaasApiIntegrationFilter http/@jaas-api-provision
REMEMBER_ME_FILTER RememberMeAuthenticationFilter http/remember-me
ANONYMOUS_FILTER AnonymousAuthenticationFilter http/anonymous
SESSION_MANAGEMENT_FILTER SessionManagementFilter session-management
EXCEPTION_TRANSLATION_FILTER ExceptionTranslationFilter http
FILTER_SECURITY_INTERCEPTOR FilterSecurityInterceptor http
SWITCH_USER_FILTER SwitchUserFilter N/A

可以看到SwitchUserFilter是spring security提供的filter里头order顺序在最后的一个。

前面讲到了FilterSecurityInterceptor主要用来进行鉴权处理,而SwitchUserFilter是用来做账户切换的,把它放在FilterSecurityInterceptor之后,是要求对切换用户的功能进行鉴权,否则任何人都可以随意切换用户,那就安全故障了。

config

@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true,jsr250Enabled = true,prePostEnabled = true
)
public class SecurityConfig extends WebSecurityConfigurerAdapter {@Beanpublic SwitchUserFilter switchUserFilter(UserDetailsService userDetailsService) throws Exception {SwitchUserFilter switchUserFilter = new SwitchUserFilter();switchUserFilter.setUserDetailsService(userDetailsService);switchUserFilter.setTargetUrl("/session");return switchUserFilter;}@Overrideprotected void configure(HttpSecurity http) throws Exception {//Each <http> namespace block always creates an SecurityContextPersistenceFilter, an ExceptionTranslationFilter and a FilterSecurityInterceptor. These are fixed and cannot be replaced with alternatives.http.addFilterAfter(switchUserFilter(userDetailsService()),FilterSecurityInterceptor.class).exceptionHandling().authenticationEntryPoint(new UnauthorizedEntryPoint()).and().csrf().disable().authorizeRequests().antMatchers("/login","/css/**", "/js/**","/fonts/**").permitAll().antMatchers("/session").authenticated().antMatchers("/login/impersonate").hasAuthority("ROLE_ADMIN").antMatchers("/logout/impersonate").hasAuthority(SwitchUserFilter.ROLE_PREVIOUS_ADMINISTRATOR).and().formLogin().permitAll().and().logout().deleteCookies("JSESSIONID").permitAll();}@Bean@Overrideprotected UserDetailsService userDetailsService(){InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();manager.createUser(User.withUsername("demoUser1").password("123456").authorities("ROLE_USER","read_x").build());manager.createUser(User.withUsername("admin").password("123456").authorities("ROLE_ADMIN").build());return manager;}
}

SwitchUserFilter默认的切换账号的url为/login/impersonate,默认注销切换账号的url为/logout/impersonate,默认的账号参数为username

使用

上面的配置为了方便验证,把切换完用户的targetUrl设置为/session,其代码如下

@RestController
@RequestMapping("/session")
public class SessionController {@GetMapping("")public Object getCurrentUser(){return SecurityContextHolder.getContext().getAuthentication();}
}

首先用普通用户登录,访问http://localhost:8080/login/impersonate?username=admin,发现返回403

注销,使用管理员登录,访问http://localhost:8080/login/impersonate?username=demoUser1,发现成功并跳转到session

{"authorities": [{"authority": "ROLE_USER"},{"authority": "read_x"},{"source": {"authorities": [{"authority": "ROLE_ADMIN"}],"details": {"remoteAddress": "0:0:0:0:0:0:0:1","sessionId": null},"authenticated": true,"principal": {"password": null,"username": "admin","authorities": [{"authority": "ROLE_ADMIN"}],"accountNonExpired": true,"accountNonLocked": true,"credentialsNonExpired": true,"enabled": true},"credentials": null,"name": "admin"},"authority": "ROLE_PREVIOUS_ADMINISTRATOR"}],"details": {"remoteAddress": "0:0:0:0:0:0:0:1","sessionId": "1BF3D6F40A6F488EFD3ABE8F80E52872"},"authenticated": true,"principal": {"password": "123456","username": "demoUser1","authorities": [{"authority": "ROLE_USER"},{"authority": "read_x"}],"accountNonExpired": true,"accountNonLocked": true,"credentialsNonExpired": true,"enabled": true},"credentials": "123456","name": "demoUser1"
}

可以发现有成功切换

之后再切换回来 http://localhost:8080/logout/impersonate?username=demoUser1

{"authorities": [{"authority": "ROLE_ADMIN"}],"details": {"remoteAddress": "0:0:0:0:0:0:0:1","sessionId": null},"authenticated": true,"principal": {"password": null,"username": "admin","authorities": [{"authority": "ROLE_ADMIN"}],"accountNonExpired": true,"accountNonLocked": true,"credentialsNonExpired": true,"enabled": true},"credentials": null,"name": "admin"
}

可以发现切换回来了,是不是非常神奇,太强大了,以后线上排查问题之类的,非常方便,爽歪歪了简直

  • 异常情况 如果你切换了不存在的用户,则报
This application has no explicit mapping for /error, so you are seeing this as a fallback.Sat Dec 16 14:36:28 CST 2017
There was an unexpected error (type=Unauthorized, status=401).
Authentication Failed: demoUser2

小结

SwitchUserFilter是个强大的filter,非常方便测试环境进行调试、测试,甚至可以用来进行上线问题排查。

转载于:https://my.oschina.net/go4it/blog/1591720

聊聊SwitchUserFilter的使用相关推荐

  1. 面向对象设计原则_聊聊面向对象的6大设计原则

    程序员都知道编程有 3 大类:面向过程.面向对象.面向函数.面向对象是被讨论的最多的,个人认为,这是因为 Java 之类的编程语言有强大的用户基础,本质还是因为比较符合人的直觉. 说到面向对象,大家可 ...

  2. python邮件发送哪个好_最全总结!聊聊 Python 发送邮件的几种方式

    1. 前言 邮件,作为最正式规范的沟通方式,在日常办公过程中经常被用到 我们都知道 Python内置了对 SMTP 的支持,可以发送纯文本.富文本.HTML 等格式的邮件 本文将聊聊利用 Python ...

  3. 今天聊聊分布式锁 No.86

    好了切入正题,一直在工作中会聊到很多锁的问题,今天跟大家一起闲聊一下,究竟什么是锁,为什么需要锁,以及分布式的情况下,怎么设计和实现锁. 什么是锁? 明·魏禧<大铁椎传>上是这样解释的: ...

  4. 聊聊找工作中的项目经验问题(推荐系统和智能问答)

    在求职过程中有这么一句话叫做"金九银十",也就是说,很多时候,求职的黄金时期就是在九月份和十月份,这两个月份中企业需求是最多的,求职的成功率也是最高的.但是随着AI方面的人才越来越 ...

  5. 聊聊Service Mesh:linkerd

    [编者的话]随着企业逐渐将传统的单体应用向微服务或云原生应用的转变,虽然微服务或者云原生应用能给企业带来更多的好处,但也会带来一些具有挑战的问题,如怎么管理从单体应用转向微服务所带来的服务间通讯的复杂 ...

  6. 庖丁解牛迭代器,聊聊那些藏在幕后的秘密

    0x00 前言 \\ 在我之前的一篇博客<细说C#:不是"栈类型"的值类型,从生命周期聊存储位置>的最后,我以总结和后记的方式涉及到一部分迭代器的知识.但是觉得还是不够 ...

  7. 聊聊Unsafe的一些使用技巧

    记得初学 Java 那会,刚学完语法基础,就接触到了反射这个 Java 提供的特性,尽管在现在看来,这是非常基础的知识点,但那时候无疑是兴奋的,瞬间觉得自己脱离了"Java 初学者" ...

  8. 聊聊 TCP 长连接和心跳那些事

    1 前言 可能很多 Java 程序员对 TCP 的理解只有一个三次握手,四次挥手的认识,我觉得这样的原因主要在于 TCP 协议本身稍微有点抽象(相比较于应用层的 HTTP 协议):其次,非框架开发者不 ...

  9. 聊聊算法在面试中的地位

    前段时间,有一位好友找到我,向我打听阿里社招笔试是否看重算法题的考察,我给予了肯定的答复.他表现的有些沮丧,表示自己工程底子很扎实,框架源码也研究地很透彻,唯独算法能力不行,leetcode 上的简单 ...

最新文章

  1. [c#]解决方案:需要“jquery”ScriptResourceMapping。请添加一个名为 jquery (区分大小写)的 ScriptResourceMapping。
  2. 你连原理都还没弄明白?java文档注释快捷键idea
  3. 如何实施异构服务器的负载均衡及过载保护?
  4. gen already exists but is not a source folder
  5. 在 .NET 中加载椭圆曲线 (EC) 密钥
  6. C++王者之路 | C++的sizeof 与C语言的sizeof
  7. python联科_联科集团携手阿里云发布科研混合云平台 共建科研教育新生态
  8. 【正交幅度调制 QAM】
  9. vue-router 源码:实现一个简单的 vue-router
  10. Rider+EmmyLua lua代码高亮设置
  11. 使用css画出一条虚线
  12. xcode5 自定义模板
  13. 做事的常识 书籍梗概 小仓广
  14. 【前端】性能优化 - WebP
  15. c语言0和1二进制,二进制0和1代表什么
  16. css -- 为什么:last-child 无效?
  17. 华三服务器管理口地址_h3c 的交换机怎样设置管理地址?
  18. 2018年上海交通大学数学建模竞赛暑期夏令营讲课课件(完整版)
  19. Qt之实现3D纹理渲染自由旋转空间立方体
  20. Intellij IDEA如何在一个窗口同时打开多个Maven项目

热门文章

  1. AI 开发指南:机器学习产品是什么?
  2. 挡不住的AI成熟趋势
  3. 流行的14个机器学习编程语言框架和工具
  4. 图神经网络(GNN)系列
  5. 人工智能项目的六投三不投
  6. 2019年人工智能的最大趋势和期望
  7. 科普丨莫拉维克悖论(人工智能中最重要的发现之一)
  8. 就业丨得益于AI,这五个行业岗位需求将呈现显著增长趋势
  9. MIT新研究:过去80年,算法效率提升到底有多快?
  10. 深度强化学习在智能城市领域应用介绍