Update CookieCsrfTokenRepository docs to cookiHttpOnly=false
Currently CookieCsrfTokenRepository does not specify that the httpOnly flag needs set to false. We should update the reference to include this setting (and a comment about it) since it states that the settings will work with AngularJS. This commit updates the documentation and provides a convenience factory method to create a CookieCsrfTokenRepository with cookiHttpOnly=false Fixes gh-3865
This commit is contained in:
parent
64f53620f8
commit
d4218c70f1
|
@ -3359,9 +3359,19 @@ You can configure `CookieCsrfTokenRepository` in XML using the following:
|
||||||
<!-- ... -->
|
<!-- ... -->
|
||||||
<csrf token-repository-ref="tokenRepository"/>
|
<csrf token-repository-ref="tokenRepository"/>
|
||||||
</http>
|
</http>
|
||||||
<b:bean id="tokenRepository" class="org.springframework.security.web.csrf.CookieCsrfTokenRepository"/>
|
<b:bean id="tokenRepository"
|
||||||
|
class="org.springframework.security.web.csrf.CookieCsrfTokenRepository"
|
||||||
|
p:cookieHttpOnly="false"/>
|
||||||
----
|
----
|
||||||
|
|
||||||
|
[NOTE]
|
||||||
|
====
|
||||||
|
The sample explicitly sets `cookieHttpOnly=false`.
|
||||||
|
This is necessary to allow JavaScript (i.e. AngularJS) to read it.
|
||||||
|
If you do not need the ability to read the cookie with JavaScript directly, it is recommended to omit `cookieHttpOnly=false` to improve security.
|
||||||
|
====
|
||||||
|
|
||||||
|
|
||||||
You can configure `CookieCsrfTokenRepository` in Java Configuration using:
|
You can configure `CookieCsrfTokenRepository` in Java Configuration using:
|
||||||
|
|
||||||
[source,java]
|
[source,java]
|
||||||
|
@ -3374,11 +3384,18 @@ public class WebSecurityConfig extends
|
||||||
protected void configure(HttpSecurity http) throws Exception {
|
protected void configure(HttpSecurity http) throws Exception {
|
||||||
http
|
http
|
||||||
.csrf()
|
.csrf()
|
||||||
.csrfTokenRepository(new CookieCsrfTokenRepository());
|
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
|
|
||||||
|
[NOTE]
|
||||||
|
====
|
||||||
|
The sample explicitly sets `cookieHttpOnly=false`.
|
||||||
|
This is necessary to allow JavaScript (i.e. AngularJS) to read it.
|
||||||
|
If you do not need the ability to read the cookie with JavaScript directly, it is recommended to omit `cookieHttpOnly=false` (by using `new CookieCsrfTokenRepository()` instead) to improve security.
|
||||||
|
====
|
||||||
|
|
||||||
|
|
||||||
[[csrf-caveats]]
|
[[csrf-caveats]]
|
||||||
=== CSRF Caveats
|
=== CSRF Caveats
|
||||||
|
@ -6594,9 +6611,9 @@ Spring Security provides `AuthenticationPrincipalArgumentResolver` which can aut
|
||||||
[source,xml]
|
[source,xml]
|
||||||
----
|
----
|
||||||
<mvc:annotation-driven>
|
<mvc:annotation-driven>
|
||||||
<mvc:argument-resolvers>
|
<mvc:argument-resolvers>
|
||||||
<bean class="org.springframework.security.web.method.annotation.AuthenticationPrincipalArgumentResolver" />
|
<bean class="org.springframework.security.web.method.annotation.AuthenticationPrincipalArgumentResolver" />
|
||||||
</mvc:argument-resolvers>
|
</mvc:argument-resolvers>
|
||||||
</mvc:annotation-driven>
|
</mvc:annotation-driven>
|
||||||
----
|
----
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,7 @@ import org.springframework.web.util.WebUtils;
|
||||||
/**
|
/**
|
||||||
* A {@link CsrfTokenRepository} that persist the CSRF token in a cookie named
|
* A {@link CsrfTokenRepository} that persist the CSRF token in a cookie named
|
||||||
* "XSRF-TOKEN" and reads from the header "X-XSRF-TOKEN" following the conventions of
|
* "XSRF-TOKEN" and reads from the header "X-XSRF-TOKEN" following the conventions of
|
||||||
* AngularJS.
|
* AngularJS. When using with AngularJS be sure to use {@link #withHttpOnlyFalse()}.
|
||||||
*
|
*
|
||||||
* @author Rob Winch
|
* @author Rob Winch
|
||||||
* @since 4.1
|
* @since 4.1
|
||||||
|
@ -153,6 +153,19 @@ public final class CookieCsrfTokenRepository implements CsrfTokenRepository {
|
||||||
return contextPath.length() > 0 ? contextPath : "/";
|
return contextPath.length() > 0 ? contextPath : "/";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Factory method to conveniently create an instance that has
|
||||||
|
* {@link #setCookieHttpOnly(boolean)} set to false.
|
||||||
|
*
|
||||||
|
* @return and instance of CookieCsrfTokenRepository with
|
||||||
|
* {@link #setCookieHttpOnly(boolean)} set to false
|
||||||
|
*/
|
||||||
|
public static CookieCsrfTokenRepository withHttpOnlyFalse() {
|
||||||
|
CookieCsrfTokenRepository result = new CookieCsrfTokenRepository();
|
||||||
|
result.setCookieHttpOnly(false);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
private String createNewToken() {
|
private String createNewToken() {
|
||||||
return UUID.randomUUID().toString();
|
return UUID.randomUUID().toString();
|
||||||
}
|
}
|
||||||
|
|
|
@ -138,6 +138,18 @@ public class CookieCsrfTokenRepositoryTests {
|
||||||
assertThat(tokenCookie.isHttpOnly()).isFalse();
|
assertThat(tokenCookie.isHttpOnly()).isFalse();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void saveTokenWithHttpOnlyFalse() {
|
||||||
|
this.repository = CookieCsrfTokenRepository.withHttpOnlyFalse();
|
||||||
|
CsrfToken token = this.repository.generateToken(this.request);
|
||||||
|
this.repository.saveToken(token, this.request, this.response);
|
||||||
|
|
||||||
|
Cookie tokenCookie = this.response
|
||||||
|
.getCookie(CookieCsrfTokenRepository.DEFAULT_CSRF_COOKIE_NAME);
|
||||||
|
|
||||||
|
assertThat(tokenCookie.isHttpOnly()).isFalse();
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void loadTokenNoCookiesNull() {
|
public void loadTokenNoCookiesNull() {
|
||||||
assertThat(this.repository.loadToken(this.request)).isNull();
|
assertThat(this.repository.loadToken(this.request)).isNull();
|
||||||
|
|
Loading…
Reference in New Issue