博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
聊聊SwitchUserFilter的使用
阅读量:5880 次
发布时间:2019-06-19

本文共 6207 字,大约阅读时间需要 20 分钟。

本文就来介绍一下如何使用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 {    @Bean    public SwitchUserFilter switchUserFilter(UserDetailsService userDetailsService) throws Exception {        SwitchUserFilter switchUserFilter = new SwitchUserFilter();        switchUserFilter.setUserDetailsService(userDetailsService);        switchUserFilter.setTargetUrl("/session");        return switchUserFilter;    }    @Override    protected void configure(HttpSecurity http) throws Exception {        //Each 
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 @Override protected 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();    }}

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

注销,使用管理员登录,访问: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"}
可以发现有成功切换

之后再切换回来

: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 2017There was an unexpected error (type=Unauthorized, status=401).Authentication Failed: demoUser2

小结

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

转载地址:http://njcix.baihongyu.com/

你可能感兴趣的文章
js - object.assign 以及浅、深拷贝
查看>>
python mysql Connect Pool mysql连接池 (201
查看>>
Boost在vs2010下的配置
查看>>
一起谈.NET技术,ASP.NET伪静态的实现及伪静态的意义
查看>>
20款绝佳的HTML5应用程序示例
查看>>
string::c_str()、string::c_data()及string与char *的正确转换
查看>>
11G数据的hive初测试
查看>>
如何使用Core Text计算一段文本绘制在屏幕上之后的高度
查看>>
==和equals区别
查看>>
2010技术应用计划
查看>>
XML 节点类型
查看>>
驯服 Tiger: 并发集合 超越 Map、Collection、List 和 Set
查看>>
Winform开发框架之权限管理系统改进的经验总结(3)-系统登录黑白名单的实现...
查看>>
Template Method Design Pattern in Java
查看>>
MVC输出字符串常用四个方式
查看>>
LeetCode – LRU Cache (Java)
查看>>
JavaScript高级程序设计--对象,数组(栈方法,队列方法,重排序方法,迭代方法)...
查看>>
【转】 学习ios(必看经典)牛人40天精通iOS开发的学习方法【2015.12.2
查看>>
在 ASP.NET MVC 中使用异步控制器
查看>>
SQL语句的执行过程
查看>>