В параметре запроса _csrf или заголовке X-CSRF-TOKEN обнаружен недействительный токен CSRF «null».

После настройки 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>

Файл логин.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.


person Hugo Robayo    schedule 15.01.2014    source источник
comment
Какую версию Spring вы используете? У меня эта же штука работает (есть отличия однако, в spring-security.xml) с Spring 4.0.0 RELEASE (GA), Spring Security 3.2.0 RELEASE (GA) (правда он интегрирован со Struts 2.3.16. Я не давал попробуйте только Spring MVC). Однако это не удается, когда запрос составной для загрузки файлов со статусом 403. Я изо всех сил пытаюсь найти решение для этого.   -  person Tiny    schedule 02.02.2014
comment
Spring 3.2.6, Spring Security 3.2.0, CSRF, токен был добавлен в объект http-запроса, объект сеанса такой же, как и поток запроса, но при выходе до его рендеринга jsp удаляет все атрибуты и только оставить атрибут ...filter_applied   -  person Hugo Robayo    schedule 04.02.2014
comment
@Tiny: Вы когда-нибудь находили решение проблемы с несколькими частями? У меня точно такая же проблема.   -  person Rob Johansen    schedule 26.02.2014
comment
@AlienBishop: Да, ознакомьтесь с этим ответом (в нем используется комбинация Spring и Struts). Если у вас есть только Spring MVC, ознакомьтесь с этим ответом. Следует отметить, что порядок фильтров в web.xml имеет решающее значение. MultipartFilter должен быть объявлен до springSecurityFilterChain. Надеюсь, это поможет. Спасибо.   -  person Tiny    schedule 26.02.2014


Ответы (11)


Похоже, что защита 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">
person MaVRoSCy    schedule 28.04.2015
comment
Это следует принять как ответ, потому что он объясняет не только, что делать, но и то, что вы должны учитывать, прежде чем что-то делать, чтобы остановить эти ошибки. - person Thomas Carlisle; 26.03.2018
comment
Вы также можете сделать .csrf().ignoringAntMatchers("/h2-console/**") - person insan-e; 14.06.2018
comment
В приведенном выше ответе избегайте использования стиля параметра запроса. Если вы сделаете это, вы выставите токены на всеобщее обозрение. - person Pramod S. Nikam; 08.05.2020

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

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

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

person borjab    schedule 06.06.2014

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

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

 <http auto-config="true" use-expressions="true">
   <intercept-url pattern="/login.jsp" access="hasRole('ANONYMOUS')" />
   <!-- you configuration -->
   </http>
person Awanish Kumar    schedule 09.08.2015
comment
Я использовал security = none, и переход к вашему ответу решил эту проблему. это потрясающе, тимелеаф автоматически добавляет токен csrf. Спасибо ! - person rxx; 29.03.2016

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

person Arkadiusz Gibes    schedule 09.05.2015

С листьями тимьяна вы можете добавить:

<input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}"/>
person Lay Leangsros    schedule 17.10.2016

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

@EnableWebSecurity
public class WebSecurityConfig extends
WebSecurityConfigurerAdapter {

   @Override
   protected void configure(HttpSecurity http) throws Exception {
      http.csrf().disable();
   }
}
person Rahul Raj    schedule 13.01.2017
comment
Не копируйте существующие ответы, пожалуйста. - person james.garriss; 07.07.2017

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

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

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

вы можете установить access="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>
person xxg    schedule 02.09.2015

я думаю, csrf работает только с весенними формами

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

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

person Saurabh Kumar    schedule 14.06.2014
comment
Вам не нужно использовать пружинные формы: docs.spring.io/spring-security/site/docs/3.2.7.RELEASE/ - person Bart Swennenhuis; 23.04.2015

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

person manish    schedule 10.02.2014
comment
Я перейду на spring 3.2.6, надеюсь, он работает без весеннего mvc. - person Hugo Robayo; 11.02.2014
comment
Да, это должно работать без проблем, так как я создал образец приложения из своего существующего приложения, которое было в Spring 3.1.4. - person manish; 11.02.2014
comment
ха-ха-ха-ха-ха, отлично, просто понизить версию — это не решение bhaiya ji @manish - person Kuldeep Singh; 29.12.2016

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

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

ЗАМЕНЕН НА:

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

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

person vancho    schedule 21.02.2018

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

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

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

<form:form modelAttribute="someName" action="someURI?${_csrf.parameterName}=${_csrf.token}
person Taras Melnyk    schedule 31.07.2017