Недопустимый токен CSRF "null" был найден в параметре запроса "_csrf" или заголовке "X-CSRF-TOKEN"

После настройки Spring Security 3.2, _csrf.token не привязан к запросу или объекту сеанса.

Это конфиг безопасности Spring:

<http pattern="/login.jsp" security="none"/>

<http>
    <intercept-url pattern="/**" access="ROLE_USER"/>
    <form-login login-page="/login.jsp"
                authentication-failure-url="/login.jsp?error=1"
                default-target-url="/index.jsp"/>
    <logout/>
    <csrf />
</http>

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

Файл login.jsp

<form name="f" action="${contextPath}/j_spring_security_check" method="post" >
    <input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" />
    <button id="ingresarButton"
            name="submit"
            type="submit"
            class="right"
            style="margin-right: 10px;">Ingresar</button>
    <span>
        <label for="usuario">Usuario :</label>
        <input type="text" name="j_username" id="u" class="" value=''/>
    </span>
    <span>
        <label for="clave">Contrase&ntilde;a :</label>

        <input type="password"
               name="j_password"
               id="p"
               class=""
               onfocus="vc_psfocus = 1;"
               value="">
    </span>
</form>

И он отображает следующий html:

<input type="hidden" name="" value="" />

В результате получается 403 статус HTTP:

Invalid CSRF Token 'null' was found on the request parameter '_csrf' or header 'X-CSRF-TOKEN'.

UPDATE После некоторой отладки объект запроса получает точную форму DelegatingFilterProxy, но в строке 469 CoyoteAdapter он выполняет request.recycle(); который стирает все атрибуты...

Я тестирую в Tomcat 6.0.36, 7.0.50 с JDK 1.7.

Я не понял этого поведения, а не было возможно, если бы кто-то указал мне в сторону какой-то примерной войны с Spring Security 3.2, которая работает с CSRF.

Ответ 1

Похоже, что защита CSRF (подделка межсайтовых запросов) в вашем приложении Spring включена. На самом деле он включен по умолчанию.

По словам spring.io:

Когда следует использовать защиту от CSRF? Мы рекомендуем использовать защиту CSRF для любого запроса, который может быть обработан браузером обычными пользователями. Если вы создаете только службу, которая используется не браузерными клиентами, вы, вероятно, захотите отключить защиту CSRF.

Итак, чтобы отключить его:

@Configuration
public class RestSecurityConfig extends WebSecurityConfigurerAdapter {
  @Override
  protected void configure(HttpSecurity http) throws Exception {
    http.csrf().disable();
  }
}

Если вы хотите, чтобы защита CSRF была включена, вам нужно включить в форму csrftoken. Вы можете сделать это так:

<form .... >
  ....other fields here....
  <input type="hidden"  name="${_csrf.parameterName}"   value="${_csrf.token}"/>
</form>

Вы даже можете включить токен CSRF в действие формы:

<form action="./upload?${_csrf.parameterName}=${_csrf.token}" method="post" enctype="multipart/form-data">

Ответ 2

Разве вы не должны добавить в форму входа?;

<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/> 

Как указано здесь в документации по безопасности Spring

Ответ 3

Если вы примените security="none" токен csrf генерироваться не будет. Страница не пройдет через фильтр безопасности. Используйте роль ANONYMOUS.

Я не вдавался в подробности, но это работает для меня.

 <http auto-config="true" use-expressions="true">
   <intercept-url pattern="/login.jsp" access="hasRole('ANONYMOUS')" />
   <!-- you configuration -->
   </http>

Ответ 4

Попробуйте изменить это: <csrf /> на это: <csrf disabled="true"/>. Он должен отключить csfr.

Ответ 5

С тимелеафом вы можете добавить:

<input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}"/>

Ответ 7

У меня была такая же проблема.

Ваша конфигурация использует security = "none", поэтому не может генерировать _csrf:

<http pattern="/login.jsp" security="none"/>

вы можете установить доступ = "IS_AUTHENTICATED_ANONYMOUSLY" для страницы /login.jsp заменить выше config:

<http>
    <intercept-url pattern="/login.jsp*" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
    <intercept-url pattern="/**" access="ROLE_USER"/>
    <form-login login-page="/login.jsp"
            authentication-failure-url="/login.jsp?error=1"
            default-target-url="/index.jsp"/>
    <logout/>
    <csrf />
</http>

Ответ 8

Я думаю, что csrf работает только с формами spring

<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>

измените на тег form:form и посмотрите, как это работает.

Ответ 9

Пожалуйста, посмотрите мое рабочее приложение на Github и сравните с настройкой.

Ответ 10

Ни одно из решений не сработало от меня. Единственный, кто работал для меня в форме Spring:

action = "./upload? $ {_ csrf.parameterName}= $ {_ csrf.token}"

ЗАМЕНЕНО С:

action = "./upload? _csrf= $ {_ csrf.token}"

(Spring 5 с включенным csrf в конфигурации java)

Ответ 11

В контроллере добавьте следующее:

@RequestParam(value = "_csrf", required = false) String csrf

И на странице jsp добавьте

<form:form modelAttribute="someName" action="someURI?${_csrf.parameterName}=${_csrf.token}

Ответ 12

Я использовал Spring Jar версии 4.2.3 для безопасности Spring, но я получил ту же ошибку. Затем я понизил до 3.1.4, и эта работа отлично.

Вот мои зависимости от pom.xml:

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-core</artifactId>
    <version>3.2.3.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-beans</artifactId>
    <version>3.2.3.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>3.2.3.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-jdbc</artifactId>
    <version>3.2.3.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-web</artifactId>
    <version>3.2.3.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>3.2.3.RELEASE</version>
</dependency>
<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>jstl</artifactId>
    <version>1.2</version>
</dependency>
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.26</version>
</dependency>
<dependency>
    <groupId>javax.validation</groupId>
    <artifactId>validation-api</artifactId>
    <version>1.1.0.Final</version>
</dependency>
<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate</artifactId>
    <version>3.5.4-Final</version>
    <type>pom</type>
</dependency>
<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-validator</artifactId>
    <version>5.0.1.Final</version>
</dependency>
<dependency>
    <groupId>commons-validator</groupId>
    <artifactId>commons-validator</artifactId>
    <version>1.4.0</version>
</dependency>
<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-core</artifactId>
    <version>3.1.4.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-web</artifactId>
    <version>3.1.4.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-config</artifactId>
    <version>3.1.4.RELEASE</version>
</dependency>