【问题标题】:Logout is not working in Spring Security注销在 Spring Security 中不起作用
【发布时间】:2016-11-30 18:55:50
【问题描述】:

我正在使用 Spring Security 4.0 编写一个安全应用程序。作为其中的一部分,我想进行注销呼叫。它只是提供不支持的请求方法'POST'。这是我的代码:

spring-security.xml

<security:http  auto-config="true">
    <security:access-denied-handler error-page="/denied"/>
        <security:form-login login-page="/login"
        username-parameter="j_username"
        password-parameter="j_password"
        login-processing-url="/j_spring_security_check"
        authentication-failure-url="/login?failed=true" 
        default-target-url="/home" always-use-default-target="true"/>
        <security:custom-filter ref="secfilter" before="FILTER_SECURITY_INTERCEPTOR" />

        <security:logout invalidate-session="true" logout-url="/j_spring_security_logout" logout-success-url="/login"/>
        <!-- <security:logout  logout-url="/j_spring_security_logout" logout-success-url="/login"/> -->

    <security:csrf /> 
</security:http>

jsp

<a href="j_spring_security_logout">  <button class="logoutbtn">logout</button></a>
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>

【问题讨论】:

    标签: java spring-security


    【解决方案1】:

    如果您使用 CSRF,则必须使用 HTTP POST(在您的 JSP 中带有 &lt;form&gt;)而不是 HTTP GET(在您的 JSP 中带有 &lt;a&gt;),请参阅Spring Security Reference

    18.5.3 退出

    添加 CSRF 将更新 LogoutFilter 以仅使用 HTTP POST。这可确保注销需要 CSRF 令牌,并且恶意用户无法强制注销您的用户。

    一种方法是使用表单注销。如果你真的想要一个链接,你可以使用 JavaScript 让链接执行 POST(即可能在隐藏表单上)。对于禁用了 JavaScript 的浏览器,您可以选择让该链接将用户带到将执行 POST 的注销确认页面。

    例如,见Spring Security Reference:

    37.5.1 自动令牌包含

    Spring Security 将自动在使用 Spring MVC 表单标签的表单中包含 CSRF 令牌。例如下面的 JSP:

    <jsp:root xmlns:jsp="http://java.sun.com/JSP/Page"
        xmlns:c="http://java.sun.com/jsp/jstl/core"
        xmlns:form="http://www.springframework.org/tags/form" version="2.0">
        <jsp:directive.page language="java" contentType="text/html" />
    <html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
        <!-- ... -->
    
        <c:url var="logoutUrl" value="/logout"/>
        <form:form action="${logoutUrl}"
                method="post">
        <input type="submit"
                   value="Log out" />
        <input type="hidden"
                    name="${_csrf.parameterName}"
                    value="${_csrf.token}"/>
        </form:form>
    
        <!-- ... -->
    </html>
    </jsp:root>
    

    【讨论】:

    • 你好,如果我使用 AngularJS 作为前端,我如何从那里通过帖子调用注销?
    【解决方案2】:

    您也可以在您的 JSP 中尝试此操作,因为我认为您的 JSP 不正确。将您给定的代码替换为以下代码:

    <form action="/j_spring_security_logout">
    
        <input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>
        <input type="submit" value="logout">
    
    </form>
    

    在您的情况下,您没有提交表单,您只是向j_spring_security_logout 发出获取请求,但它需要一个带有 POST 请求的 CSRF 令牌,因此它会返回您收到的错误消息。

    编辑:撤消您对上一个答案所做的更改,因为这只是对您已有的内容的修改。

    【讨论】:

      【解决方案3】:

      我在我的项目中解决了这个问题。代码如下:

          @RequestMapping(value="/j_spring_security_logout", method = RequestMethod.GET)
          public String logoutPage (HttpServletRequest request, HttpServletResponse response) {
              Authentication auth = SecurityContextHolder.getContext().getAuthentication();
              if (auth != null){
                  new SecurityContextLogoutHandler().logout(request, response, auth);
                  logger.info("logout ok");
              }
              return "redirect";//You can redirect wherever you want, but generally it's a good practice to show login screen again.
          }
      


      不知道你能不能接受这种方式。 如果你打开 CSRF,你必须使用 post 请求注销 url。在spring security4中,CSRF默认开启。该文件将为您提供更多信息。 18.5.3 Logging out18.5.3 退出

      【讨论】:

      • 它对我有用,但我不明白这段代码。你能给我一些解释吗?它会使会话无效
      猜你喜欢
      • 2013-05-24
      • 2011-10-05
      • 2011-08-20
      • 2018-06-23
      • 2013-02-15
      • 1970-01-01
      • 2014-05-21
      • 2016-09-30
      • 2016-02-04
      相关资源
      最近更新 更多