注销在Spring Security中不起作用

时间:2016-11-30 09:54:47

标签: java spring-security

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

弹簧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}"/>

3 个答案:

答案 0 :(得分:4)

如果使用CSRF,则必须使用HTTP POST(在JSP中使用<form>而不是HTTP GET(在JSP中使用<a>) ,请参阅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>

答案 1 :(得分:1)

您也可以在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发出get请求,但它需要一个带有POST请求的CSRF令牌,因此它将返回您收到的错误消息。< / p>

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

答案 2 :(得分:0)

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

    @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 out 18.5.3退出