摘要:序本文就來介紹一下如何使用進(jìn)行賬戶切換順序內(nèi)置的各種可以看到是提供的里頭順序在最后的一個(gè)。前面講到了主要用來進(jìn)行鑒權(quán)處理,而是用來做賬戶切換的,把它放在之后,是要求對(duì)切換用戶的功能進(jìn)行鑒權(quán),否則任何人都可以隨意切換用戶,那就安全故障了。
序
本文就來介紹一下如何使用SwitchUserFilter進(jìn)行賬戶切換
filter順序spring security內(nèi)置的各種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順序在最后的一個(gè)。config前面講到了FilterSecurityInterceptor主要用來進(jìn)行鑒權(quán)處理,而SwitchUserFilter是用來做賬戶切換的,把它放在FilterSecurityInterceptor之后,是要求對(duì)切換用戶的功能進(jìn)行鑒權(quán),否則任何人都可以隨意切換用戶,那就安全故障了。
@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 { //Eachnamespace 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默認(rèn)的切換賬號(hào)的url為/login/impersonate,默認(rèn)注銷切換賬號(hào)的url為/logout/impersonate,默認(rèn)的賬號(hào)參數(shù)為username使用
上面的配置為了方便驗(yàn)證,把切換完用戶的targetUrl設(shè)置為/session,其代碼如下
@RestController @RequestMapping("/session") public class SessionController { @GetMapping("") public Object getCurrentUser(){ return SecurityContextHolder.getContext().getAuthentication(); } }
首先用普通用戶登錄,訪問http://localhost:8080/login/impersonate?username=admin,發(fā)現(xiàn)返回403
注銷,使用管理員登錄,訪問http://localhost:8080/login/impersonate?username=demoUser1,發(fā)現(xiàn)成功并跳轉(zhuǎn)到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" }
可以發(fā)現(xiàn)有成功切換
之后再切換回來
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" }
可以發(fā)現(xiàn)切換回來了,是不是非常神奇,太強(qiáng)大了,以后線上排查問題之類的,非常方便,爽歪歪了簡(jiǎn)直
異常情況
如果你切換了不存在的用戶,則報(bào)
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小結(jié)
SwitchUserFilter是個(gè)強(qiáng)大的filter,非常方便測(cè)試環(huán)境進(jìn)行調(diào)試、測(cè)試,甚至可以用來進(jìn)行上線問題排查。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/11321.html
摘要:返回總共需要處理個(gè)地方,一個(gè)是異常的處理,需要兼容請(qǐng)求,一個(gè)是成功返回的處理,一個(gè)是失敗返回的處理。這里就是攔截,獲取提交的參數(shù),然后交給去認(rèn)證。之后就是走后續(xù)的,如果成功,則會(huì)進(jìn)行相應(yīng)的配置。動(dòng)態(tài)配置權(quán)限筆記自定義 序 本文講述一下如何自定義spring security的登錄頁,網(wǎng)上給的資料大多過時(shí),而且是基于后端模板技術(shù)的,講的不是太清晰,本文給出一個(gè)采用ajax的登錄及返回的前...
摘要:布爾類型,表示文檔是否按照有序或者無序插入,默認(rèn)是返回參數(shù)返回了含有操作狀態(tài)的對(duì)象插入文檔成功返回如下對(duì)象字段指明了插入文檔的總數(shù)如果該操作遇到了錯(cuò)誤對(duì)象將包含該錯(cuò)誤信息例子四其它可以向集合中添加文檔的方法和選項(xiàng)一起使用的。 上一節(jié)介紹了MongoDB的基本的命令,以及結(jié)構(gòu)的了解,這一節(jié)的主題是介紹一下MongoDB的插入文檔的操作的基礎(chǔ)命令的使用,MongoDB當(dāng)中文檔的數(shù)據(jù)結(jié)構(gòu)和j...
摘要:對(duì)中的數(shù)據(jù)綁定場(chǎng)景,小伙伴們就再熟悉不過了。比如包下大名鼎鼎的源碼分析的源碼相對(duì)來說還是頗為復(fù)雜的,它提供的能力非常強(qiáng)大,也注定了它的方法非常多屬性也非常多。并且備注入群字樣,會(huì)手動(dòng)邀請(qǐng)入群 每篇一句 唯有熱愛和堅(jiān)持,才能讓你在程序人生中屹立不倒,切忌跟風(fēng)什么語言或就學(xué)什么去~ 相關(guān)閱讀 【小家Spring】聊聊Spring中的數(shù)據(jù)綁定 --- 屬性訪問器PropertyAccesso...
閱讀 1734·2021-11-22 12:09
閱讀 1461·2019-08-30 13:22
閱讀 2093·2019-08-29 17:00
閱讀 2644·2019-08-29 16:28
閱讀 2955·2019-08-26 13:51
閱讀 1183·2019-08-26 13:25
閱讀 3245·2019-08-26 12:14
閱讀 3015·2019-08-26 12:14