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

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

Это весенний конфигурационный файл безопасности:

<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'.

ОБНОВЛЕНИЕ После некоторой отладки объект запроса получает прекрасный вид DelegatingFilterProxy, но в строке 469 CoyoteAdapter он выполняет request.recycle(); который стирает все атрибуты...

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

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

12 ответов

Похоже, что защита 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">

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

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

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

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

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

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

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

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

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

Документация Spring для отключения csrf: https://docs.spring.io/spring-security/site/docs/current/reference/html/csrf.html

@EnableWebSecurity
public class WebSecurityConfig extends
WebSecurityConfigurerAdapter {

   @Override
   protected void configure(HttpSecurity http) throws Exception {
      http.csrf().disable();
   }
}

Раньше у меня была такая же проблема.

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

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

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

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

Я думаю, что CSRF работает только с пружинными формами

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

изменить на form:form пометьте и посмотрите, что работает.

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

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

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

ЗАМЕНЕНО С:

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

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

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

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

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

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

Я использовал версию jar Spring 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>
Другие вопросы по тегам