我一直在尝试 Spring Security,在构建了一个小原型之后,我在这里遇到了一个有趣的场景,我无法弄清楚我做错了什么。
这是一个简单的场景:用户请求试用。系统生成一个随机字符串并发送一个带有该字符串的链接。用户点击链接(或在他/她的浏览器地址栏中复制),系统重定向以设置密码。
在用户单击链接之前,一切正常。该链接是使用 Spring MVC 映射的,我的方法仅检查字符串是否有效且未过期。然后使用 PreAuthenticatedAuthenticationToken 我登录用户并重定向到密码页面。(见下面的代码)
try {
SecurityIdentification securityIdentification = securityService.loadSecurityId(securityId);
User user = securityIdentification.getUser();
PreAuthenticatedAuthenticationToken preAuthenticatedAuthenticationToken = new PreAuthenticatedAuthenticationToken(user.getEmailAddress(), securityId, user.getAuthorities());
Authentication authentication = authenticationManager.authenticate(preAuthenticatedAuthenticationToken);
SecurityContext securityContext = SecurityContextHolder.getContext();
securityContext.setAuthentication(authentication);
return "redirect:/password";
} catch (AuthenticationException e) {
model.addAttribute("message", e.getMessage());
model.addAttribute(new TrialForm());
return "trial";
}
另外,这是我的上下文 xml。我只是为了节省空间而放豆子。:)
<context:component-scan
base-package="xyz.com.security" />
<security:http
pattern="/trial/**"
security="none" />
<security:http>
<security:intercept-url
pattern="/**"
access="ROLE_USER" />
<security:anonymous
username="guest"
granted-authority="ROLE_GUEST"
enabled="true" />
<security:form-login default-target-url="/dashboard" />
<security:logout />
<security:remember-me />
</security:http>
<security:authentication-manager alias="authenticationManager">
<security:authentication-provider
ref="daoAuthenticationProvider" />
<security:authentication-provider
ref="preAuthenticatedAuthenticationProvider" />
</security:authentication-manager>
<bean
id="authenticator"
class="xyz.com.security.Authenticator" />
<bean
id="encoder"
class="org.springframework.security.crypto.password.StandardPasswordEncoder" />
<bean
id="daoAuthenticationProvider"
class="org.springframework.security.authentication.dao.DaoAuthenticationProvider"
>
<property
name="userDetailsService"
ref="authenticator" />
<property
name="passwordEncoder"
ref="encoder" />
</bean>
<bean
id="preAuthenticatedAuthenticationProvider"
class="org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider"
>
<property
name="preAuthenticatedUserDetailsService"
ref="authenticator" />
</bean>
我将 UserDetails 实现为我的实体“用户”,将 GrantedAuthority 实现为我的实体“角色”。我还实现了 AuthenticationUserDetailsService,它在数据库中查找并加载我的用户。
现在......最后......:D我面临的问题是,当我使用上面的代码对我的用户进行预身份验证并重定向到密码页面时,spring security会向我显示登录页面而不是我期望的密码页面已通过身份验证的用户。
我见过一些实现,我的一个非常相似。唯一的区别是一些实现使用的 AbstractPreAuthenticatedProcessingFilter 但我看不到自己实现的理由。
你们对我缺少什么有任何想法吗?任何帮助都会很棒。谢谢你。
---------** 更新 **---------- 这是堆栈跟踪。
11:19:05,874 DEBUG [org.springframework.beans.factory.support.DefaultListableBeanFactory] (http-localhost-127.0.0.1-8080-1) Invoking afterPropertiesSet() on bean with name 'redirect:/password'
11:19:05,875 DEBUG [org.springframework.web.servlet.DispatcherServlet] (http-localhost-127.0.0.1-8080-1) Rendering view [org.springframework.web.servlet.view.RedirectView: name 'redirect:/password'; URL [/password]] in DispatcherServlet with name 'myapp'
11:19:05,878 DEBUG [org.springframework.web.servlet.DispatcherServlet] (http-localhost-127.0.0.1-8080-1) Successfully completed request
11:19:05,881 DEBUG [org.apache.tomcat.util.http.Cookies] (http-localhost-127.0.0.1-8080-1) Cookies: Parsing b[]: JSESSIONID=oos2stZVidFUWNWLtjCuFfaH.undefined
11:19:05,884 DEBUG [org.springframework.security.web.util.AntPathRequestMatcher] (http-localhost-127.0.0.1-8080-1) Checking match of request : '/password'; against '/trial/**'
11:19:05,887 DEBUG [org.springframework.security.web.FilterChainProxy] (http-localhost-127.0.0.1-8080-1) /password at position 1 of 11 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter'
11:19:05,889 DEBUG [org.springframework.security.web.context.HttpSessionSecurityContextRepository] (http-localhost-127.0.0.1-8080-1) HttpSession returned null object for SPRING_SECURITY_CONTEXT
11:19:05,891 DEBUG [org.springframework.security.web.context.HttpSessionSecurityContextRepository] (http-localhost-127.0.0.1-8080-1) No SecurityContext was available from the HttpSession: org.apache.catalina.session.StandardSessionFacade@23bdc15c. A new one will be created.
11:19:05,897 DEBUG [org.springframework.security.web.FilterChainProxy] (http-localhost-127.0.0.1-8080-1) /password at position 2 of 11 in additional filter chain; firing Filter: 'LogoutFilter'
11:19:05,899 DEBUG [org.springframework.security.web.FilterChainProxy] (http-localhost-127.0.0.1-8080-1) /password at position 3 of 11 in additional filter chain; firing Filter: 'UsernamePasswordAuthenticationFilter'
11:19:05,901 DEBUG [org.springframework.security.web.FilterChainProxy] (http-localhost-127.0.0.1-8080-1) /password at position 4 of 11 in additional filter chain; firing Filter: 'DefaultLoginPageGeneratingFilter'
11:19:05,903 DEBUG [org.springframework.security.web.FilterChainProxy] (http-localhost-127.0.0.1-8080-1) /password at position 5 of 11 in additional filter chain; firing Filter: 'RequestCacheAwareFilter'
11:19:05,905 DEBUG [org.springframework.security.web.FilterChainProxy] (http-localhost-127.0.0.1-8080-1) /password at position 6 of 11 in additional filter chain; firing Filter: 'SecurityContextHolderAwareRequestFilter'
11:19:05,907 DEBUG [org.springframework.security.web.FilterChainProxy] (http-localhost-127.0.0.1-8080-1) /password at position 7 of 11 in additional filter chain; firing Filter: 'RememberMeAuthenticationFilter'
11:19:05,909 DEBUG [org.springframework.security.web.FilterChainProxy] (http-localhost-127.0.0.1-8080-1) /password at position 8 of 11 in additional filter chain; firing Filter: 'AnonymousAuthenticationFilter'
11:19:05,911 DEBUG [org.springframework.security.web.authentication.AnonymousAuthenticationFilter] (http-localhost-127.0.0.1-8080-1) Populated SecurityContextHolder with anonymous token: 'org.springframework.security.authentication.AnonymousAuthenticationToken@90545b24: Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@12afc: RemoteIpAddress: 127.0.0.1; SessionId: oos2stZVidFUWNWLtjCuFfaH.undefined; Granted Authorities: ROLE_ANONYMOUS'
11:19:05,916 DEBUG [org.springframework.security.web.FilterChainProxy] (http-localhost-127.0.0.1-8080-1) /password at position 9 of 11 in additional filter chain; firing Filter: 'SessionManagementFilter'
11:19:05,917 DEBUG [org.springframework.security.web.FilterChainProxy] (http-localhost-127.0.0.1-8080-1) /password at position 10 of 11 in additional filter chain; firing Filter: 'ExceptionTranslationFilter'
11:19:05,919 DEBUG [org.springframework.security.web.FilterChainProxy] (http-localhost-127.0.0.1-8080-1) /password at position 11 of 11 in additional filter chain; firing Filter: 'FilterSecurityInterceptor'
11:19:05,921 DEBUG [org.springframework.security.web.access.intercept.FilterSecurityInterceptor] (http-localhost-127.0.0.1-8080-1) Secure object: FilterInvocation: URL: /password; Attributes: [ROLE_USER]
11:19:05,923 DEBUG [org.springframework.security.web.access.intercept.FilterSecurityInterceptor] (http-localhost-127.0.0.1-8080-1) Previously Authenticated: org.springframework.security.authentication.AnonymousAuthenticationToken@90545b24: Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@12afc: RemoteIpAddress: 127.0.0.1; SessionId: oos2stZVidFUWNWLtjCuFfaH.undefined; Granted Authorities: ROLE_ANONYMOUS
11:19:51,333 DEBUG [org.apache.catalina.session.ManagerBase] (ContainerBackgroundProcessor[StandardEngine[jboss.web]]) Start expire sessions StandardManager at 1355177991333 sessioncount 0
11:19:51,339 DEBUG [org.apache.catalina.session.ManagerBase] (ContainerBackgroundProcessor[StandardEngine[jboss.web]]) End expire sessions StandardManager processingTime 6 expired sessions: 0
11:20:01,346 DEBUG [org.apache.catalina.session.ManagerBase] (ContainerBackgroundProcessor[StandardEngine[jboss.web]]) Start expire sessions StandardManager at 1355178001346 sessioncount 1
11:20:01,351 DEBUG [org.apache.catalina.session.ManagerBase] (ContainerBackgroundProcessor[StandardEngine[jboss.web]]) End expire sessions StandardManager processingTime 5 expired sessions: 0
11:20:20,500 DEBUG [org.springframework.security.access.vote.AffirmativeBased] (http-localhost-127.0.0.1-8080-1) Voter: org.springframework.security.access.vote.RoleVoter@50d9370d, returned: -1
11:20:20,512 DEBUG [org.springframework.security.access.vote.AffirmativeBased] (http-localhost-127.0.0.1-8080-1) Voter: org.springframework.security.access.vote.AuthenticatedVoter@64ad5ff2, returned: 0
11:20:20,520 DEBUG [org.springframework.security.web.access.ExceptionTranslationFilter] (http-localhost-127.0.0.1-8080-1) Access is denied (user is anonymous); redirecting to authentication entry point: org.springframework.security.access.AccessDeniedException: Access is denied
at org.springframework.security.access.vote.AffirmativeBased.decide(AffirmativeBased.java:83) [spring-security-core-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.springframework.security.access.intercept.AbstractSecurityInterceptor.beforeInvocation(AbstractSecurityInterceptor.java:206) [spring-security-core-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:115) [spring-security-web-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:84) [spring-security-web-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) [spring-security-web-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:113) [spring-security-web-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) [spring-security-web-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:103) [spring-security-web-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) [spring-security-web-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:113) [spring-security-web-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) [spring-security-web-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationFilter.doFilter(RememberMeAuthenticationFilter.java:139) [spring-security-web-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) [spring-security-web-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:54) [spring-security-web-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) [spring-security-web-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:45) [spring-security-web-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) [spring-security-web-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter.doFilter(DefaultLoginPageGeneratingFilter.java:91) [spring-security-web-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) [spring-security-web-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:183) [spring-security-web-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) [spring-security-web-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:105) [spring-security-web-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) [spring-security-web-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:87) [spring-security-web-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) [spring-security-web-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:192) [spring-security-web-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:160) [spring-security-web-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346) [spring-web-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:259) [spring-web-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:280) [jbossweb-7.0.13.Final.jar:]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:248) [jbossweb-7.0.13.Final.jar:]
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:275) [jbossweb-7.0.13.Final.jar:]
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:161) [jbossweb-7.0.13.Final.jar:]
at org.jboss.as.jpa.interceptor.WebNonTxEmCloserValve.invoke(WebNonTxEmCloserValve.java:50) [jboss-as-jpa-7.1.1.Final.jar:7.1.1.Final]
at org.jboss.as.web.security.SecurityContextAssociationValve.invoke(SecurityContextAssociationValve.java:153) [jboss-as-web-7.1.1.Final.jar:7.1.1.Final]
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:155) [jbossweb-7.0.13.Final.jar:]
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102) [jbossweb-7.0.13.Final.jar:]
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109) [jbossweb-7.0.13.Final.jar:]
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:368) [jbossweb-7.0.13.Final.jar:]
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:877) [jbossweb-7.0.13.Final.jar:]
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:671) [jbossweb-7.0.13.Final.jar:]
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:930) [jbossweb-7.0.13.Final.jar:]
at java.lang.Thread.run(Thread.java:662) [rt.jar:1.6.0_34]
11:20:20,595 DEBUG [org.apache.tomcat.util.http.Parameters] (http-localhost-127.0.0.1-8080-1) Set encoding to ISO-8859-1
11:20:20,597 DEBUG [org.springframework.security.web.savedrequest.HttpSessionRequestCache] (http-localhost-127.0.0.1-8080-1) DefaultSavedRequest added to Session: DefaultSavedRequest[http://localhost:8080/myapp/password]
11:20:20,600 DEBUG [org.springframework.security.web.access.ExceptionTranslationFilter] (http-localhost-127.0.0.1-8080-1) Calling Authentication entry point.
11:20:20,602 DEBUG [org.springframework.security.web.DefaultRedirectStrategy] (http-localhost-127.0.0.1-8080-1) Redirecting to 'http://localhost:8080/myapp/spring_security_login'
11:20:20,603 DEBUG [org.springframework.security.web.context.HttpSessionSecurityContextRepository] (http-localhost-127.0.0.1-8080-1) SecurityContext is empty or contents are anonymous - context will not be stored in HttpSession.
11:20:20,605 DEBUG [org.springframework.security.web.context.SecurityContextPersistenceFilter] (http-localhost-127.0.0.1-8080-1) SecurityContextHolder now cleared, as request processing completed
11:20:20,610 DEBUG [org.apache.tomcat.util.http.Cookies] (http-localhost-127.0.0.1-8080-1) Cookies: Parsing b[]: JSESSIONID=oos2stZVidFUWNWLtjCuFfaH.undefined
11:20:20,612 DEBUG [org.springframework.security.web.util.AntPathRequestMatcher] (http-localhost-127.0.0.1-8080-1) Checking match of request : '/spring_security_login'; against '/trial/**'
11:20:20,615 DEBUG [org.springframework.security.web.FilterChainProxy] (http-localhost-127.0.0.1-8080-1) /spring_security_login at position 1 of 11 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter'
11:20:20,616 DEBUG [org.springframework.security.web.context.HttpSessionSecurityContextRepository] (http-localhost-127.0.0.1-8080-1) HttpSession returned null object for SPRING_SECURITY_CONTEXT
11:20:20,618 DEBUG [org.springframework.security.web.context.HttpSessionSecurityContextRepository] (http-localhost-127.0.0.1-8080-1) No SecurityContext was available from the HttpSession: org.apache.catalina.session.StandardSessionFacade@23bdc15c. A new one will be created.
11:20:20,620 DEBUG [org.springframework.security.web.FilterChainProxy] (http-localhost-127.0.0.1-8080-1) /spring_security_login at position 2 of 11 in additional filter chain; firing Filter: 'LogoutFilter'
11:20:20,622 DEBUG [org.springframework.security.web.FilterChainProxy] (http-localhost-127.0.0.1-8080-1) /spring_security_login at position 3 of 11 in additional filter chain; firing Filter: 'UsernamePasswordAuthenticationFilter'
11:20:20,625 DEBUG [org.springframework.security.web.FilterChainProxy] (http-localhost-127.0.0.1-8080-1) /spring_security_login at position 4 of 11 in additional filter chain; firing Filter: 'DefaultLoginPageGeneratingFilter'
11:20:20,628 DEBUG [org.apache.tomcat.util.http.Parameters] (http-localhost-127.0.0.1-8080-1) Set encoding to ISO-8859-1
11:20:20,630 DEBUG [org.springframework.security.web.context.HttpSessionSecurityContextRepository] (http-localhost-127.0.0.1-8080-1) SecurityContext is empty or contents are anonymous - context will not be stored in HttpSession.
11:20:20,633 DEBUG [org.springframework.security.web.context.SecurityContextPersistenceFilter] (http-localhost-127.0.0.1-8080-1) SecurityContextHolder now cleared, as request processing completed