Spring Security:注销不起作用 - “请求的资源不可用”

Posted

技术标签:

【中文标题】Spring Security:注销不起作用 - “请求的资源不可用”【英文标题】:Spring Security: Logout Isn't working - "requested resource not available" 【发布时间】:2016-02-04 03:22:06 【问题描述】:

所以,我正在尝试让我的第一个练习应用程序与 Spring Security 一起工作。在继续进行更复杂的实现之前,这只是一个简单的测试,看看我是否可以让基础工作正常。

我正在使用 Spring Security 4 顺便说一句,Spring 4.2.2。

现在,我有一个欢迎页面和一个管理页面。尝试访问管理页面被拦截并重定向到默认的 Spring Security 登录表单。从那里,我可以登录并通过身份验证访问管理页面。

在管理页面上,我有一个注销链接。这就是它出错的地方。我现在有两个注销链接,我尝试了两种不同的方法来完成这项工作。

第一个是一个简单的 URL。它使用标签,其中包含 JSTL 标签。我正在尝试在那里调用注销 URL。当我这样做时,我得到一个 HTTP 状态 404 页面,其中描述说请求的资源不可用。

第二种方式是使用表格。我尝试在表单中有一个提交按钮,表单的操作属性设置为注销 URL,方法设置为发布。

这给了我一个更复杂的错误,我将在这里复制并粘贴:

标题:HTTP 状态 403 - 在请求参数“_csrf”或标头“X-CSRF-TOKEN”上发现无效的 CSRF 令牌“null”。

类型:状态报告

消息:在请求参数“_csrf”或标头“X-CSRF-TOKEN”上发现无效的 CSRF 令牌“null”。

说明:对指定资源的访问已被禁止。

顺便说一句,两种情况下错误页面的 url 都是 localhost:8080/spring-security/logout。 spring-security 是这个测试应用程序的名称。

所以,我有点迷路了。这是我第一次使用 Spring Security,我真的不知道我做错了什么。任何帮助将不胜感激。

下面我将粘贴我的 admin.jsp 页面和 spring-security.xml 页面。

提前致谢。

admin.jsp 页面:

<%@ page session="true" %>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<%@ include file="jstl-stub.jsp" %> <!-- Include links to JSTL Libraries -->
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Admin Page</title>
</head>
<body>

<h1>Title: $title</h1>

<h1>Message: $message</h1>

<c:if test="$pageContext.request.userPrincipal.name != null">
    <h2>Welcome: $pageContext.request.userPrincipal.name
    | <a href="<c:url value="/logout"/>">Logout</a></h2>

    <br><br>

    <form action="logout" method="post">
        <input type="submit" value="logout"/>
    </form>
</c:if>

</body>
</html>

spring-security.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:security="http://www.springframework.org/schema/security"
xsi:schemaLocation="http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-4.0.xsd
    http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd">

<security:http auto-config="true">
    <security:intercept-url pattern="/admin" access="hasRole('ROLE_USER')"/>
    <security:logout logout-url="/logout" logout-success-url="/welcome"/>
</security:http>

<security:authentication-manager>
    <security:authentication-provider >
        <security:user-service>
            <security:user name="user" password="password" authorities="ROLE_USER"/>
        </security:user-service>
    </security:authentication-provider>
</security:authentication-manager>

</beans:beans>

【问题讨论】:

【参考方案1】:

我认为第二个问题是您的 post 方法。我看到你用的是security 4.0,4.0默认开启了csrf保护。如果你不想拥有这个,你必须禁用它。

从 Spring Security 4.0 开始,CSRF 保护默认启用 XML 配置。如果您想禁用 CSRF 保护, 对应的XML配置见下。

<http>
  <!-- ... -->
  <csrf disabled="true"/>
</http>

请看下面的链接 http://docs.spring.io/spring-security/site/docs/4.0.x/reference/htmlsingle/#csrf-configure

但是如果要添加csrf保护,则需要在post方法中添加header。

本教程可能会对您有所帮助。

http://myshittycode.com/2015/03/30/spring-security-invalid-csrf-token-null-was-found-on-the-request-parameter-_csrf-or-header-x-csrf-token/

【讨论】:

【参考方案2】:
@Override
protected void configure(HttpSecurity http) throws Exception 
    http.csrf().disable();
    // other code ...

禁用 csrf 将为您工作。并允许你通过get方法调用/logout

【讨论】:

以上是关于Spring Security:注销不起作用 - “请求的资源不可用”的主要内容,如果未能解决你的问题,请参考以下文章

单次注销在 keycloak 和 spring security 中不起作用

Spring Security:注销不起作用 - “请求的资源不可用”

Spring Security Oauth2 removeAccessToken 不起作用

调用 j_spring_security_logout 不起作用

AspNet.Security.OpenIdConnect.Server 令牌吊销和注销不起作用

Spring SAML - 点击 URL '/saml/logout' 后全局注销不起作用