Skip to content

Instantly share code, notes, and snippets.

@adrobisch
Created October 15, 2015 13:03
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save adrobisch/0876ed217d8f28588d2b to your computer and use it in GitHub Desktop.
Save adrobisch/0876ed217d8f28588d2b to your computer and use it in GitHub Desktop.
Spring Boot security example configuration for AngularJS applications including XSRF
var angular = require('angular');
var LoginController = require("./LoginController");
var loginModule = angular.module('login', []);
loginModule.controller("LoginController", LoginController);
loginModule.service("login", require("./LoginApi"));
module.exports = loginModule;
var AutenticationInterceptor = ['$q', '$window', function($q, window) {
return {
response: function(response) {
return response || $q.when(response);
},
responseError: function(rejection) {
if (rejection.status === 401) {
window.location.href = "login.html";
}
return $q.reject(rejection);
}
};
}];
module.exports = AutenticationInterceptor;
<!doctype html>
<html>
<head>
<link rel="stylesheet" href="css/style.css">
</head>
<body data-ng-app="login">
<div class="container" data-ng-controller="LoginController">
<div class="row">
<h3>Login</h3>
<div class="alert alert-danger" data-ng-show="error">
There was a problem logging in. Please try again.
</div>
<form role="form" data-ng-submit="login()">
<div class="form-group">
<label for="username">Username:</label>
<input type="text"
class="form-control"
id="username"
name="username"
data-ng-model="username"/>
</div>
<div class="form-group">
<label for="password">Password:</label>
<input type="password"
class="form-control"
id="password"
name="password"
data-ng-model="password"/>
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
</div>
</div>
<script src="app.js"></script>
</body>
</html>
function LoginApi(http) {
this.login = function (username, password) {
return http({
method: 'POST',
url: "login",
data: "username=" + username + "&password=" + password,
headers: {'Content-Type': 'application/x-www-form-urlencoded'}
});
};
}
LoginApi.$inject = ["$http"];
module.exports = LoginApi;
var LoginController = function(scope, window, login) {
scope.login = function () {
login.login(scope.username, scope.password)
.success(scope.onLoginSuccess)
.error(scope.onLoginError);
};
scope.onLoginSuccess = function () {
scope.error = false;
window.location.href = "./";
};
scope.onLoginError = function (error) {
scope.error = true;
window.alert("error");
};
};
LoginController.$inject = ["$scope", "$window", "login"];
module.exports = LoginController;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.security.SecurityProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.core.env.Environment;
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.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint;
import org.springframework.security.web.csrf.CsrfFilter;
import org.springframework.security.web.csrf.CsrfToken;
import org.springframework.security.web.csrf.CsrfTokenRepository;
import org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
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;
import java.security.Principal;
@Configuration
@Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
public static final String LOGIN = "/login";
@Autowired
Environment environment;
@Override
protected void configure(HttpSecurity http) throws Exception {
http.exceptionHandling().authenticationEntryPoint(new AjaxAwareEntryPoint(LOGIN))
.and()
.authorizeRequests()
.antMatchers("/api/**").authenticated()
.anyRequest().permitAll()
.and()
.formLogin().loginPage(LOGIN)
.and()
.csrf().csrfTokenRepository(csrfTokenRepository())
.and()
.addFilterAfter(new CsrfHeaderFilter(), CsrfFilter.class);
}
private CsrfTokenRepository csrfTokenRepository() {
HttpSessionCsrfTokenRepository repository = new HttpSessionCsrfTokenRepository();
repository.setHeaderName("X-XSRF-TOKEN");
return repository;
}
@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("admin").password("admin").roles("ADMIN", "USER")
.and()
.withUser("user").password("user") .roles("USER");
}
@RestController
public static class UserController {
@RequestMapping("/user")
public Principal user(Principal user) {
return user;
}
}
class AjaxAwareEntryPoint extends LoginUrlAuthenticationEntryPoint {
private static final String XML_HTTP_REQUEST = "XMLHttpRequest";
private static final String X_REQUESTED_WITH = "X-Requested-With";
public AjaxAwareEntryPoint(String loginFormUrl) {
super(loginFormUrl);
}
@Override
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception)
throws IOException, ServletException {
if (XML_HTTP_REQUEST.equals(request.getHeader(X_REQUESTED_WITH))) {
response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
} else {
super.commence(request, response, exception);
}
}
}
class CsrfHeaderFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
CsrfToken csrf = (CsrfToken) request.getAttribute(CsrfToken.class.getName());
if (csrf != null) {
Cookie cookie = WebUtils.getCookie(request, "XSRF-TOKEN");
String token = csrf.getToken();
if (cookie==null || token!=null && !token.equals(cookie.getValue())) {
cookie = new Cookie("XSRF-TOKEN", token);
cookie.setPath("/");
response.addCookie(cookie);
}
}
filterChain.doFilter(request, response);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment