1

I have application in SpringMVC with Spring Security. In spring security xml configuration file i enable csrf using <csrf/>. View in html work properly when i add csrf token to link in form but now i want add Controller and made some rest communication. Controller looks like this:

@Controller
public class RestControllerTest {   
    @RequestMapping(value = "/rest", method = RequestMethod.POST, produces = "application/json")
    @ResponseStatus(value = HttpStatus.OK)
    public @ResponseBody void setUser(@RequestBody User user){
        System.out.println("Witaj " + user.getFirstname() + "!");
    }
}

When i try to send JSon with user (using postman):

{
  "firstname": "name",
  "lastname": "name"
}

I get 404 not found status in postman and WARN : org.springframework.web.servlet.PageNotFound - Request method 'POST' not supported in STS. I know that I have to use csrf token but i don't have idea how to do this. enter image description here

lukhol
  • 318
  • 2
  • 6
  • 18
  • 1
    Is your application successfully deployed? what is the full URL to which you are trying to Post this data? – Master Po May 24 '17 at 18:37
  • Yes, application work properly. All controller which returns view works good. When I disable csrf i can send json user using postman but when i enable csrf i unfortunately have problem witch post method. – lukhol May 24 '17 at 18:44
  • 1
    For the csrf token: https://stackoverflow.com/questions/27182701/how-do-i-send-spring-csrf-token-from-postman-rest-client Although the problem you described doesn't seem to be caused by it, as lack of the token would give you a 403. Is that your whole controller? Do you have a prefix request mapping on the class? Edit - just saw your response. So, if you disable csrf the same request in postman works? – chaos May 24 '17 at 18:44
  • I didn't add all controller in post. Of cours i have @Controller annotation on this class. When i disable csrf i can send json using postman. – lukhol May 24 '17 at 18:49
  • 1
    It's hard to know what's wrong with the code posted. Can you add an [mcve] to the question? or at least tell us which URL you are using via Postman? the error message does not seem to be related to the `csrf` token – blurfus May 24 '17 at 18:51
  • https://s27.postimg.org/yfb97q2ub/image.png - as i sad, it work when csrf is disable, and don't work when enable. – lukhol May 24 '17 at 18:54
  • You may have a different post mapping (which works) - from the image I can see that you are posting to `/rest` but your mapping (in the code provided) is mapped to `/restUser` - try using POSTMAN to post to the mapped URL instead – blurfus May 24 '17 at 19:23
  • Every thing in mapping is ok, i send wrong screen. – lukhol May 24 '17 at 21:33
  • post ur xml config file also. – aksss May 25 '17 at 08:41

1 Answers1

1

I have a similar working usecase as yours. This is how things look like in my case.

My Filter class -

public class MyCsrfFilter extends OncePerRequestFilter { 

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, 
        FilterChain filterChain)
            throws Exception {
        CsrfToken csrf = (CsrfToken) request.getAttribute(org.springframework.security.web.csrf.CsrfToken.class.getName());
        if (csrf != null) {
            Cookie cookie = WebUtils.getCookie(request, "XSRF-TOKEN");
            String token = csrf.getToken();
            if (cookie == null) {
                cookie = new Cookie("XSRF-TOKEN", token);
                cookie.setPath(YOUR_DOMAIN_NAME);
                cookie.setHttpOnly(true);
                response.addCookie(cookie);
            }
        }
        filterChain.doFilter(request, response);
    }

}

Below is the security configuration in spring-boot. You can convert it to equivalent xml config file if you need one.

@Configuration
@EnableWebMvcSecurity
public class CustomWebSecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf()
                .csrfTokenRepository(getTokenRepo())
                .and()
                .authorizeRequests()
                .antMatchers("/login", "/login**").permitAll()
                .and()
                .addFilterAfter(new CsrfHeaderFilter(), CsrfFilter.class);
    }

    private CsrfTokenRepository getTokenRepo() {
        HttpSessionCsrfTokenRepository repo = new HttpSessionCsrfTokenRepository();
        repo.setHeaderName("X-XSRF-TOKEN");
        return repo;
      }

Hope this helps !

aksss
  • 333
  • 5
  • 17