2016-11-30 128 views
1

我正在用Spring Security 4.0编写安全应用程序。作为我想做出注销电话的一部分。它仅仅是提供不支持请求方法'POST'。这里是我的代码:注销在Spring Security中不起作用

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

回答

4

如果使用CSRF,你必须使用HTTP POST(在你的JSP一个<form>),而不是HTTP GET(在你的JSP一个<a>),见Spring Security Reference

18.5.3记录Out

添加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> 
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,则必须使用帖子来请求注销URL。在春季安全4中,CSRF默认打开。这些文件将给你更多的信息。 18.5.3 Logging out 18.5.3注销

+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> 

你的情况,你是不是提交表单,你只是一个GET请求j_spring_security_logout但它需要一个CSRF令牌POST请求,所以它会返回您收到的错误消息。

编辑:取消您从之前的答案中所做的更改,因为这只是对已有内容的修改。