我正在使用Spring 3.2 Milestone 1来实现long polling的服务.但是由于某些原因,Spring Security(3.1.2)会在第一个延迟结果过期(达到asynctimeout并且tomcat响应http.200)后立即清除SPRING_Security_CONTEXT.一些响应被发送回客户端.使用Spring Security 3.1.0只会在某些情况下发生(httpS和客户端位于某些硬件防火墙之后),而对于3.1.2来说,它总是会发生(在满足第一个DefferedResult之后)!
这是日志相关部分的调试输出
DEBUG: org.springframework.security.web.util.AntPathRequestMatcher - Checking match of request : '/updates/events'; against '/login*'DEBUG: org.springframework.security.web.FilterChainProxy - /updates/events?clIEntID=nvrs1346481959144×tamp=0&_=1346481959526 at position 1 of 11 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter'DEBUG: org.springframework.security.web.context.httpSessionSecurityContextRepository - Obtained a valID SecurityContext from SPRING_Security_CONTEXT: 'org.springframework.security.core.context.SecurityContextImpl@fc783ee2: Authentication: org.springframework.security.authentication.UsernamePasswordAuthenticationToken@fc783ee2: Principal: org.springframework.security.core.userdetails.User@33ca09: Username: nvrs; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted AuthoritIEs: admin; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@0: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionID: 46EC76439E921FE347EC48ECF71C1258; Granted AuthoritIEs: admin'DEBUG: org.springframework.security.web.FilterChainProxy - /updates/events?clIEntID=nvrs1346481959144×tamp=0&_=1346481959526 at position 2 of 11 in additional filter chain; firing Filter: 'logoutFilter'DEBUG: org.springframework.security.web.FilterChainProxy - /updates/events?clIEntID=nvrs1346481959144×tamp=0&_=1346481959526 at position 3 of 11 in additional filter chain; firing Filter: 'UsernamePasswordAuthenticationFilter'DEBUG: org.springframework.security.web.FilterChainProxy - /updates/events?clIEntID=nvrs1346481959144×tamp=0&_=1346481959526 at position 4 of 11 in additional filter chain; firing Filter: 'BasicAuthenticationFilter'DEBUG: org.springframework.security.web.FilterChainProxy - /updates/events?clIEntID=nvrs1346481959144×tamp=0&_=1346481959526 at position 5 of 11 in additional filter chain; firing Filter: 'RequestCacheAwareFilter'DEBUG: org.springframework.security.web.FilterChainProxy - /updates/events?clIEntID=nvrs1346481959144×tamp=0&_=1346481959526 at position 6 of 11 in additional filter chain; firing Filter: 'SecurityContextHolderAwareRequestFilter'DEBUG: org.springframework.security.web.FilterChainProxy - /updates/events?clIEntID=nvrs1346481959144×tamp=0&_=1346481959526 at position 7 of 11 in additional filter chain; firing Filter: 'RememberMeAuthenticationFilter'DEBUG: org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationFilter - SecurityContextHolder not populated with remember-me token,as it already contained: 'org.springframework.security.authentication.UsernamePasswordAuthenticationToken@fc783ee2: Principal: org.springframework.security.core.userdetails.User@33ca09: Username: nvrs; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted AuthoritIEs: admin; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@0: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionID: 46EC76439E921FE347EC48ECF71C1258; Granted AuthoritIEs: admin'DEBUG: org.springframework.security.web.FilterChainProxy - /updates/events?clIEntID=nvrs1346481959144×tamp=0&_=1346481959526 at position 8 of 11 in additional filter chain; firing Filter: 'AnonymousAuthenticationFilter'DEBUG: org.springframework.security.web.authentication.AnonymousAuthenticationFilter - SecurityContextHolder not populated with anonymous token,as it already contained: 'org.springframework.security.authentication.UsernamePasswordAuthenticationToken@fc783ee2: Principal: org.springframework.security.core.userdetails.User@33ca09: Username: nvrs; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted AuthoritIEs: admin; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@0: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionID: 46EC76439E921FE347EC48ECF71C1258; Granted AuthoritIEs: admin'DEBUG: org.springframework.security.web.FilterChainProxy - /updates/events?clIEntID=nvrs1346481959144×tamp=0&_=1346481959526 at position 9 of 11 in additional filter chain; firing Filter: 'SessionManagementFilter'DEBUG: org.springframework.security.web.FilterChainProxy - /updates/events?clIEntID=nvrs1346481959144×tamp=0&_=1346481959526 at position 10 of 11 in additional filter chain; firing Filter: 'ExceptionTranslationFilter'DEBUG: org.springframework.security.web.FilterChainProxy - /updates/events?clIEntID=nvrs1346481959144×tamp=0&_=1346481959526 at position 11 of 11 in additional filter chain; firing Filter: 'FilterSecurityInterceptor'DEBUG: org.springframework.security.web.util.AntPathRequestMatcher - Checking match of request : '/updates/events'; against '/updates/**'DEBUG: org.springframework.security.web.access.intercept.FilterSecurityInterceptor - Secure object: FilterInvocation: URL: /updates/events?clIEntID=nvrs1346481959144×tamp=0&_=1346481959526; Attributes: [hasAnyRole('admin','MANAGER','INTERNAL')]DEBUG: org.springframework.security.web.access.intercept.FilterSecurityInterceptor - PrevIoUsly Authenticated: org.springframework.security.authentication.UsernamePasswordAuthenticationToken@fc783ee2: Principal: org.springframework.security.core.userdetails.User@33ca09: Username: nvrs; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted AuthoritIEs: admin; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@0: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionID: 46EC76439E921FE347EC48ECF71C1258; Granted AuthoritIEs: adminDEBUG: org.springframework.security.access.Vote.AffirmativeBased - Voter: org.springframework.security.web.access.Expression.WebExpressionVoter@52bf21bf,returned: 1DEBUG: org.springframework.security.web.access.intercept.FilterSecurityInterceptor - Authorization successfulDEBUG: org.springframework.security.web.access.intercept.FilterSecurityInterceptor - RunAsManager dID not change Authentication objectDEBUG: org.springframework.security.web.FilterChainProxy - /updates/events?clIEntID=nvrs1346481959144×tamp=0&_=1346481959526 reached end of additional filter chain; proceeding with original chainDEBUG: org.springframework.security.web.access.ExceptionTranslationFilter - Chain processed normallyDEBUG: org.springframework.security.web.context.SecurityContextPersistenceFilter - SecurityContextHolder Now cleared,as request processing completedDEBUG: org.springframework.security.web.access.ExceptionTranslationFilter - Chain processed normallyDEBUG: org.springframework.security.web.context.SecurityContextPersistenceFilter - SecurityContextHolder Now cleared,as request processing completedDEBUG: org.springframework.security.web.util.AntPathRequestMatcher - Checking match of request : '/updates/events'; against '/login*'DEBUG: org.springframework.security.web.util.AntPathRequestMatcher - Checking match of request : '/updates/events'; against '/resources/CSS/**'DEBUG: org.springframework.security.web.util.AntPathRequestMatcher - Checking match of request : '/updates/events'; against '/resources/images/**'DEBUG: org.springframework.security.web.util.AntPathRequestMatcher - Checking match of request : '/updates/events'; against '/resources/*'DEBUG: org.springframework.security.web.FilterChainProxy - /updates/events?clIEntID=nvrs1346481959144×tamp=0&_=1346481985081 at position 1 of 11 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter'DEBUG: org.springframework.security.web.context.httpSessionSecurityContextRepository - httpSession returned null object for SPRING_Security_CONTEXTDEBUG: org.springframework.security.web.context.httpSessionSecurityContextRepository - No SecurityContext was available from the httpSession: org.apache.catalina.session.StandardSessionFacade@61ed10f7. A new one will be created.
如果仔细查看输出,将看到第一个长轮询请求“ / updates / events?”.已正确处理-授予访问权限,但随后会清除spring安全上下文,如您从“ httpSession为SPRING_Security_CONTEXT返回httpSession返回空对象”行中看到的那样,它是由第一个URL过期后客户端对该URL的另一个请求触发的事件触发非空响应.
我想在这里指出,我所有的自定义过滤器均已禁用,并且在处理长轮询请求时,我将DefferedResult存储到Map中,其中sessionID-clIEntID(对于每个页面实例浏览器选项卡都是唯一的)作为访问它的键,在收到JMS消息的情况下将结果发送给客户端.
Spring框架3.2 M1和最新的3.2快照版本与Spring Security 3.1.2或其在Tomcat 7.0.28 / 7.0.29(默认和APR连接器)下各自最新的快照结合使用时出现此问题.
最佳答案借助调试器,我得出了以下结论:设置DefferedResult后,将调用org.springframework.security.web.context.SaveContextOnUpdateOrErrorResponseWrapper的flush()方法,该方法通过代理调用org.springframework.security.web.context.httpSessionSecurityContextRepository的saveContext().
@OverrIDeprotected voID saveContext(SecurityContext context) { final Authentication authentication = context.getAuthentication(); httpSession httpSession = request.getSession(false); // See SEC-776 if (authentication == null || authenticationTrustResolver.isAnonymous(authentication)) { if (logger.isDeBUGEnabled()) { logger.deBUG("SecurityContext is empty or contents are anonymous - context will not be stored in httpSession."); } if (httpSession != null && !contextObject.equals(contextBeforeExecution)) { // SEC-1587 A non-anonymous context may still be in the session // SEC-1735 remove if the contextBeforeExecution was not anonymous httpSession.removeAttribute(springSecurityContextKey); } return; }
由于身份验证对象为空(由于已清除spring安全上下文,因此该行)
httpSession.removeAttribute(springSecurityContextKey)从会话中删除SPRING_Security_CONTEXT,并且该用户在没有安全上下文的会话中导致下一个请求结果,因此将用户重定向到登录名.
除非我在这里缺少明显的东西,否则这是异步请求的破坏者.我想知道Spring Security团队是否知道这个问题,是否计划在3.2发布之前修复它.
同时,是否有人对适当的解决方案有任何建议?
编辑:目前,作为临时解决方案,我通过在异步请求的情况下不编辑会话来解决此问题.具体来说,我修改了从以下位置刷新securityContext的检查:
if (httpSession != null && !contextObject.equals(contextBeforeExecution))
至
if (httpSession != null && !contextObject.equals(contextBeforeExecution) && this.request.getAttribute("javax.servlet.async.request_uri") == null)
谢谢 总结
以上是内存溢出为你收集整理的Spring 3.2长时间轮询导致清除了SPRING_SECURITY_CONTEXT 全部内容,希望文章能够帮你解决Spring 3.2长时间轮询导致清除了SPRING_SECURITY_CONTEXT 所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)