I have to issue a HTTP.Post (Android App) to my restful service, to register a new user!
The problem is, when I try to issue a request to a register endpoint ( without security ), Spring keeps blocking me!
My Project Dependencies
<properties> <java-version>1.6</java-version> <org.springframework-version>4.1.7.RELEASE</org.springframework-version> <org.aspectj-version>1.6.10</org.aspectj-version> <org.slf4j-version>1.6.6</org.slf4j-version> <jackson.version>1.9.10</jackson.version> <spring.security.version>4.0.2.RELEASE</spring.security.version> <hibernate.version>4.2.11.Final</hibernate.version> <jstl.version>1.2</jstl.version> <mysql.connector.version>5.1.30</mysql.connector.version> </properties>
Spring Security
<beans:beans xmlns="http://www.springframework.org/schema/security" xmlns:beans="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd"> <!--this is the register endpoint--> <http security="none" pattern="/webapi/cadastro**"/> <http auto-config="true" use-expressions="true"> <intercept-url pattern="/webapi/dados**" access="hasAnyRole('ROLE_USER','ROLE_SYS')" /> <intercept-url pattern="/webapi/system**" access="hasRole('ROLE_SYS')" /> <!-- <access-denied-handler error-page="/negado" /> --> <form-login login-page="/home/" default-target-url="/webapi/" authentication-failure-url="/home?error" username-parameter="username" password-parameter="password" /> <logout logout-success-url="/home?logout" /> <csrf token-repository-ref="csrfTokenRepository" /> </http> <authentication-manager> <authentication-provider> <password-encoder hash="md5" /> <jdbc-user-service data-source-ref="dataSource" users-by-username-query="SELECT username, password, ativo FROM usuarios WHERE username = ?" authorities-by-username-query="SELECT u.username, r.role FROM usuarios_roles r, usuarios u WHERE u.id = r.usuario_id AND u.username = ?" /> </authentication-provider> </authentication-manager> <beans:bean id="csrfTokenRepository" class="org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository"> <beans:property name="headerName" value="X-XSRF-TOKEN" /> </beans:bean> </beans:beans>
Controller
@RestController @RequestMapping(value="/webapi/cadastro", produces="application/json") public class CadastroController { @Autowired UsuarioService usuarioService; Usuario u = new Usuario(); @RequestMapping(value="/novo",method=RequestMethod.POST) public String register() { // this.usuarioService.insert(usuario); // usuario.setPassword(HashMD5.criptar(usuario.getPassword())); return "teste"; } }
JS Post ( Angular )
$http.post('/webapi/cadastro/novo').success(function(data) { alert('ok'); }).error(function(data) { alert(data); });
And the error
HTTP Status 403 - Invalid CSRF Token 'null' was found on the request parameter '_csrf' or header 'X-XSRF-TOKEN'.</h1><HR size="1" noshade="noshade"><p><b>type</b> Status report</p><p><b>message</b> <u>Invalid CSRF Token 'null' was found on the request parameter '_csrf' or header 'X-XSRF-TOKEN'
--- Solution ---
Implemented a filter to attach my X-XSRF-TOKEN to every request header
public 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); } }
Added a mapping to this filter to the web.xml and done!