The following test fails because it returns a login page as opposed to the content.
TestRestTemplate restTemplate = new TestRestTemplate();
HttpHeaders headers = new HttpHeaders();
headers.setAccept(Arrays.asList(MediaType.TEXT_HTML));
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
MultiValueMap<String, String> form = new LinkedMultiValueMap<>();
form.set("username", testUser.getUser().getUid());
form.set("password", testUser.getUserPassword());
ResponseEntity<String> loginEntity = restTemplate.exchange(
url("/login"),
HttpMethod.POST,
new HttpEntity<>(form, headers),
String.class);
HttpHeaders requestHeaders = new HttpHeaders();
requestHeaders.setAccept(Arrays.asList(MediaType.TEXT_HTML));
requestHeaders.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
//
// auth csrf and form login - doesn't work
ResponseEntity<String> getLoginEntity = restTemplate.getForEntity(url("/login"), String.class);
String cookie = getLoginEntity.getHeaders().getFirst(HttpHeaders.SET_COOKIE);
// contains CSRF-TOKEN
requestHeaders.set(HttpHeaders.COOKIE, cookie);
Pattern pattern = Pattern.compile("(?s).*name=\"_csrf\".*?value=\"([^\"]+).*");
Matcher matcher = pattern.matcher(getLoginEntity.getBody());
matcher.matches();
requestHeaders.set("X-CSRF-TOKEN", matcher.group(1));
//
ResponseEntity<String> memberEntity = restTemplate.exchange(
url("/members"),
HttpMethod.GET,
new HttpEntity<>(form, requestHeaders),
String.class
);
assertEquals("Unexpected member content", "Welcome member!", memberEntity.getBody());
The configuration is like so
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().and()
.authorizeRequests()
.antMatchers("/**").fullyAuthenticated()
.and()
.formLogin()
.permitAll();
}
The login page returned includes _csrf as a hidden field and the value corresponds to the value which has been set in the cookie.
Note that with minor modifications, I am able to get the following scenarios to work:
However, I've had no success with
Any guidance on how to get this to work would be appreciated.
BTW: The approach I've taken follows: https://github.com/spring-projects/spring-boot/blob/master/spring-boot-samples/spring-boot-sample-web-secure/src/test/java/sample/web/secure/SampleSecureApplicationTests.java
It does not work because you need cookie and csrf to POST to login, so you need to make two requests at least.
First you need to setup a /csrf
page that exposes the csrf token, eg: {"token": "b3c7338e-95c0-4088-9fb7-d72a870bd60c", "headerName": "X-CSRF-TOKEN", "parameterName": "_csrf" }
Then the flow is like this:
token
from /csrf
storing also the cookie passed with header Set-Cookie
token
in the request header with name specified by /csrf
, eg: X-CSRF-TOKEN: b3c7338e-95c0-4088-9fb7-d72a870bd60c
Cookie
(this because cookie and csrf token are bound together on the server)/login
storing the cookie passed to you with response header Set-Cookie
(it changes after login) /login
setting it in request header Cookie
token
from /csrf
(since cookie changed also token changed)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.