Spring MVC preauthorize Controller action not getting POST request

891 views Asked by At

A noob at Spring MVC and Ajax stuff. I'm trying to send some data from the view to the controller using jQuery Ajax post but its either giving me 405 handleHttpRequestMethodNotSupported or 403 :-( Could someone please point me in the right direction?

This is my controller action that is preAuthorize.

@PreAuthorize( "hasAuthority('Admin')" )
@RequestMapping( value = "/configSave", method = RequestMethod.POST )
public String saveConfiguration( @RequestParam String test )
{
    return "configSave";
}

Following is the code from the page from where the post request is being sent.

...
<input type="button" value="Save" id="save" onclick="saveConfig()"/>
...
function saveConfig()
    {
        var testPost = { test: "testing"};

        $.ajax(
                {
                    url: "hello/configSave",
                    data: "{'test':'testing'}",
                    contentType: "application/x-www-form-urlencoded",
                    type: "post",
                    beforeSend: function (xhr) {
                        xhr.setRequestHeader("Accept", "application/json");
                        xhr.setRequestHeader("Content-Type", "application/json");
                    },
                    success: function () {
                        alert("foo");
                    },
                    error: function() {
                        alert("bar");
                    }
                }
        );
    }

All it does is it throws me either a 403 (for now, else 405) error with bar alert.

EDIT: Surprisingly, when I don't do ajax post (which I need to do) it calls the configSave action in the controller. Just really puzzled with this behaviour!

2

There are 2 answers

0
Kunal Patel On BEST ANSWER

Managed to find a couple of sections in Spring docs this and this which says that I need to use CSRF token to send a post request across, when using Spring Security. After a lot of test and trail I found the following code working for me. I hope it helps others too. Any better suggestions are welcomed.

...<%@ taglib prefix="sec" uri="http://www.springframework.org/security/tags" %>...

...<sec:csrfMetaTags />...//Within <head>

...var csrfToken = $("meta[name='_csrf']").attr("content");...//somewhere in page load

function saveConfig()
    {
        var test = { name: "testing" };

        $.ajax(
                {
                    url: "hello/configSave",
                    data: JSON.stringify( test ),
                    dataType: "text",
                    contentType: "application/json",
                    type: "post",
                    headers: {
                        'Accept': 'application/json',
                        'Content-Type': 'application/json',
                        'X-CSRF-TOKEN': csrfToken //adding this made it WORK!
                    },
                    success: function (msg) {
                        alert("Yippie! Saved");
                    },
                    error: function() {
                        alert("Save failed, please try again!");
                    }
                }
        );
    }
6
java_dude On

Add headers = "Accept=application/json"

replace contentType: "application/x-www-form-urlencoded", by contentType : "application/json",

There are lots of moving parts here. Why don't you break it down and verify in smaller parts. Create similar code outside Spring authentication. Once you have Ajax working, then you can add Spring authentication back. 403 has nothing to do with 405. Since, this is just header mis-match and other is security issue.