在我们的项目中,我们使用Security提供两种身份验证方法。第一个是使用LDAP的基于表单的登录,第二个是使用Kerberos的SSO。这两种类型共享共同的功能。Kerberos基本上给出了主体,然后我们使用LDAP查询Active Directory以检索某些数据(部门、电子邮件地址等)。对于基于表单的登录,我们采用用户提供的登录/密码,使用LDAP对Active进行验证,并检索一些信息。
在这两种方法中,我们使用一个(相同的)自定义UserDetailsContextMapper,它负责将LDAP信息映射到内部用户对象。
在已实现的mapUserFromContext方法中,我们还执行其他一些验证,例如,我们检查连接到传入的LDAP用户的应用程序内部用户对象是否不活动。在这种情况下,我们将抛出一个AuthenticationException,而不是返回一个UserDetails模型。
如果身份验证失败,则应使用错误消息显示表单登录页。
现在的问题是,每当使用Internet 8/9/10在Kerberos环境中抛出这样的异常时,就会导致重定向循环。这似乎与我们在SpnegoAuthenticationProcessingFilter bean中注入的SpnegoAuthenticationProcessingFilter有关。SpnegoAuthenticationProcessingFilter bean将尝试身份验证,我们抛出我们的AuthenticationException,它将遇到一个catch块,并通过重定向到表单登录页面来处理失败处理程序。
Firefox不会在重定向循环中结束。它显示带有错误消息的登录页面。
此外,在IE中使用到表单登录页的直接链接将绕过Kerberos,并以错误消息正确地重新显示登录页面,以防我们抛出异常。
Kerberos和SSO工作得很好。正是我们抛出的AuthenticationException与Kerberos相结合才导致了这个问题。
不涉及HTTP/HTTPS交换。我们总是在测试环境中使用HTTP。
问题是:
UserDetailsContextMapper是执行自定义验证的最佳位置吗?我们可以在那里扔AuthenticationException吗?我们的测试环境:
整个Spring安全相关的配置是相当广泛的,所以现在我将把它保持在最低限度,只列出我认为对这个问题很重要的部分。
Resources.groovy中的Bean配置:
ldapUserDetailsMapper(CustomLdapUserDetailsContextMapper) {
grailsApplication = ref('grailsApplication')
}
kerberosUserSearch(FilterBasedLdapUserSearch,
application.config.grails.plugins.springsecurity.ldap.search.base,
application.config.grails.plugins.springsecurity.ldap.search.filterKerberos,
ref('contextSource')) {
}
kerberosUserDetailsService(LdapUserDetailsService, ref('kerberosUserSearch'), ref('ldapAuthoritiesPopulator')) {
userDetailsMapper = ref('ldapUserDetailsMapper')
}
kerberosServiceAuthenticationProvider(KerberosServiceAuthenticationProvider) {
userDetailsService = ref('kerberosUserDetailsService')
ticketValidator = ref('kerberosTicketValidator')
}
authenticationFailureHandler(org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler) {
defaultFailureUrl = '/login/authfail?login_error=1'
}
spnegoAuthenticationProcessingFilter(org.springframework.security.extensions.kerberos.web.SpnegoAuthenticationProcessingFilter) {
authenticationManager = ref('authenticationManager')
failureHandler = ref('authenticationFailureHandler')
}与Spring安全相关的配置定义了某些属性(我省略了不相关的属性):
grails.plugins.springsecurity.ldap.search.searchSubtree = true
grails.plugins.springsecurity.ldap.auth.hideUserNotFoundExceptions = false
grails.plugins.springsecurity.ldap.search.derefLink = true
grails.plugins.springsecurity.ldap.authorities.retrieveGroupRoles = true
grails.plugins.springsecurity.ldap.authorities.retrieveDatabaseRoles = false
grails.plugins.springsecurity.ldap.authorities.ignorePartialResultException = true
grails.plugins.springsecurity.ldap.useRememberMe = false
grails.plugins.springsecurity.providerNames = ['ldapAuthProvider', 'kerberosServiceAuthenticationProvider']
grails.plugins.springsecurity.securityConfigType = "InterceptUrlMap"
grails.plugins.springsecurity.interceptUrlMap = [
'/login/**': ['IS_AUTHENTICATED_ANONYMOUSLY'],
'/logout/**': ['IS_AUTHENTICATED_ANONYMOUSLY'],
'/**': ['IS_AUTHENTICATED_FULLY']
]使用Fiddler可以观察到的请求是:
如果需要的话我可以提供更多的细节。任何帮助和评论都是非常感谢的。
Spring安全调试日志记录:
2014-09-01 08:37:54,884 [http-apr-8080-exec-4] DEBUG web.FilterChainProxy - Converted URL to lowercase, from: '/index.gsp'; to: '/index.gsp'
2014-09-01 08:37:54,884 [http-apr-8080-exec-4] DEBUG web.FilterChainProxy - Candidate is: '/index.gsp'; pattern is /**; matched=true
2014-09-01 08:37:54,900 [http-apr-8080-exec-4] DEBUG web.FilterChainProxy - /index.gsp at position 1 of 9 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter'
2014-09-01 08:37:54,900 [http-apr-8080-exec-4] DEBUG context.HttpSessionSecurityContextRepository - No HttpSession currently exists
2014-09-01 08:37:54,900 [http-apr-8080-exec-4] DEBUG context.HttpSessionSecurityContextRepository - No SecurityContext was available from the HttpSession: null. A new one will be created.
2014-09-01 08:37:54,900 [http-apr-8080-exec-4] DEBUG web.FilterChainProxy - /index.gsp at position 2 of 9 in additional filter chain; firing Filter: 'MutableLogoutFilter'
2014-09-01 08:37:54,900 [http-apr-8080-exec-4] DEBUG web.FilterChainProxy - /index.gsp at position 3 of 9 in additional filter chain; firing Filter: 'RequestHolderAuthenticationFilter'
2014-09-01 08:37:54,900 [http-apr-8080-exec-4] DEBUG web.FilterChainProxy - /index.gsp at position 4 of 9 in additional filter chain; firing Filter: 'SpnegoAuthenticationProcessingFilter'
2014-09-01 08:37:54,900 [http-apr-8080-exec-4] DEBUG web.FilterChainProxy - /index.gsp at position 5 of 9 in additional filter chain; firing Filter: 'SecurityContextHolderAwareRequestFilter'
2014-09-01 08:37:54,900 [http-apr-8080-exec-4] DEBUG web.FilterChainProxy - /index.gsp at position 6 of 9 in additional filter chain; firing Filter: 'RememberMeAuthenticationFilter'
2014-09-01 08:37:54,900 [http-apr-8080-exec-4] DEBUG web.FilterChainProxy - /index.gsp at position 7 of 9 in additional filter chain; firing Filter: 'AnonymousAuthenticationFilter'
2014-09-01 08:37:54,900 [http-apr-8080-exec-4] DEBUG authentication.AnonymousAuthenticationFilter - Populated SecurityContextHolder with anonymous token: 'org.springframework.security.authentication.AnonymousAuthenticationToken@6faa3d44: Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@ffff4c9c: RemoteIpAddress: 192.168.0.126; SessionId: null; Granted Authorities: ROLE_ANONYMOUS'
2014-09-01 08:37:54,900 [http-apr-8080-exec-4] DEBUG web.FilterChainProxy - /index.gsp at position 8 of 9 in additional filter chain; firing Filter: 'ExceptionTranslationFilter'
2014-09-01 08:37:54,900 [http-apr-8080-exec-4] DEBUG web.FilterChainProxy - /index.gsp at position 9 of 9 in additional filter chain; firing Filter: 'FilterSecurityInterceptor'
2014-09-01 08:37:54,900 [http-apr-8080-exec-4] DEBUG intercept.FilterSecurityInterceptor - Secure object: FilterInvocation: URL: /index.gsp; Attributes: [IS_AUTHENTICATED_FULLY]
2014-09-01 08:37:54,900 [http-apr-8080-exec-4] DEBUG intercept.FilterSecurityInterceptor - Previously Authenticated: org.springframework.security.authentication.AnonymousAuthenticationToken@6faa3d44: Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@ffff4c9c: RemoteIpAddress: 192.168.0.126; SessionId: null; Granted Authorities: ROLE_ANONYMOUS
2014-09-01 08:37:54,931 [http-apr-8080-exec-4] DEBUG access.ExceptionTranslationFilter - Access is denied (user is anonymous); redirecting to authentication entry point
org.springframework.security.access.AccessDeniedException: Access is denied
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:662)
2014-09-01 08:37:54,931 [http-apr-8080-exec-4] DEBUG savedrequest.HttpSessionRequestCache - DefaultSavedRequest added to Session: DefaultSavedRequest[http://vs-vm-dev2003:8080/app/]
2014-09-01 08:37:54,931 [http-apr-8080-exec-4] DEBUG access.ExceptionTranslationFilter - Calling Authentication entry point.
2014-09-01 08:37:54,931 [http-apr-8080-exec-4] DEBUG web.SpnegoEntryPoint - Sending back Negotiate Header for request: http://vs-vm-dev2003:8080/app/
2014-09-01 08:37:54,931 [http-apr-8080-exec-4] DEBUG context.HttpSessionSecurityContextRepository - SecurityContext is empty or anonymous - context will not be stored in HttpSession.
2014-09-01 08:37:54,931 [http-apr-8080-exec-4] DEBUG context.SecurityContextPersistenceFilter - SecurityContextHolder now cleared, as request processing completed
2014-09-01 08:37:54,993 [http-apr-8080-exec-5] DEBUG web.FilterChainProxy - Converted URL to lowercase, from: '/index.gsp'; to: '/index.gsp'
2014-09-01 08:37:54,993 [http-apr-8080-exec-5] DEBUG web.FilterChainProxy - Candidate is: '/index.gsp'; pattern is /**; matched=true
2014-09-01 08:37:54,993 [http-apr-8080-exec-5] DEBUG web.FilterChainProxy - /index.gsp at position 1 of 9 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter'
2014-09-01 08:37:54,993 [http-apr-8080-exec-5] DEBUG context.HttpSessionSecurityContextRepository - HttpSession returned null object for SPRING_SECURITY_CONTEXT
2014-09-01 08:37:54,993 [http-apr-8080-exec-5] DEBUG context.HttpSessionSecurityContextRepository - No SecurityContext was available from the HttpSession: org.apache.catalina.session.StandardSessionFacade@18a92eb. A new one will be created.
2014-09-01 08:37:54,993 [http-apr-8080-exec-5] DEBUG web.FilterChainProxy - /index.gsp at position 2 of 9 in additional filter chain; firing Filter: 'MutableLogoutFilter'
2014-09-01 08:37:54,993 [http-apr-8080-exec-5] DEBUG web.FilterChainProxy - /index.gsp at position 3 of 9 in additional filter chain; firing Filter: 'RequestHolderAuthenticationFilter'
2014-09-01 08:37:54,993 [http-apr-8080-exec-5] DEBUG web.FilterChainProxy - /index.gsp at position 4 of 9 in additional filter chain; firing Filter: 'SpnegoAuthenticationProcessingFilter'
2014-09-01 08:37:54,993 [http-apr-8080-exec-5] DEBUG web.SpnegoAuthenticationProcessingFilter - Received Negotiate Header for request http://vs-vm-dev2003:8080/app/: Negotiate <omitted>
2014-09-01 08:37:55,009 [http-apr-8080-exec-5] DEBUG authentication.ProviderManager - Authentication attempt using org.springframework.security.extensions.kerberos.KerberosServiceAuthenticationProvider
2014-09-01 08:37:55,009 [http-apr-8080-exec-5] DEBUG kerberos.KerberosServiceAuthenticationProvider - Try to validate Kerberos Token
Found key for HTTP/vs-vm-dev2003@DOMAIN.LOCAL(23)
Entered Krb5Context.acceptSecContext with state=STATE_NEW
>>> EType: sun.security.krb5.internal.crypto.ArcFourHmacEType
Using builtin default etypes for permitted_enctypes
default etypes for permitted_enctypes: 3 1 23 16 17 18.
>>> EType: sun.security.krb5.internal.crypto.ArcFourHmacEType
replay cache for TESTER@DOMAIN.LOCAL is null.
object 0: 1409575075000/30
object 0: 1409575075000/30
>>> KrbApReq: authenticate succeed.
>>> EType: sun.security.krb5.internal.crypto.ArcFourHmacEType
>>>Delegated Creds have pname=TESTER@DOMAIN.LOCAL sname=krbtgt/DOMAIN.LOCAL@DOMAIN.LOCAL authtime=null starttime=20140901123744Z endtime=20140901223743ZrenewTill=20140908123743Z
Krb5Context setting peerSeqNumber to: 207387731
>>> EType: sun.security.krb5.internal.crypto.ArcFourHmacEType
Krb5Context setting mySeqNumber to: 159224545
2014-09-01 08:37:55,212 [http-apr-8080-exec-5] DEBUG kerberos.KerberosServiceAuthenticationProvider - Succesfully validated TESTER@DOMAIN.LOCAL
2014-09-01 08:37:55,212 [http-apr-8080-exec-5] DEBUG search.FilterBasedLdapUserSearch - Searching for user 'TESTER@DOMAIN.LOCAL', with user search [ searchFilter: 'mail={0}', searchBase: 'DC=company,DC=com', scope: subtree, searchTimeLimit: 0, derefLinkFlag: false ]
2014-09-01 08:37:55,603 [http-apr-8080-exec-5] DEBUG ldap.SpringSecurityLdapTemplate - Searching for entry under DN '', base = 'dc=company,dc=com', filter = 'mail={0}'
2014-09-01 08:37:55,618 [http-apr-8080-exec-5] DEBUG ldap.SpringSecurityLdapTemplate - Found DN: cn=TESTER,ou=Users,ou=Users,dc=company,dc=com
2014-09-01 08:37:55,634 [http-apr-8080-exec-5] DEBUG userdetails.DefaultLdapAuthoritiesPopulator - Getting authorities for user cn=TESTER,ou=Users,ou=Users,dc=company,dc=com
2014-09-01 08:37:55,634 [http-apr-8080-exec-5] DEBUG userdetails.DefaultLdapAuthoritiesPopulator - Searching for roles for user 'TESTER@DOMAIN.LOCAL', DN = 'cn=TESTER,ou=Users,ou=Users,dc=company,dc=com', with filter member={0} in search base 'OU=Groups,OU=Users,DC=company,DC=com'
2014-09-01 08:37:55,634 [http-apr-8080-exec-5] DEBUG ldap.SpringSecurityLdapTemplate - Using filter: member=cn=TESTER,ou=Users,ou=Users,dc=company,dc=com
2014-09-01 08:37:55,665 [http-apr-8080-exec-5] DEBUG userdetails.DefaultLdapAuthoritiesPopulator - Roles from search: []
2014-09-01 08:37:55,665 [http-apr-8080-exec-5] DEBUG security.CustomLdapUserDetailsContextMapper - Mapping user details from context with DN: cn=TESTER,ou=Users,ou=Users,dc=company,dc=com
2014-09-01 08:37:56,103 [http-apr-8080-exec-5] ERROR security.CustomLdapUserDetailsContextMapper - The user TESTER@DOMAIN.LOCAL does not have a corresponding SysX login configured.
2014-09-01 08:37:56,571 [http-apr-8080-exec-5] WARN web.SpnegoAuthenticationProcessingFilter - Negotiate Header was invalid: Negotiate <omitted>
com.company.app.security.ex.NoCorrespondingSysXLoginAuthenticationException:
at com.company.app.security.CustomLdapUserDetailsContextMapper$_mapUserFromContext_closure5.doCall(CustomLdapUserDetailsContextMapper.groovy:73)
at org.grails.datastore.gorm.GormStaticApi.withTransaction(GormStaticApi.groovy:687)
at com.company.app.security.CustomLdapUserDetailsContextMapper.mapUserFromContext(CustomLdapUserDetailsContextMapper.groovy:53)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:662)
2014-09-01 08:37:56,571 [http-apr-8080-exec-5] DEBUG authentication.SimpleUrlAuthenticationFailureHandler - Redirecting to /login/authfail?login_error=1
2014-09-01 08:37:56,571 [http-apr-8080-exec-5] DEBUG web.DefaultRedirectStrategy - Redirecting to '/app/login/authfail?login_error=1'
2014-09-01 08:37:56,571 [http-apr-8080-exec-5] DEBUG context.HttpSessionSecurityContextRepository - SecurityContext is empty or anonymous - context will not be stored in HttpSession.
2014-09-01 08:37:56,571 [http-apr-8080-exec-5] DEBUG context.SecurityContextPersistenceFilter - SecurityContextHolder now cleared, as request processing completed
2014-09-01 08:37:56,571 [http-apr-8080-exec-6] DEBUG web.FilterChainProxy - Converted URL to lowercase, from: '/login/authfail'; to: '/login/authfail'
2014-09-01 08:37:56,587 [http-apr-8080-exec-6] DEBUG web.FilterChainProxy - Candidate is: '/login/authfail'; pattern is /**; matched=true
2014-09-01 08:37:56,587 [http-apr-8080-exec-6] DEBUG web.FilterChainProxy - /login/authfail?login_error=1 at position 1 of 9 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter'
2014-09-01 08:37:56,587 [http-apr-8080-exec-6] DEBUG context.HttpSessionSecurityContextRepository - HttpSession returned null object for SPRING_SECURITY_CONTEXT
2014-09-01 08:37:56,587 [http-apr-8080-exec-6] DEBUG context.HttpSessionSecurityContextRepository - No SecurityContext was available from the HttpSession: org.apache.catalina.session.StandardSessionFacade@18a92eb. A new one will be created.
2014-09-01 08:37:56,587 [http-apr-8080-exec-6] DEBUG web.FilterChainProxy - /login/authfail?login_error=1 at position 2 of 9 in additional filter chain; firing Filter: 'MutableLogoutFilter'
2014-09-01 08:37:56,587 [http-apr-8080-exec-6] DEBUG web.FilterChainProxy - /login/authfail?login_error=1 at position 3 of 9 in additional filter chain; firing Filter: 'RequestHolderAuthenticationFilter'
2014-09-01 08:37:56,587 [http-apr-8080-exec-6] DEBUG web.FilterChainProxy - /login/authfail?login_error=1 at position 4 of 9 in additional filter chain; firing Filter: 'SpnegoAuthenticationProcessingFilter'
2014-09-01 08:37:56,587 [http-apr-8080-exec-6] DEBUG web.SpnegoAuthenticationProcessingFilter - Received Negotiate Header for request http://vs-vm-dev2003:8080/app/login/authfail: Negotiate <omitted>
2014-09-01 08:37:56,587 [http-apr-8080-exec-6] DEBUG authentication.ProviderManager - Authentication attempt using org.springframework.security.extensions.kerberos.KerberosServiceAuthenticationProvider
2014-09-01 08:37:56,587 [http-apr-8080-exec-6] DEBUG kerberos.KerberosServiceAuthenticationProvider - Try to validate Kerberos Token
Found key for HTTP/vs-vm-dev2003@DOMAIN.LOCAL(23)
Entered Krb5Context.acceptSecContext with state=STATE_NEW
>>> EType: sun.security.krb5.internal.crypto.ArcFourHmacEType
Using builtin default etypes for permitted_enctypes
default etypes for permitted_enctypes: 3 1 23 16 17 18.
>>> EType: sun.security.krb5.internal.crypto.ArcFourHmacEType
object 0: 1409575076000/31
object 1: 1409575075000/30
object 0: 1409575076000/31
object 1: 1409575075000/30
replay cache found.
>>> KrbApReq: authenticate succeed.
>>> EType: sun.security.krb5.internal.crypto.ArcFourHmacEType
>>>Delegated Creds have pname=TESTER@DOMAIN.LOCAL sname=krbtgt/DOMAIN.LOCAL@DOMAIN.LOCAL authtime=null starttime=20140901123744Z endtime=20140901223743ZrenewTill=20140908123743Z
Krb5Context setting peerSeqNumber to: 255994332
>>> EType: sun.security.krb5.internal.crypto.ArcFourHmacEType
Krb5Context setting mySeqNumber to: 867958603
2014-09-01 08:37:56,587 [http-apr-8080-exec-6] DEBUG kerberos.KerberosServiceAuthenticationProvider - Succesfully validated TESTER@DOMAIN.LOCAL
2014-09-01 08:37:56,587 [http-apr-8080-exec-6] DEBUG search.FilterBasedLdapUserSearch - Searching for user 'TESTER@DOMAIN.LOCAL', with user search [ searchFilter: 'mail={0}', searchBase: 'DC=company,DC=com', scope: subtree, searchTimeLimit: 0, derefLinkFlag: false ]
2014-09-01 08:37:56,587 [http-apr-8080-exec-6] DEBUG ldap.SpringSecurityLdapTemplate - Searching for entry under DN '', base = 'dc=company,dc=com', filter = 'mail={0}'
2014-09-01 08:37:56,587 [http-apr-8080-exec-6] DEBUG ldap.SpringSecurityLdapTemplate - Found DN: cn=TESTER,ou=Users,ou=Users,dc=company,dc=com
2014-09-01 08:37:56,603 [http-apr-8080-exec-6] DEBUG userdetails.DefaultLdapAuthoritiesPopulator - Getting authorities for user cn=TESTER,ou=Users,ou=Users,dc=company,dc=com
2014-09-01 08:37:56,603 [http-apr-8080-exec-6] DEBUG userdetails.DefaultLdapAuthoritiesPopulator - Searching for roles for user 'TESTER@DOMAIN.LOCAL', DN = 'cn=TESTER,ou=Users,ou=Users,dc=company,dc=com', with filter member={0} in search base 'OU=Groups,OU=Users,DC=company,DC=com'
2014-09-01 08:37:56,603 [http-apr-8080-exec-6] DEBUG ldap.SpringSecurityLdapTemplate - Using filter: member=cn=TESTER,ou=Users,ou=Users,dc=company,dc=com
2014-09-01 08:37:56,618 [http-apr-8080-exec-6] DEBUG userdetails.DefaultLdapAuthoritiesPopulator - Roles from search: []
2014-09-01 08:37:56,618 [http-apr-8080-exec-6] DEBUG security.CustomLdapUserDetailsContextMapper - Mapping user details from context with DN: cn=TESTER,ou=Users,ou=Users,dc=company,dc=com
2014-09-01 08:37:56,790 [http-apr-8080-exec-6] ERROR security.CustomLdapUserDetailsContextMapper - The user TESTER@DOMAIN.LOCAL does not have a corresponding SysX login configured.
2014-09-01 08:37:56,868 [http-apr-8080-exec-6] WARN web.SpnegoAuthenticationProcessingFilter - Negotiate Header was invalid: Negotiate <omitted>
com.company.app.security.ex.NoCorrespondingSysXLoginAuthenticationException:
at com.company.app.security.CustomLdapUserDetailsContextMapper$_mapUserFromContext_closure5.doCall(CustomLdapUserDetailsContextMapper.groovy:73)
at org.grails.datastore.gorm.GormStaticApi.withTransaction(GormStaticApi.groovy:687)
at com.company.app.security.CustomLdapUserDetailsContextMapper.mapUserFromContext(CustomLdapUserDetailsContextMapper.groovy:53)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:662)
2014-09-01 08:37:56,868 [http-apr-8080-exec-6] DEBUG authentication.SimpleUrlAuthenticationFailureHandler - Redirecting to /login/authfail?login_error=1
2014-09-01 08:37:56,868 [http-apr-8080-exec-6] DEBUG web.DefaultRedirectStrategy - Redirecting to '/app/login/authfail?login_error=1'
2014-09-01 08:37:56,868 [http-apr-8080-exec-6] DEBUG context.HttpSessionSecurityContextRepository - SecurityContext is empty or anonymous - context will not be stored in HttpSession.
2014-09-01 08:37:56,868 [http-apr-8080-exec-6] DEBUG context.SecurityContextPersistenceFilter - SecurityContextHolder now cleared, as request processing completed发布于 2014-09-16 22:15:19
当引发身份验证异常时,由于此配置,它会导致重定向:
authenticationFailureHandler(org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler) {
defaultFailureUrl = '/login/authfail?login_error=1'
}由于某些原因,IE一直在每个请求中发送Negotiate头,从而触发SpnegoAuthenticationProcessingFilter中的处理,后者反过来试图使用引发身份验证异常的自定义UserDetailsContextMapper加载用户详细信息。这将导致无穷无尽的重定向循环。
解决方法是绕过登录/注销页面的SpnegoAuthenticationProcessingFilter,这样,尽管存在,Negotiate头仍然会被忽略。
下面的Spring安全配置完成了这一任务:
grails.plugins.springsecurity.filterChain.chainMap = [
'/login/**': 'JOINED_FILTERS,-spnegoAuthenticationProcessingFilter',
'/logout/**': 'JOINED_FILTERS,-spnegoAuthenticationProcessingFilter',
'/**': 'JOINED_FILTERS'
]https://stackoverflow.com/questions/25572265
复制相似问题