BAEL-797 removing csrf protections
This commit is contained in:
parent
be4b206478
commit
e193a60dc6
|
@ -1,15 +1,11 @@
|
||||||
package com.baeldung.spring.cloud.bootstrap.gateway;
|
package com.baeldung.spring.cloud.bootstrap.gateway;
|
||||||
|
|
||||||
import com.baeldung.spring.cloud.bootstrap.gateway.filter.CsrfHeaderFilter;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
||||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
||||||
import org.springframework.security.web.csrf.CsrfFilter;
|
|
||||||
import org.springframework.security.web.csrf.CsrfTokenRepository;
|
|
||||||
import org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository;
|
|
||||||
|
|
||||||
@EnableWebSecurity
|
@EnableWebSecurity
|
||||||
@Configuration
|
@Configuration
|
||||||
|
@ -27,8 +23,6 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
|
||||||
protected void configure(HttpSecurity http) throws Exception {
|
protected void configure(HttpSecurity http) throws Exception {
|
||||||
http
|
http
|
||||||
.formLogin()
|
.formLogin()
|
||||||
.loginPage("/login.html")
|
|
||||||
.loginProcessingUrl("/login")
|
|
||||||
.defaultSuccessUrl("/home/index.html", true)
|
.defaultSuccessUrl("/home/index.html", true)
|
||||||
.and()
|
.and()
|
||||||
.authorizeRequests()
|
.authorizeRequests()
|
||||||
|
@ -39,13 +33,6 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
|
||||||
.and()
|
.and()
|
||||||
.logout()
|
.logout()
|
||||||
.and()
|
.and()
|
||||||
.addFilterAfter(new CsrfHeaderFilter(), CsrfFilter.class)
|
.csrf().disable();
|
||||||
.csrf().csrfTokenRepository(csrfTokenRepository());
|
|
||||||
}
|
|
||||||
|
|
||||||
private CsrfTokenRepository csrfTokenRepository() {
|
|
||||||
HttpSessionCsrfTokenRepository repository = new HttpSessionCsrfTokenRepository();
|
|
||||||
repository.setHeaderName("X-XSRF-TOKEN");
|
|
||||||
return repository;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,29 +0,0 @@
|
||||||
package com.baeldung.spring.cloud.bootstrap.gateway.filter;
|
|
||||||
|
|
||||||
import org.springframework.security.web.csrf.CsrfToken;
|
|
||||||
import org.springframework.web.filter.OncePerRequestFilter;
|
|
||||||
import org.springframework.web.util.WebUtils;
|
|
||||||
|
|
||||||
import javax.servlet.FilterChain;
|
|
||||||
import javax.servlet.ServletException;
|
|
||||||
import javax.servlet.http.Cookie;
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
public class CsrfHeaderFilter extends OncePerRequestFilter {
|
|
||||||
@Override
|
|
||||||
protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException {
|
|
||||||
CsrfToken csrfToken = (CsrfToken) httpServletRequest.getAttribute(CsrfToken.class.getName());
|
|
||||||
if (csrfToken != null) {
|
|
||||||
Cookie cookie = WebUtils.getCookie(httpServletRequest, "XSRF-TOKEN");
|
|
||||||
String token = csrfToken.getToken();
|
|
||||||
if (cookie == null || token != null && !token.equals(cookie.getValue())) {
|
|
||||||
cookie = new Cookie("XSRF-TOKEN", token);
|
|
||||||
cookie.setPath("/");
|
|
||||||
httpServletResponse.addCookie(cookie);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
filterChain.doFilter(httpServletRequest, httpServletResponse);
|
|
||||||
}
|
|
||||||
}
|
|
File diff suppressed because one or more lines are too long
|
@ -7,6 +7,6 @@
|
||||||
<body>
|
<body>
|
||||||
<h1>Book Rater</h1>
|
<h1>Book Rater</h1>
|
||||||
<p>So many great things about the books</p>
|
<p>So many great things about the books</p>
|
||||||
<a href="/login.html">Login</a>
|
<a href="/login">Login</a>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
|
@ -1,65 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<title>Login</title>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<form id="loginForm">
|
|
||||||
<label>Username:</label>
|
|
||||||
<input id="username" type="text" name="username"/>
|
|
||||||
<label>Password:</label>
|
|
||||||
<input id="password" type="password" name="password"/>
|
|
||||||
<button>Submit</button>
|
|
||||||
</form>
|
|
||||||
<script type="text/javascript">
|
|
||||||
// from stackoverflow: http://stackoverflow.com/questions/5639346/shortest-function-for-reading-a-cookie-in-javascript
|
|
||||||
(function(){
|
|
||||||
var cookies;
|
|
||||||
|
|
||||||
function readCookie(name,c,C,i){
|
|
||||||
if(cookies){ return cookies[name]; }
|
|
||||||
|
|
||||||
c = document.cookie.split('; ');
|
|
||||||
cookies = {};
|
|
||||||
|
|
||||||
for(i=c.length-1; i>=0; i--){
|
|
||||||
C = c[i].split('=');
|
|
||||||
cookies[C[0]] = C[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
return cookies[name];
|
|
||||||
}
|
|
||||||
|
|
||||||
window.readCookie = readCookie; // or expose it however you want
|
|
||||||
})();
|
|
||||||
|
|
||||||
document.getElementById('loginForm').addEventListener('submit', function (e) {
|
|
||||||
e.preventDefault(); //to prevent form submission
|
|
||||||
var csrf = window.readCookie("XSRF-TOKEN");
|
|
||||||
console.log(csrf);
|
|
||||||
var username = document.getElementById("username").value;
|
|
||||||
console.log(username);
|
|
||||||
var password = document.getElementById("password").value;
|
|
||||||
console.log(password);
|
|
||||||
|
|
||||||
var xhr = new XMLHttpRequest();
|
|
||||||
xhr.open('POST', '/login?' + 'username=' + encodeURIComponent(username) + '&password=' + encodeURIComponent(password));
|
|
||||||
xhr.setRequestHeader("X-XSRF-TOKEN", csrf);
|
|
||||||
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
|
|
||||||
xhr.send(null);
|
|
||||||
xhr.onreadystatechange = function () {
|
|
||||||
var DONE = 4;
|
|
||||||
var OK = 200;
|
|
||||||
if (xhr.readyState === DONE) {
|
|
||||||
if (xhr.status === OK) {
|
|
||||||
window.location.replace(xhr.responseURL)
|
|
||||||
} else {
|
|
||||||
console.log(xhr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
|
@ -2,9 +2,8 @@ package com.baeldung.spring.cloud.bootstrap.gateway;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||||
import io.restassured.RestAssured;
|
import io.restassured.RestAssured;
|
||||||
|
import io.restassured.authentication.FormAuthConfig;
|
||||||
import io.restassured.config.RedirectConfig;
|
import io.restassured.config.RedirectConfig;
|
||||||
import io.restassured.config.SessionConfig;
|
|
||||||
import io.restassured.filter.session.SessionFilter;
|
|
||||||
import io.restassured.http.ContentType;
|
import io.restassured.http.ContentType;
|
||||||
import io.restassured.response.Response;
|
import io.restassured.response.Response;
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
|
@ -17,13 +16,12 @@ import static io.restassured.RestAssured.config;
|
||||||
public class LiveTest {
|
public class LiveTest {
|
||||||
|
|
||||||
private final String ROOT_URI = "http://localhost:8080";
|
private final String ROOT_URI = "http://localhost:8080";
|
||||||
SessionFilter sessionFilter;
|
private final FormAuthConfig formConfig = new FormAuthConfig("/login", "username", "password");
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setup() {
|
public void setup() {
|
||||||
RestAssured.config = config()
|
RestAssured.config = config().redirect(RedirectConfig.redirectConfig()
|
||||||
.redirect(RedirectConfig.redirectConfig().followRedirects(false))
|
.followRedirects(false));
|
||||||
.sessionConfig(new SessionConfig().sessionIdName("SESSION"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -35,28 +33,26 @@ public class LiveTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void whenAccessProtectedResourceWithoutLogin_thenRedirectToLogin() {
|
public void whenAccessProtectedResourceWithoutLogin_thenRedirectToLogin() {
|
||||||
final Response response = RestAssured.get(ROOT_URI + "/rating-service/ratings?bookId=1");
|
final Response response = RestAssured.get(ROOT_URI + "/home/index.html");
|
||||||
Assert.assertEquals(HttpStatus.FORBIDDEN.value(), response.getStatusCode());
|
Assert.assertEquals(HttpStatus.FOUND.value(), response.getStatusCode());
|
||||||
Assert.assertNotNull(response.getBody());
|
Assert.assertEquals("http://localhost:8080/login", response.getHeader("Location"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void whenAccessProtectedResourceAfterLogin_thenSuccess() {
|
public void whenAccessProtectedResourceAfterLogin_thenSuccess() {
|
||||||
SessionData sessionData = login("user", "password");
|
|
||||||
final Response response = RestAssured.given()
|
final Response response = RestAssured.given()
|
||||||
.header("X-XSRF-TOKEN", sessionData.getCsrf())
|
.auth()
|
||||||
.filter(sessionFilter)
|
.form("user", "password", formConfig)
|
||||||
.get(ROOT_URI + "/rating-service/ratings?bookId=1");
|
.get(ROOT_URI + "/book-service/books/1");
|
||||||
Assert.assertEquals(HttpStatus.OK.value(), response.getStatusCode());
|
Assert.assertEquals(HttpStatus.OK.value(), response.getStatusCode());
|
||||||
Assert.assertNotNull(response.getBody());
|
Assert.assertNotNull(response.getBody());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void whenAccessAdminProtectedResource_thenForbidden() {
|
public void whenAccessAdminProtectedResource_thenForbidden() {
|
||||||
SessionData sessionData = login("user", "password");
|
|
||||||
final Response response = RestAssured.given()
|
final Response response = RestAssured.given()
|
||||||
.header("X-XSRF-TOKEN", sessionData.getCsrf())
|
.auth()
|
||||||
.filter(sessionFilter)
|
.form("user", "password", formConfig)
|
||||||
.get(ROOT_URI + "/rating-service/ratings");
|
.get(ROOT_URI + "/rating-service/ratings");
|
||||||
Assert.assertEquals(HttpStatus.FORBIDDEN.value(), response.getStatusCode());
|
Assert.assertEquals(HttpStatus.FORBIDDEN.value(), response.getStatusCode());
|
||||||
|
|
||||||
|
@ -64,10 +60,9 @@ public class LiveTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void whenAdminAccessProtectedResource_thenSuccess() {
|
public void whenAdminAccessProtectedResource_thenSuccess() {
|
||||||
SessionData sessionData = login("admin", "admin");
|
|
||||||
final Response response = RestAssured.given()
|
final Response response = RestAssured.given()
|
||||||
.header("X-XSRF-TOKEN", sessionData.getCsrf())
|
.auth()
|
||||||
.filter(sessionFilter)
|
.form("admin", "admin", formConfig)
|
||||||
.get(ROOT_URI + "/rating-service/ratings");
|
.get(ROOT_URI + "/rating-service/ratings");
|
||||||
Assert.assertEquals(HttpStatus.OK.value(), response.getStatusCode());
|
Assert.assertEquals(HttpStatus.OK.value(), response.getStatusCode());
|
||||||
Assert.assertNotNull(response.getBody());
|
Assert.assertNotNull(response.getBody());
|
||||||
|
@ -75,10 +70,9 @@ public class LiveTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void whenAdminAccessDiscoveryResource_thenSuccess() {
|
public void whenAdminAccessDiscoveryResource_thenSuccess() {
|
||||||
SessionData sessionData = login("admin", "admin");
|
|
||||||
final Response response = RestAssured.given()
|
final Response response = RestAssured.given()
|
||||||
.header("X-XSRF-TOKEN", sessionData.getCsrf())
|
.auth()
|
||||||
.filter(sessionFilter)
|
.form("admin", "admin", formConfig)
|
||||||
.get(ROOT_URI + "/discovery");
|
.get(ROOT_URI + "/discovery");
|
||||||
Assert.assertEquals(HttpStatus.OK.value(), response.getStatusCode());
|
Assert.assertEquals(HttpStatus.OK.value(), response.getStatusCode());
|
||||||
}
|
}
|
||||||
|
@ -88,12 +82,10 @@ public class LiveTest {
|
||||||
|
|
||||||
final Rating rating = new Rating(1L, 4);
|
final Rating rating = new Rating(1L, 4);
|
||||||
|
|
||||||
SessionData sessionData = login("admin", "admin");
|
|
||||||
|
|
||||||
// request the protected resource
|
// request the protected resource
|
||||||
final Response ratingResponse = RestAssured.given()
|
final Response ratingResponse = RestAssured.given()
|
||||||
.header("X-XSRF-TOKEN", sessionData.getCsrf())
|
.auth()
|
||||||
.filter(sessionFilter)
|
.form("admin", "admin", formConfig)
|
||||||
.and()
|
.and()
|
||||||
.contentType(ContentType.JSON)
|
.contentType(ContentType.JSON)
|
||||||
.body(rating)
|
.body(rating)
|
||||||
|
@ -108,12 +100,10 @@ public class LiveTest {
|
||||||
public void whenAddnewBook_thenSuccess() {
|
public void whenAddnewBook_thenSuccess() {
|
||||||
final Book book = new Book("Baeldung", "How to spring cloud");
|
final Book book = new Book("Baeldung", "How to spring cloud");
|
||||||
|
|
||||||
SessionData sessionData = login("admin", "admin");
|
|
||||||
|
|
||||||
// request the protected resource
|
// request the protected resource
|
||||||
final Response bookResponse = RestAssured.given()
|
final Response bookResponse = RestAssured.given()
|
||||||
.header("X-XSRF-TOKEN", sessionData.getCsrf())
|
.auth()
|
||||||
.filter(sessionFilter)
|
.form("admin", "admin", formConfig)
|
||||||
.and()
|
.and()
|
||||||
.contentType(ContentType.JSON)
|
.contentType(ContentType.JSON)
|
||||||
.body(book)
|
.body(book)
|
||||||
|
@ -204,60 +194,4 @@ public class LiveTest {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private SessionData login(String username, String password) {
|
|
||||||
sessionFilter = new SessionFilter();
|
|
||||||
Response getLoginResponse = RestAssured.given()
|
|
||||||
.filter(sessionFilter)
|
|
||||||
.when()
|
|
||||||
.get("/login.html")
|
|
||||||
.then()
|
|
||||||
.extract()
|
|
||||||
.response();
|
|
||||||
|
|
||||||
String csrfToken = getLoginResponse.cookie("XSRF-TOKEN");
|
|
||||||
|
|
||||||
RestAssured.given().log().all().
|
|
||||||
filter(sessionFilter)
|
|
||||||
.header("X-XSRF-TOKEN", csrfToken)
|
|
||||||
.param("username", username)
|
|
||||||
.param("password", password)
|
|
||||||
.when()
|
|
||||||
.post("/login");
|
|
||||||
|
|
||||||
Response afterLoginResponse = RestAssured.given()
|
|
||||||
.filter(sessionFilter)
|
|
||||||
.when()
|
|
||||||
.get("/")
|
|
||||||
.then()
|
|
||||||
.extract()
|
|
||||||
.response();
|
|
||||||
|
|
||||||
return new SessionData(afterLoginResponse.cookie("XSRF-TOKEN"), sessionFilter.getSessionId());
|
|
||||||
}
|
|
||||||
|
|
||||||
private class SessionData {
|
|
||||||
private String csrf;
|
|
||||||
private String session;
|
|
||||||
|
|
||||||
public SessionData(String csrf, String session) {
|
|
||||||
this.csrf = csrf;
|
|
||||||
this.session = session;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getCsrf() {
|
|
||||||
return csrf;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setCsrf(String csrf) {
|
|
||||||
this.csrf = csrf;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getSession() {
|
|
||||||
return session;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setSession(String session) {
|
|
||||||
this.session = session;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
Loading…
Reference in New Issue