我使用Spring security和thymeleaf创建我的登录页面,但我遇到CSRF问题。 这是我登录页面的形式:
<form th:action="@{/login}" method="post">
<div th:if="${param.error}">
<script>
notifyMessage("Invalid username and password!", 'error');
</script>
</div>
<div th:if="${param.logout}">
<script>
notifyMessage("You have been logged out!", 'success');
</script>
</div>
<div class="form-group has-feedback">
<input id="username" name="username" type="text"
class="form-control" placeholder="Username">
<span class="glyphicon glyphicon-user form-control-feedback"></span>
</div>
<div class="form-group has-feedback">
<input id="password" name="password" type="password"
class="form-control" placeholder="Password">
<span class="glyphicon glyphicon-lock form-control-feedback"></span>
</div>
<div class="row">
<!-- /.col -->
<div class="col-xs-4 col-xs-offset-8" style="margin-bottom: 15px;">
<button id="signinButton" type="submit" class="btn btn-primary btn-block btn-flat">
Sign In
</button>
</div>
<!-- /.col -->
</div>
</form>
在Spring配置中我有:
@Configuration
@EnableWebMvcSecurity
@EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true, proxyTargetClass = true)
@PropertySource(value = {"classpath:application.properties"})
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Configuration
protected static class AuthenticationConfiguration
implements AuthenticationProvider {
@Autowired
private UserServices userServices;
@Autowired
LdapServices ldapServices;
@Override
public Authentication authenticate(Authentication authentication) throws
AuthenticationException {
Set<GrantedAuthority> authorities = new HashSet<GrantedAuthority>();
String name = authentication.getName();
String password = authentication.getCredentials().toString();
boolean isFind = ldapServices.ldapSearch(name, password);
if (isFind) {
com.domain.User user = userServices.getByUsersEnabled(name);
if (user != null) {
authorities.add(new SimpleGrantedAuthority("ROLE_" + user.getRole().getRole()));
}
return new UsernamePasswordAuthenticationToken(user, password, authorities);
} else return null;
}
@Override
public boolean supports(Class<?> authentication) {
return authentication.equals(UsernamePasswordAuthenticationToken.class);
}
}
// .....
http
.authorizeRequests()
.anyRequest().hasAnyRole(rolesArray)
.and()
.formLogin()
.loginPage("/login")
//important because otherwise it goes in a loop because login page require
// authentication and authentication require login page
.permitAll()
.and()
.exceptionHandling().accessDeniedPage("/403")
.and()
.logout()
.logoutSuccessUrl("/login?logout")
.deleteCookies("JSESSIONID", "JSESSIONID")
.invalidateHttpSession(true)
.permitAll()
.and()
.sessionManagement().invalidSessionUrl("/invalidSession.html").maximumSessions(1)
.expiredUrl("/expired.html");
这是日志的一部分:
2016-07-25 17:39:13 [http-nio-8086-exec-8] DEBUG o.h.l.p.e.p.i.ResultSetProcessorImpl - Starting ResultSet row #0
2016-07-25 17:39:13 [http-nio-8086-exec-8] DEBUG o.h.l.p.e.p.i.EntityReferenceInitializerImpl - On call to EntityIdentifierReaderImpl#resolve, EntityKey was already known; should only happen on root returns with an optional identifier specified
2016-07-25 17:39:13 [http-nio-8086-exec-8] DEBUG o.h.engine.internal.TwoPhaseLoad - Resolving associations for [com.domain.Role#1]
2016-07-25 17:39:13 [http-nio-8086-exec-8] DEBUG o.h.engine.internal.TwoPhaseLoad - Done materializing entity [com.domain.Role#1]
2016-07-25 17:39:13 [http-nio-8086-exec-8] DEBUG o.h.l.e.p.AbstractLoadPlanBasedEntityLoader - Done entity load : com.domain.Role#1
2016-07-25 17:39:13 [http-nio-8086-exec-8] DEBUG o.h.e.t.spi.AbstractTransactionImpl - committing
2016-07-25 17:39:13 [http-nio-8086-exec-8] DEBUG o.h.e.t.i.jdbc.JdbcTransaction - committed JDBC Connection
2016-07-25 17:39:13 [http-nio-8086-exec-8] DEBUG o.h.e.t.i.jdbc.JdbcTransaction - re-enabling autocommit
2016-07-25 17:39:13 [http-nio-8086-exec-8] DEBUG o.h.e.j.i.LogicalConnectionImpl - Releasing JDBC connection
2016-07-25 17:39:13 [http-nio-8086-exec-8] DEBUG o.h.e.j.i.LogicalConnectionImpl - Released JDBC connection
2016-07-25 17:39:13 [http-nio-8086-exec-8] DEBUG o.h.internal.SessionFactoryImpl - Returning a Reference to the SessionFactory
2016-07-25 17:39:13 [http-nio-8086-exec-8] DEBUG o.s.s.w.a.s.CompositeSessionAuthenticationStrategy - Delegating to org.springframework.security.web.authentication.session.ConcurrentSessionControlAuthenticationStrategy@52fffd66
2016-07-25 17:39:13 [http-nio-8086-exec-8] DEBUG o.s.s.w.a.s.CompositeSessionAuthenticationStrategy - Delegating to org.springframework.security.web.authentication.session.ChangeSessionIdAuthenticationStrategy@6b539c7c
2016-07-25 17:39:13 [http-nio-8086-exec-8] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'delegatingApplicationListener'
2016-07-25 17:39:13 [http-nio-8086-exec-8] DEBUG o.s.s.w.a.s.CompositeSessionAuthenticationStrategy - Delegating to org.springframework.security.web.authentication.session.RegisterSessionAuthenticationStrategy@10801ce3
2016-07-25 17:39:13 [http-nio-8086-exec-8] DEBUG o.s.s.c.session.SessionRegistryImpl - Registering session F5738A6748EBBE0D718A50FC3CC55ACF, for principal com.domain.User@21af5fd0
2016-07-25 17:39:13 [http-nio-8086-exec-8] DEBUG o.s.s.w.a.s.CompositeSessionAuthenticationStrategy - Delegating to org.springframework.security.web.csrf.CsrfAuthenticationStrategy@5e273a21
2016-07-25 17:39:13 [http-nio-8086-exec-8] DEBUG o.s.s.w.a.UsernamePasswordAuthenticationFilter - Authentication success. Updating SecurityContextHolder to contain: org.springframework.security.authentication.UsernamePasswordAuthenticationToken@610e8c1e: Principal: com.domain.User@21af5fd0; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@21a2c: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: B71FCF118A338633055BACB1DBD12F74; Granted Authorities: ROLE_ADMIN
2016-07-25 17:39:13 [http-nio-8086-exec-8] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'delegatingApplicationListener'
2016-07-25 17:39:13 [http-nio-8086-exec-8] DEBUG o.s.s.w.a.SavedRequestAwareAuthenticationSuccessHandler - Redirecting to DefaultSavedRequest Url: http://localhost:8086/invalidSession.html
2016-07-25 17:39:13 [http-nio-8086-exec-8] DEBUG o.s.s.web.DefaultRedirectStrategy - Redirecting to 'http://localhost:8086/invalidSession.html'
2016-07-25 17:39:13 [http-nio-8086-exec-8] DEBUG o.s.s.w.h.writers.HstsHeaderWriter - Not injecting HSTS header since it did not match the requestMatcher org.springframework.security.web.header.writers.HstsHeaderWriter$SecureRequestMatcher@6cc5f625
2016-07-25 17:39:13 [http-nio-8086-exec-8] DEBUG o.s.s.w.c.HttpSessionSecurityContextRepository - SecurityContext 'org.springframework.security.core.context.SecurityContextImpl@610e8c1e: Authentication: org.springframework.security.authentication.UsernamePasswordAuthenticationToken@610e8c1e: Principal: com.domain.User@21af5fd0; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@21a2c: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: B71FCF118A338633055BACB1DBD12F74; Granted Authorities: ROLE_ADMIN' stored to HttpSession: 'org.apache.catalina.session.StandardSessionFacade@199c4c42
2016-07-25 17:39:13 [http-nio-8086-exec-8] DEBUG o.s.s.w.c.SecurityContextPersistenceFilter - SecurityContextHolder now cleared, as request processing completed
2016-07-25 17:39:13 [http-nio-8086-exec-9] DEBUG o.s.s.w.u.m.AntPathRequestMatcher - Checking match of request : '/invalidSession.html'; against '/static/**'
2016-07-25 17:39:13 [http-nio-8086-exec-9] DEBUG o.s.s.w.u.m.AntPathRequestMatcher - Checking match of request : '/invalidSession.html'; against '/client/**'
2016-07-25 17:39:13 [http-nio-8086-exec-9] DEBUG o.s.security.web.FilterChainProxy - /invalidSession.html at position 1 of 13 in additional filter chain; firing Filter: 'WebAsyncManagerIntegrationFilter'
2016-07-25 17:39:13 [http-nio-8086-exec-9] DEBUG o.s.security.web.FilterChainProxy - /invalidSession.html at position 2 of 13 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter'
2016-07-25 17:39:13 [http-nio-8086-exec-9] DEBUG o.s.s.w.c.HttpSessionSecurityContextRepository - Obtained a valid SecurityContext from SPRING_SECURITY_CONTEXT: 'org.springframework.security.core.context.SecurityContextImpl@610e8c1e: Authentication: org.springframework.security.authentication.UsernamePasswordAuthenticationToken@610e8c1e: Principal: com.domain.User@21af5fd0; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@21a2c: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: B71FCF118A338633055BACB1DBD12F74; Granted Authorities: ROLE_ADMIN'
2016-07-25 17:39:13 [http-nio-8086-exec-9] DEBUG o.s.security.web.FilterChainProxy - /invalidSession.html at position 3 of 13 in additional filter chain; firing Filter: 'HeaderWriterFilter'
2016-07-25 17:39:13 [http-nio-8086-exec-9] DEBUG o.s.security.web.FilterChainProxy - /invalidSession.html at position 4 of 13 in additional filter chain; firing Filter: 'CsrfFilter'
2016-07-25 17:39:13 [http-nio-8086-exec-9] DEBUG o.s.security.web.FilterChainProxy - /invalidSession.html at position 5 of 13 in additional filter chain; firing Filter: 'LogoutFilter'
2016-07-25 17:39:13 [http-nio-8086-exec-9] DEBUG o.s.s.w.u.m.AntPathRequestMatcher - Request 'GET /invalidSession.html' doesn't match 'POST /logout
2016-07-25 17:39:13 [http-nio-8086-exec-9] DEBUG o.s.security.web.FilterChainProxy - /invalidSession.html at position 6 of 13 in additional filter chain; firing Filter: 'UsernamePasswordAuthenticationFilter'
2016-07-25 17:39:13 [http-nio-8086-exec-9] DEBUG o.s.s.w.u.m.AntPathRequestMatcher - Request 'GET /invalidSession.html' doesn't match 'POST /login
2016-07-25 17:39:13 [http-nio-8086-exec-9] DEBUG o.s.security.web.FilterChainProxy - /invalidSession.html at position 7 of 13 in additional filter chain; firing Filter: 'ConcurrentSessionFilter'
2016-07-25 17:39:13 [http-nio-8086-exec-9] DEBUG o.s.security.web.FilterChainProxy - /invalidSession.html at position 8 of 13 in additional filter chain; firing Filter: 'RequestCacheAwareFilter'
2016-07-25 17:39:13 [http-nio-8086-exec-9] DEBUG o.s.s.w.s.DefaultSavedRequest - pathInfo: both null (property equals)
2016-07-25 17:39:13 [http-nio-8086-exec-9] DEBUG o.s.s.w.s.DefaultSavedRequest - queryString: both null (property equals)
2016-07-25 17:39:13 [http-nio-8086-exec-9] DEBUG o.s.s.w.s.DefaultSavedRequest - requestURI: arg1=/invalidSession.html; arg2=/invalidSession.html (property equals)
2016-07-25 17:39:13 [http-nio-8086-exec-9] DEBUG o.s.s.w.s.DefaultSavedRequest - serverPort: arg1=8086; arg2=8086 (property equals)
2016-07-25 17:39:13 [http-nio-8086-exec-9] DEBUG o.s.s.w.s.DefaultSavedRequest - requestURL: arg1=http://localhost:8086/invalidSession.html; arg2=http://localhost:8086/invalidSession.html (property equals)
2016-07-25 17:39:13 [http-nio-8086-exec-9] DEBUG o.s.s.w.s.DefaultSavedRequest - scheme: arg1=http; arg2=http (property equals)
2016-07-25 17:39:13 [http-nio-8086-exec-9] DEBUG o.s.s.w.s.DefaultSavedRequest - serverName: arg1=localhost; arg2=localhost (property equals)
2016-07-25 17:39:13 [http-nio-8086-exec-9] DEBUG o.s.s.w.s.DefaultSavedRequest - contextPath: arg1=; arg2= (property equals)
2016-07-25 17:39:13 [http-nio-8086-exec-9] DEBUG o.s.s.w.s.DefaultSavedRequest - servletPath: arg1=/invalidSession.html; arg2=/invalidSession.html (property equals)
2016-07-25 17:39:13 [http-nio-8086-exec-9] DEBUG o.s.s.w.s.HttpSessionRequestCache - Removing DefaultSavedRequest from session if present
2016-07-25 17:39:13 [http-nio-8086-exec-9] DEBUG o.s.security.web.FilterChainProxy - /invalidSession.html at position 9 of 13 in additional filter chain; firing Filter: 'SecurityContextHolderAwareRequestFilter'
2016-07-25 17:39:13 [http-nio-8086-exec-9] DEBUG o.s.security.web.FilterChainProxy - /invalidSession.html at position 10 of 13 in additional filter chain; firing Filter: 'AnonymousAuthenticationFilter'
2016-07-25 17:39:13 [http-nio-8086-exec-9] DEBUG o.s.s.w.a.AnonymousAuthenticationFilter - SecurityContextHolder not populated with anonymous token, as it already contained: 'org.springframework.security.authentication.UsernamePasswordAuthenticationToken@610e8c1e: Principal: com.domain.User@21af5fd0; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@21a2c: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: B71FCF118A338633055BACB1DBD12F74; Granted Authorities: ROLE_ADMIN'
2016-07-25 17:39:13 [http-nio-8086-exec-9] DEBUG o.s.security.web.FilterChainProxy - /invalidSession.html at position 11 of 13 in additional filter chain; firing Filter: 'SessionManagementFilter'
2016-07-25 17:39:13 [http-nio-8086-exec-9] DEBUG o.s.security.web.FilterChainProxy - /invalidSession.html at position 12 of 13 in additional filter chain; firing Filter: 'ExceptionTranslationFilter'
2016-07-25 17:39:13 [http-nio-8086-exec-9] DEBUG o.s.security.web.FilterChainProxy - /invalidSession.html at position 13 of 13 in additional filter chain; firing Filter: 'FilterSecurityInterceptor'
2016-07-25 17:39:13 [http-nio-8086-exec-9] DEBUG o.s.s.w.u.m.AntPathRequestMatcher - Request 'GET /invalidSession.html' doesn't match 'POST /logout
2016-07-25 17:39:13 [http-nio-8086-exec-9] DEBUG o.s.s.w.a.i.FilterSecurityInterceptor - Secure object: FilterInvocation: URL: /invalidSession.html; Attributes: [hasAnyRole('ROLE_ADMIN','ROLE_FLEET_ENG','ROLE_SUPPLIER','ROLE_VIEW_ENG','ROLE_DART')]
2016-07-25 17:39:13 [http-nio-8086-exec-9] DEBUG o.s.s.w.a.i.FilterSecurityInterceptor - Previously Authenticated: org.springframework.security.authentication.UsernamePasswordAuthenticationToken@610e8c1e: Principal: com.domain.User@21af5fd0; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@21a2c: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: B71FCF118A338633055BACB1DBD12F74; Granted Authorities: ROLE_ADMIN
2016-07-25 17:39:13 [http-nio-8086-exec-9] DEBUG o.s.s.access.vote.AffirmativeBased - Voter: org.springframework.security.web.access.expression.WebExpressionVoter@2c9803fe, returned: 1
2016-07-25 17:39:13 [http-nio-8086-exec-9] DEBUG o.s.s.w.a.i.FilterSecurityInterceptor - Authorization successful
2016-07-25 17:39:13 [http-nio-8086-exec-9] DEBUG o.s.s.w.a.i.FilterSecurityInterceptor - RunAsManager did not change Authentication object
2016-07-25 17:39:13 [http-nio-8086-exec-9] DEBUG o.s.security.web.FilterChainProxy - /invalidSession.html reached end of additional filter chain; proceeding with original chain
2016-07-25 17:39:13 [http-nio-8086-exec-9] DEBUG o.s.web.servlet.DispatcherServlet - DispatcherServlet with name 'dispatcher' processing GET request for [/invalidSession.html]
2016-07-25 17:39:13 [http-nio-8086-exec-9] DEBUG o.s.w.s.m.m.a.RequestMappingHandlerMapping - Looking up handler method for path /invalidSession.html
2016-07-25 17:39:13 [http-nio-8086-exec-9] DEBUG o.s.w.s.m.m.a.RequestMappingHandlerMapping - Did not find handler method for [/invalidSession.html]
2016-07-25 17:39:13 [http-nio-8086-exec-9] WARN o.s.web.servlet.PageNotFound - No mapping found for HTTP request with URI [/invalidSession.html] in DispatcherServlet with name 'dispatcher'
2016-07-25 17:39:13 [http-nio-8086-exec-9] DEBUG o.s.s.w.h.writers.HstsHeaderWriter - Not injecting HSTS header since it did not match the requestMatcher org.springframework.security.web.header.writers.HstsHeaderWriter$SecureRequestMatcher@6cc5f625
2016-07-25 17:39:13 [http-nio-8086-exec-9] DEBUG o.s.web.servlet.DispatcherServlet - Successfully completed request
2016-07-25 17:39:13 [http-nio-8086-exec-9] DEBUG o.s.s.w.a.ExceptionTranslationFilter - Chain processed normally
2016-07-25 17:39:13 [http-nio-8086-exec-9] DEBUG o.s.s.w.c.SecurityContextPersistenceFilter - SecurityContextHolder now cleared, as request processing completed
我可以看到在我的html登录页面中出现了隐藏的CSRF,但是第一次登录会将我重定向到invalidSession页面,但验证工作正常,因为如果那时我从网址中删除了invalidSession.html
我在我的第一次验证页。
你怎么看?问题是什么?
我也试图添加隐藏的CSRF,但问题是一样的,我有两次转义为html代码的CSRF令牌。
即使maximumSessions似乎也不起作用,我可以使用两个不同的浏览器登录而没有任何问题
更新:我注意到如果我使用f5更新网址,那么问题就在于第一页。最大会话的问题仍然存在