使用Spring Security和CAS进行单点注销

前端之家收集整理的这篇文章主要介绍了使用Spring Security和CAS进行单点注销前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

使用纯Spring Java Config我很难让Spring和CAS执行单点注销.我有单点登录使用下面的配置.我使用一个简单的JSP页面对url https://nginx.shane.com/app/logout执行表单POST,并在POST’d数据中包含CSRF值.这一切似乎都没有错误,但是当我进入安全页面时,它只是让我回来而无需登录.有任何想法吗?

  1. @Configuration
  2. @EnableWebSecurity
  3. public class SecurityWebAppConfig extends WebSecurityConfigurerAdapter {
  4. @Bean
  5. protected ServiceProperties serviceProperties() {
  6. ServiceProperties serviceProperties = new ServiceProperties();
  7. serviceProperties.setService("https://Nginx.shane.com/app/j_spring_cas_security_check");
  8. serviceProperties.setSendRenew(false);
  9. return serviceProperties;
  10. }
  11. @Bean
  12. public CasAuthenticationProvider casAuthenticationProvider() {
  13. CasAuthenticationProvider casAuthenticationProvider = new CasAuthenticationProvider();
  14. casAuthenticationProvider.setAuthenticationUserDetailsService(authenticationUserDetailsService());
  15. casAuthenticationProvider.setServiceProperties(serviceProperties());
  16. casAuthenticationProvider.setTicketValidator(cas20ServiceTicketValidator());
  17. casAuthenticationProvider.setKey("an_id_for_this_auth_provider_only");
  18. return casAuthenticationProvider;
  19. }
  20. @Bean
  21. public AuthenticationUserDetailsServiceNginx.shane.com/cas");
  22. }
  23. @Bean
  24. public CasAuthenticationFilter casAuthenticationFilter() throws Exception {
  25. CasAuthenticationFilter casAuthenticationFilter = new CasAuthenticationFilter();
  26. casAuthenticationFilter.setAuthenticationManager(authenticationManager());
  27. return casAuthenticationFilter;
  28. }
  29. @Bean
  30. public CasAuthenticationEntryPoint casAuthenticationEntryPoint() {
  31. CasAuthenticationEntryPoint casAuthenticationEntryPoint = new CasAuthenticationEntryPoint();
  32. casAuthenticationEntryPoint.setLoginUrl("https://Nginx.shane.com/cas/login");
  33. casAuthenticationEntryPoint.setServiceProperties(serviceProperties());
  34. return casAuthenticationEntryPoint;
  35. }
  36. @Bean
  37. public SingleSignOutFilter singleSignOutFilter() {
  38. // This filter handles a Single logout Request from the CAS Server
  39. return new SingleSignOutFilter();
  40. }
  41. @Bean
  42. public logoutFilter requestlogoutFilter() {
  43. // This filter redirects to the CAS Server to signal Single logout should be performed
  44. SecurityContextlogoutHandler handler = new SecurityContextlogoutHandler();
  45. handler.setClearAuthentication(true);
  46. handler.setInvalidateHttpSession(true);
  47. logoutFilter logoutFilter = new logoutFilter("https://Nginx.shane.com/",handler);
  48. return logoutFilter;
  49. }
  50. @Override
  51. protected void configure(HttpSecurity http) throws Exception {
  52. http.addFilter(casAuthenticationFilter());
  53. http.addFilterBefore(requestlogoutFilter(),logoutFilter.class);
  54. http.addFilterBefore(singleSignOutFilter(),CasAuthenticationFilter.class);
  55. http.exceptionHandling()
  56. .authenticationEntryPoint(casAuthenticationEntryPoint());
  57. http.authorizeRequests()
  58. .antMatchers("/admin/**").access("hasRole('ROLE_ADMIN')")
  59. .antMatchers("/dba/**").access("hasRole('ROLE_ADMIN') or hasRole('ROLE_DBA')");
  60. http.logout()
  61. .addlogoutHandler(handler)
  62. .deleteCookies("remove")
  63. .invalidateHttpSession(true)
  64. .logoutUrl("/logout")
  65. .logoutSuccessUrl("/");
  66. }
  67. @Override
  68. protected void configure(AuthenticationManagerBuilder auth) throws Exception {
  69. auth.authenticationProvider(casAuthenticationProvider());
  70. }

}

我还添加了一个WebListener来处理会话销毁事件:

  1. @WebListener
  2. public class SecurityWebListener implements HttpSessionListener {
  3. private SingleSignOutHttpSessionListener listener = new SingleSignOutHttpSessionListener();
  4. @Override
  5. public void sessionCreated(HttpSessionEvent se) {
  6. listener.sessionCreated(se);
  7. }
  8. @Override
  9. public void sessionDestroyed(HttpSessionEvent se) {
  10. listener.sessionDestroyed(se);
  11. }
  12. }

这是日志输出

  1. [org.springframework.security.web.FilterChainProxy] [/logout at position 6 of 14 in additional filter chain; firing Filter: 'logoutFilter'] []
  2. [org.springframework.security.web.util.matcher.AntPathRequestMatcher] [Checking match of request : '/logout'; against '/logout'] []
  3. [org.springframework.security.web.authentication.logout.logoutFilter] [Logging out user 'org.springframework.security.cas.authentication.CasAuthenticationToken@836ad34b: Principal: org.springframework.security.core.userdetails.User@586034f: Username: admin; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_ADMIN; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@fffdaa08: RemoteIpAddress: 127.0.0.1; SessionId: FA880C15EF09C033E1CA0C8E4785905F; Granted Authorities: ROLE_ADMIN Assertion: org.jasig.cas.client.validation.AssertionImpl@fcd38ec Credentials (Service/Proxy Ticket): ST-23-1UandqRxBcG6HCTx0Pdd-cas01.example.org' and transferring to logout destination] []
  4. [org.springframework.security.web.authentication.logout.SecurityContextlogoutHandler] [Invalidating session: FA880C15EF09C033E1CA0C8E4785905F] []
  5. [org.jasig.cas.client.session.HashMapBackedSessionMappingStorage] [Attempting to remove Session=[FA880C15EF09C033E1CA0C8E4785905F]] []
  6. [org.jasig.cas.client.session.HashMapBackedSessionMappingStorage] [Found mapping for session. Session Removed.] []
  7. [org.springframework.security.web.authentication.logout.SimpleUrllogoutSuccessHandler] [Using default Url: /] []
  8. [org.springframework.security.web.DefaultRedirectStrategy] [Redirecting to '/app/'] []
最佳答案
(联合国)幸运我有类似问题;)当CAS试图调用您的应用程序注销时发生.一方面,CAS尝试传递sessionId以执行注销,另一方面,SpringSecurity期望获得CSRF令牌,该令牌不是由CAS发送的,因为它仅发送GET请求. CsrfFilter找不到csrf令牌并中断过滤器链.用户不知道这一点,因为CAS隐式调用了注销请求.请求直接从CAS服务器发送到应用程序服务器,而不是通过在Web浏览器中重定向用户.

为了使其工作,您需要配置HttpSecurity以排除/不包括logoutFilter filterProcessesUrl(在您使用默认值时,在您的情况下为j_spring_security_logout).

假设您在尝试创建新管理员时要检查CSRF,为了解决问题,您需要按如下方式对其进行配置:

  1. @Override
  2. protected void configure(HttpSecurity http) throws Exception {
  3. http.addFilter(casAuthenticationFilter());
  4. http.addFilterBefore(requestlogoutFilter(),CasAuthenticationFilter.class);
  5. http.exceptionHandling()
  6. .authenticationEntryPoint(casAuthenticationEntryPoint());
  7. http.authorizeRequests()
  8. .antMatchers("/admin/**").access("hasRole('ROLE_ADMIN')")
  9. .antMatchers("/dba/**").access("hasRole('ROLE_ADMIN') or hasRole('ROLE_DBA')");
  10. http.csrf()
  11. .requireCsrfProtectionMatcher(new AntPathRequestMatcher("/admin/create"));
  12. http.logout()
  13. .addlogoutHandler(handler)
  14. .deleteCookies("remove")
  15. .invalidateHttpSession(true)
  16. .logoutUrl("/logout")
  17. .logoutSuccessUrl("/");
  18. }

只是为了表明,我已经补充说

http.csrf().requireCsrfProtectionMatcher(new AntPathRequestMatcher(“/ admin / create”));.

注意你不能使用match all pattern(/ admin / **),因为你可能想要调用一些get请求,CSRF过滤器会期望它们发送令牌.

由于在那里引入了跨站点请求伪造(CSRF)支持,因此Spring Security 3.2x之前不会出现此类问题.

希望这些帮助:)

猜你在找的Spring相关文章