Я нашел «The Login Page: Angular JS and Spring Security» большую помощь, чтобы добавить защиту CSRF в веб-приложение, которое использует Spring (Security, среди прочих), реализуя REST API, который используется Приложение AngularJS. Приложение AngularJS использует аутентификацию на основе форм (JSESSIONID
). Вот суть этой работы:Получение теста RestAssured для работы с Spring Security CSRF для AngularJS
- Скрытое поле ввода
_csrf
на странице входа CsrfHeaderFilter
добавляетXSRF-TOKEN
печенье в ответHttpSessionCsrfTokenRepository
сsetHeaderName("X-XSRF-TOKEN")
Это все работает отлично (насколько я могу заметить).
Я считаю, что это приводит к следующему потоку:
- Перенаправление на страницу входа
- Войти страница содержит
_csrf
- Логин ответ включает
XSRF-TOKEN
печенье - Угловая использует значение куки в качестве
X-XSRF-TOKEN
заголовка на REST запросы - Счастье!
Номер 2. кажется ванили Весна Безопасность CSRF. 3. и 4. кажется an attempt для адаптации к AngularJS CSRF support.
Опять же, этот все работает нормально, от тестирования промежуточного экземпляра. Тем не менее, некоторые тесты интеграции разбиты на, в частности тесты, которые используют RestAssured. Я не нашел хороших примеров для RestAssured, этой настройки. This - это вся документация, которую я могу найти.
Предлагается использовать formAuthConfig().withAutoDetectionOfCsrf()
или withCsrfFieldName("_csrf")
и делать явные get
страницы входа. Использование этого, похоже, имеет дело штраф с логином. Но я не понимаю, как я тогда расскажу RestAssured о том, чтобы использовать заголовок X-XSRF-TOKEN
.
Я неудачно прошла через много вариаций этого кода, но я в настоящее время имея это:
FormAuthConfig baseConfig = new FormAuthConfig(loginPage, "username", "password");
FormAuthConfig config = baseConfig.sendCsrfTokenAsHeader();
config = config.withCsrfFieldName("X-XSRF-TOKEN");
RestAssured.authentication = RestAssured.form(userName, password, config);
given().auth().form("admin", "admin", baseConfig.withCsrfFieldName("_csrf"))
.when().get(loginPage)
.then().statusCode(200);
expect().statusCode(200)
.when().get(...); // line 246
Это награждается следующий вывод:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<title>Error 401 Unauthorized</title>
</head>
<body>
<h2>HTTP ERROR 401</h2>
<p>Problem accessing /application_name/rest/something. Reason:
</p>
<pre> Unauthorized</pre>
<hr/>
<i>
<small>Powered by Jetty://</small>
</i>
<hr/>
</body>
</html>
java.lang.IllegalArgumentException: Couldn't find the CSRF input field with name X-XSRF-TOKEN in response. Response was:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<title>Error 401 Unauthorized</title>
</head>
<body>
<h2>HTTP ERROR 401</h2>
<p>Problem accessing /application_name/rest/something. Reason:
</p>
<pre> Unauthorized</pre>
<hr/>
<i>
<small>Powered by Jetty://</small>
</i>
<hr/>
</body>
</html>
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:422)
at org.codehaus.groovy.reflection.CachedConstructor.invoke(CachedConstructor.java:80)
at org.codehaus.groovy.reflection.CachedConstructor.doConstructorInvoke(CachedConstructor.java:74)
at org.codehaus.groovy.runtime.callsite.ConstructorSite$ConstructorSiteNoUnwrap.callConstructor(ConstructorSite.java:84)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallConstructor(CallSiteArray.java:60)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callConstructor(AbstractCallSite.java:235)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callConstructor(AbstractCallSite.java:247)
at com.jayway.restassured.internal.filter.FormAuthFilter.filter(FormAuthFilter.groovy:85)
at com.jayway.restassured.filter.Filter$filter.call(Unknown Source)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:48)
at com.jayway.restassured.filter.Filter$filter.call(Unknown Source)
at com.jayway.restassured.internal.filter.FilterContextImpl.next(FilterContextImpl.groovy:49)
at com.jayway.restassured.filter.FilterContext$next.call(Unknown Source)
at com.jayway.restassured.internal.RequestSpecificationImpl.invokeFilterChain(RequestSpecificationImpl.groovy:994)
<snip>
at com.jayway.restassured.internal.ResponseSpecificationImpl.get(ResponseSpecificationImpl.groovy)
at com.company.application_name.AbstractJettyJsonRestTest.getCollection(AbstractJettyJsonRestTest.java:246)
at com.company.application_name.JsonRestIntegrationTest.testSomething(JsonRestIntegrationTest.java:74)
<snip>
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:74)
Ваша помощь очень признателен!
Я думаю, вам нужно использовать RequestSpecification в RestAssured http://static.javadoc.io/com.jayway.restassured/rest-assured/2.4.1/com/jayway/restassured/specification/RequestSpecification.html –
Спасибо для этого, но я боюсь, что вы не оцениваете, что я довольно опытный пользователь RestAssured, который приложил много усилий, прежде чем задавать этот вопрос, поэтому просто указывая на самый основной класс (интерфейс) в указанной библиотеке не помогает мне, если я не пропущу что-то здесь. В любом случае, немного более подробная информация поможет вам, спасибо! –