【问题标题】:spring security j_spring_security logout problemspring security j_spring_security 注销问题
【发布时间】:2026-02-13 13:35:02
【问题描述】:

我正在研究 Spring Security。但 j_spring_security servet 似乎不起作用。我如何调试问题,或者至少寻找根本原因?我没有看到任何有用的日志文件...

<?xml version="1.0" encoding="UTF-8"?>

 <!--
  - Sample namespace-based configuration
  -
  -->

<beans:beans xmlns="http://www.springframework.org/schema/security"
 xmlns:beans="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
                        http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.0.xsd">

 <global-method-security pre-post-annotations="enabled">
  <!--
   AspectJ pointcut expression that locates our "post" method and
   applies security that way <protect-pointcut expression="execution(*
   bigbank.*Service.post*(..))" access="ROLE_TELLER"/>
  -->
 </global-method-security>

 <http use-expressions="true">
  <intercept-url pattern="/" access="permitAll" />
  <intercept-url pattern="/login/**" filters="none" />
  <intercept-url pattern="/static/**" filters="none" />
  <intercept-url pattern="/**" access="isAuthenticated()" />
  <form-login login-page="/login/login.jsp"
   default-target-url="/fileList.do" authentication-failure-url="/login/login.jsp?login_error=1" />
  <logout logout-success-url="/login/logout_success.jsp" />
  <!--
   Uncomment to enable X509 client authentication support <x509 />
  -->
  <!-- Uncomment to limit the number of sessions a user can have -->
  <session-management invalid-session-url="/timeout.jsp">
   <concurrency-control max-sessions="1"
    error-if-maximum-exceeded="true" />
  </session-management>
 </http>

编辑

然后我检查了错误,这里是日志文件的一部分

当我退出时

DEBUG [http-8080-2] (FilterChainProxy.java:175) - Converted URL to lowercase, from: '/j_spring_security_logout'; to: '/j_spring_security_logout'
DEBUG [http-8080-2] (FilterChainProxy.java:182) - Candidate is: '/j_spring_security_logout'; pattern is /login/**; matched=false
DEBUG [http-8080-2] (FilterChainProxy.java:175) - Converted URL to lowercase, from: '/j_spring_security_logout'; to: '/j_spring_security_logout'
DEBUG [http-8080-2] (FilterChainProxy.java:182) - Candidate is: '/j_spring_security_logout'; pattern is /static/**; matched=false
DEBUG [http-8080-2] (FilterChainProxy.java:175) - Converted URL to lowercase, from: '/j_spring_security_logout'; to: '/j_spring_security_logout'
DEBUG [http-8080-2] (FilterChainProxy.java:182) - Candidate is: '/j_spring_security_logout'; pattern is /**; matched=true
DEBUG [http-8080-2] (FilterChainProxy.java:350) - /j_spring_security_logout at position 1 of 10 in additional filter chain; firing Filter: 'org.springframework.security.web.session.ConcurrentSessionFilter@40ece0'
DEBUG [http-8080-2] (FilterChainProxy.java:350) - /j_spring_security_logout at position 2 of 10 in additional filter chain; firing Filter: 'org.springframework.security.web.context.SecurityContextPersistenceFilter@1041876'
DEBUG [http-8080-2] (HttpSessionSecurityContextRepository.java:165) - Obtained a valid SecurityContext from SPRING_SECURITY_CONTEXT: 'org.springframework.security.core.context.SecurityContextImpl@86583dd2: Authentication: org.springframework.security.authentication.UsernamePasswordAuthenticationToken@86583dd2: Principal: org.springframework.security.core.userdetails.User@2117c700: Username: rod; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_SUPERVISOR,ROLE_TELLER,ROLE_USER; Password: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@fffe3f86: RemoteIpAddress: 127.0.0.1; SessionId: C6056CE774DE3568943D98A05ABCC744; Granted Authorities: ROLE_SUPERVISOR, ROLE_TELLER, ROLE_USER'
DEBUG [http-8080-2] (FilterChainProxy.java:350) - /j_spring_security_logout at position 3 of 10 in additional filter chain; firing Filter: 'org.springframework.security.web.authentication.logout.LogoutFilter@174a6e2'
DEBUG [http-8080-2] (LogoutFilter.java:93) - Logging out user 'org.springframework.security.authentication.UsernamePasswordAuthenticationToken@86583dd2: Principal: org.springframework.security.core.userdetails.User@2117c700: Username: rod; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_SUPERVISOR,ROLE_TELLER,ROLE_USER; Password: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@fffe3f86: RemoteIpAddress: 127.0.0.1; SessionId: C6056CE774DE3568943D98A05ABCC744; Granted Authorities: ROLE_SUPERVISOR, ROLE_TELLER, ROLE_USER' and transferring to logout destination
DEBUG [http-8080-2] (AbstractAuthenticationTargetUrlRequestHandler.java:93) - Using default Url: /login/logout_success.jsp
DEBUG [http-8080-2] (DefaultRedirectStrategy.java:34) - Redirecting to '/crvWeb/login/logout_success.jsp'
DEBUG [http-8080-2] (HttpSessionSecurityContextRepository.java:359) - HttpSession is now null, but was not null at start of request; session was invalidated, so do not create a new session
DEBUG [http-8080-2] (SecurityContextPersistenceFilter.java:89) - SecurityContextHolder now cleared, as request processing completed
DEBUG [http-8080-2] (FilterChainProxy.java:175) - Converted URL to lowercase, from: '/login/logout_success.jsp'; to: '/login/logout_success.jsp'
DEBUG [http-8080-2] (FilterChainProxy.java:182) - Candidate is: '/login/logout_success.jsp'; pattern is /login/**; matched=true
DEBUG [http-8080-2] (FilterChainProxy.java:139) -  has an empty filter list

然后再次登录。 spring 说我有一个活动会话并且不允许登录

注意日志中的异常 原因:已超出此主体的最大会话数 1。

DEBUG [http-8080-2] (FilterChainProxy.java:175) - Converted URL to lowercase, from: '/j_spring_security_check'; to: '/j_spring_security_check'
DEBUG [http-8080-2] (FilterChainProxy.java:182) - Candidate is: '/j_spring_security_check'; pattern is /login/**; matched=false
DEBUG [http-8080-2] (FilterChainProxy.java:175) - Converted URL to lowercase, from: '/j_spring_security_check'; to: '/j_spring_security_check'
DEBUG [http-8080-2] (FilterChainProxy.java:182) - Candidate is: '/j_spring_security_check'; pattern is /static/**; matched=false
DEBUG [http-8080-2] (FilterChainProxy.java:175) - Converted URL to lowercase, from: '/j_spring_security_check'; to: '/j_spring_security_check'
DEBUG [http-8080-2] (FilterChainProxy.java:182) - Candidate is: '/j_spring_security_check'; pattern is /**; matched=true
DEBUG [http-8080-2] (FilterChainProxy.java:350) - /j_spring_security_check at position 1 of 10 in additional filter chain; firing Filter: 'org.springframework.security.web.session.ConcurrentSessionFilter@40ece0'
DEBUG [http-8080-2] (FilterChainProxy.java:350) - /j_spring_security_check at position 2 of 10 in additional filter chain; firing Filter: 'org.springframework.security.web.context.SecurityContextPersistenceFilter@1041876'
DEBUG [http-8080-2] (HttpSessionSecurityContextRepository.java:141) - HttpSession returned null object for SPRING_SECURITY_CONTEXT
DEBUG [http-8080-2] (HttpSessionSecurityContextRepository.java:87) - No SecurityContext was available from the HttpSession: org.apache.catalina.session.StandardSessionFacade@e3fda4. A new one will be created.
DEBUG [http-8080-2] (FilterChainProxy.java:350) - /j_spring_security_check at position 3 of 10 in additional filter chain; firing Filter: 'org.springframework.security.web.authentication.logout.LogoutFilter@174a6e2'
DEBUG [http-8080-2] (FilterChainProxy.java:350) - /j_spring_security_check at position 4 of 10 in additional filter chain; firing Filter: 'org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter@1786a3c'
DEBUG [http-8080-2] (AbstractAuthenticationProcessingFilter.java:193) - Request is to process authentication
DEBUG [http-8080-2] (ProviderManager.java:117) - Authentication attempt using org.springframework.security.authentication.dao.DaoAuthenticationProvider
DEBUG [http-8080-2] (AbstractAuthenticationProcessingFilter.java:318) - Authentication request failed: org.springframework.security.web.authentication.session.SessionAuthenticationException: Maximum sessions of 1 for this principal exceeded
DEBUG [http-8080-2] (AbstractAuthenticationProcessingFilter.java:319) - Updated SecurityContextHolder to contain null Authentication
DEBUG [http-8080-2] (AbstractAuthenticationProcessingFilter.java:320) - Delegating to authentication failure handlerorg.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler@21447f
DEBUG [http-8080-2] (SimpleUrlAuthenticationFailureHandler.java:56) - Redirecting to /login/login.jsp?login_error=1
DEBUG [http-8080-2] (DefaultRedirectStrategy.java:34) - Redirecting to '/crvWeb/login/login.jsp?login_error=1'
DEBUG [http-8080-2] (SecurityContextPersistenceFilter.java:89) - SecurityContextHolder now cleared, as request processing completed
DEBUG [http-8080-2] (FilterChainProxy.java:175) - Converted URL to lowercase, from: '/login/login.jsp'; to: '/login/login.jsp'
DEBUG [http-8080-2] (FilterChainProxy.java:182) - Candidate is: '/login/login.jsp'; pattern is /login/**; matched=true
DEBUG [http-8080-2] (FilterChainProxy.java:139) -  has an empty filter list

为什么我的注销不起作用?如何查找原因?

【问题讨论】:

    标签: java spring spring-security


    【解决方案1】:

    Spring Security 需要 &lt;listener&gt;web.xml 中才能启用 &lt;concurrency-control&gt;see docs

    <listener>
        <listener-class>
            org.springframework.security.web.session.HttpSessionEventPublisher
        </listener-class>
    </listener>
    

    【讨论】:

    • 这几乎肯定是这里的问题。注销时销毁会话时,需要更新 Spring Security 会话注册表。 Spring Security FAQ 中也有一个关于此的条目。
    【解决方案2】:

    我没有看到任何有用的日志文件...

    您是否已在 Web 应用中配置日志记录以将日志记录级别设置为 DEBUG? Spring / SpringSecurity 在那个级别输出了很多有用的东西。

    编辑

    您的日志文件通常写入$CATALINA_HOME/logs,但这取决于您的日志记录属性。

    配置 webapp 的日志记录(假设 log4j)的简单方法是将 log4j.propertieslog4j.xml 文件放入 webapp 的 /WEB-INF/classes 目录。

    如果你想通过类路径访问资源文件,它们也需要在类目录中。但是,如果您可以通过其他方式访问它们,它们可能位于 webapp 树中的任何位置。 (您甚至可以将资源放在树之外,但是部署它们时会遇到问题。)

    这些问题都在相关的 Tomcat 和 Log4j 文档中得到了更全面的解决。也可能在 Spring“入门”文档中。

    【讨论】:

    • 还有一个问题:如何定义资源路径,我们在哪里实践?
    • 我不明白你在说什么。你说的“他们”是什么?
    • 我说的是资源文件。在开发模式和生产模式下,我们将资源文件指向哪里?并且需要任何配置?还是只使用默认值?以及日志文件将指向哪里?
    • 嗯,你还没说你用的是什么web容器,什么构建工具等等等等。
    • 对不起。我在 Tomcat 6,Eclipse,在 Windows 上开发。而且我还没有使用构建工具。我想我会在以后真正生产时制作一些 ant 脚本。