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


90

Після налаштування 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.


1
Яку версію Spring ви використовуєте? Це те саме працює для мене (однак, є відмінності, однак spring-security.xml) з Spring 4.0.0 RELEASE (GA), Spring Security 3.2.0 RELEASE (GA) (хоча він інтегрований із Struts 2.3.16. Я не дав йому спробуйте лише з Spring MVC). Однак це не вдається, коли запит є багаточастинним для завантаження файлів із статусом 403. Я намагаюся знайти рішення для нього.
Крихітний

Весна 3.2.6, Spring Security 3.2.0, маркер CSRF, був доданий до об’єкта http-запиту, об’єкт сеансу є однаковим разом із потоком запиту, але коли він вимикається, поки jsp не видаляє всі атрибути і лише залишити атрибут ... filter_applied
Hugo Robayo

@Tiny: Ви коли-небудь знаходили рішення багаточастинної проблеми? У мене точно така ж проблема.
Роб Йохансен

1
@AlienBishop: Так, будь ласка, перевірте цю відповідь (вона використовує комбінацію Spring та Struts). Якщо у вас тоді є Spring MVC, будь ласка, перевірте цю відповідь. Слід зазначити, що порядок введення фільтрів web.xmlмає вирішальне значення. MultipartFilterповинні бути оголошені раніше springSecurityFilterChain. Сподіваюся, що це допомагає. Дякую.
Крихітний

Відповіді:


110

Схоже, захист CSRF (Cross Site Request Forgery) у вашій програмі 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
Це слід прийняти як відповідь, оскільки воно пояснює не тільки те, що робити, але й те, що слід врахувати, перш ніж щось робити, щоб зупинити ці помилки.
Томас Карлайл,

1
Ви також можете зробити.csrf().ignoringAntMatchers("/h2-console/**")
insan-e

У наведеній вище відповіді уникайте використання параметра параметра запиту. Якщо ви зробите це, ви публікуєте жетони.
Прамод С. Нікам

31

Чи не слід додати до форми входу ?;

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

Як зазначено тут у весняній документації щодо безпеки


12

Якщо ви подаєте заявку, security="none"то жоден маркер csrf не буде створений. Сторінка не буде проходити через фільтр безпеки. Використовуйте роль ANONYMOUS.

Я не вдався в подробиці, але це працює для мене.

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

Я використовував security = none і перехід до вашої відповіді вирішив цю проблему. це чудовий чебрець автоматично додає маркер csrf. Дякую !
rxx




4

Раніше у мене була та сама проблема.

Ваша конфігурація використовує 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>


1

Будь ласка, перегляньте мій робочий зразок програми на Github і порівняйте з вашим налаштуванням.


Я повернуся до версії 3.2.6, сподіваюся, це працює без весняного mvc.
Hugo Robayo

Так, це повинно працювати без проблем, оскільки я створив зразок програми з моєї існуючої програми, яка була навесні 3.1.4.
маніш

ха-ха-ха-ха-ха, чудово, змусити його працювати лише зниження рейтингу не є рішенням bhaiya ji @manish
Singh

1

Жодне з рішень не спрацювало у мене. Єдиний, який працював у мене у весняному вигляді:

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

ЗАМЕНЕНО НА:

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

(Spring 5 з увімкненим CSRF у конфігурації Java)


0

Додайте у свій контролер таке:

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

І на jsp-сторінці додайте

<form:form modelAttribute="someName" action="someURI?${_csrf.parameterName}=${_csrf.token}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.