我正在使用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}"/>
答案 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退出