Ajax POST结果为405(不允许使用方法)-Spring MVC [英] Ajax POST results in a 405 (Method Not Allowed) - Spring MVC

查看:772
本文介绍了Ajax POST结果为405(不允许使用方法)-Spring MVC的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图用POST方法对我的Spring控制器/动作进行ajax调用,并使用@ResponseBody从服务器返回一个对象.奇怪的情况是,在添加spring安全层之后,它停止工作,之前一切正常.我将尝试解释解决问题的方法,然后向您显示代码/捕获/等.

1. 经过一些研究,我发现了一些答案,说明该问题可能与csrf机制有关,因此我将其禁用并仍然遇到问题. (下面是spring-security.xml)

2. 我进行了wireshark捕获来检查请求/响应.我的ajax请求正确,我的控制器声明正确,但是我不明白为什么,405响应指示> 允许:GET (捕获以下消息)

3. 我试图通过浏览器访问我的控制器操作(即发出GET请求),但出现错误 HTTP状态405-请求方法'GET'不支持

4. 我试图将RequestMapping(method ...)更改为RequestMethod.GET,请求到达控制器并可以正常工作,但是我不希望它在GET方法上工作,我想要POST请求.

5. 更改了RequestMapping(消费,生产,标头)以接受所有类型的数据,但仍然是405 ...

这让我发疯了!我在下面发布我的文件,以便大家检查,任何提示将不胜感激.谢谢! (重要说明:这是我的绝望配置)

spring-security.xml

<beans:beans 
     xmlns...(all needed declarations)>

<http pattern="/js/**" security="none" />
<http pattern="/css/**" security="none" />

<!-- enable use-expressions -->
<http auto-config="true" >
    <access-denied-handler error-page="/403" />
    <intercept-url pattern="/admin/**" access="hasRole('ROLE_ADMIN')" />
    <intercept-url pattern="/login" access="isAnonymous()" />
    <intercept-url pattern="/403" access="permitAll" />
    <intercept-url pattern="/**" access="hasRole('ROLE_USER')" />

    <form-login  login-page="/login"
                 username-parameter="email"
                 password-parameter="password"
                 authentication-failure-url="/login?failed" />

    <!--
    <csrf/>
    -->
</http>

 ..... (authentication)  

AdminController.java

@Controller
@RequestMapping("/admin**")
public class AdminController {

    ... (all my autowired beans)

    @RequestMapping(
        value = "/events/loadEvents",
        method = RequestMethod.POST,
        consumes = MediaType.ALL_VALUE,
        produces = MediaType.ALL_VALUE,
        headers = "Accept=*/*")
    @ResponseBody
    public Event loadEvents(@RequestParam("parentId") long parentId) {
        ... (my logic)
        return event;
    }
}

请求(wireshark捕获)

响应(wireshark捕获)

编辑 jquery ajax调用代码

$.ajax({
    type: 'POST',
    cache: false,
    url: /admin/events/loadEvents,
    data: { parentId: 1 },
    dataType = 'json',
    contentType = 'application/json',

    ...
});

解决方案

经过数小时的研究和测试,我终于明白了,这是一个(非常非常)愚蠢的情况.所以,在我的问题中,我说

所以我禁用了它(spring-security.xml上的csrf),仍然有问题.

不,我没有禁用它.我正在尝试禁用它

<!--
<csrf/>
-->

但我应该这样做:

<csrf disabled="true"/>

注释csrf标签不会禁用csrf,这是因为csrf默认情况下处于启用状态!找到问题后,很容易说出这是一个愚蠢的错误,但是当我添加csrf标记来启用它时,我认为注释它会禁用它.在 Spring文档

现在,回到我的问题了.要修复启用CSRF的POST AJAX调用中的405错误消息,这确实很容易.我将csrf参数保留在JS变量中,如下所示:

<script type="text/javascript">
    var csrfParameter = '${_csrf.parameterName}';
    var csrfToken = '${_csrf.token}';
</script>

然后我的ajax调用看起来像这样:

var jsonParams = {};
jsonParams['parentId'] = 1;
jsonParams[csrfParameter] = csrfToken;
$.ajax({
    type: 'POST',
    cache: false,
    url: /admin/events/loadEvents,
    data: jsonParams,
    dataType = 'json',
    contentType = 'application/json',

    ...
});

像魔术师一样工作.希望能对以后的人有所帮助.

I'm trying to make an ajax call to my Spring controller/action with POST method, and return an object from the server with @ResponseBody. The strange situation is that it stop working after add spring security layer, everything was working fine before. I will try to explain my moves to solve the problem and then show you the code/captures/etc.

1. After some research I found some answers telling the problem might be related with csrf mechanism, so I disabled it and still have the issue. (spring-security.xml bellow)

2. I've made a wireshark capture to check the request/response. My ajax request is OK, my controller declaration is OK, but I don't understand why, the 405 response indicates > Allow: GET (capture bellow)

3. I've tried to access my controller action through the browser (i.e., make an GET request), and I get the error HTTP Status 405 - Request method 'GET' not supported!

4. I've tried to change the RequestMapping(method...) to RequestMethod.GET and the request arrives to the controller and works fine, but I don't want it to work on GET method, I want a POST request.

5. Changed the RequestMapping(consumes, produces, headers) to accept all kind of data, but still 405...

This is driving me crazy! I post my files bellow, so you can check it guys, any tip will be appreciated. Thanks! (IMPORTANT NOTE: this is my despair configuration)

spring-security.xml

<beans:beans 
     xmlns...(all needed declarations)>

<http pattern="/js/**" security="none" />
<http pattern="/css/**" security="none" />

<!-- enable use-expressions -->
<http auto-config="true" >
    <access-denied-handler error-page="/403" />
    <intercept-url pattern="/admin/**" access="hasRole('ROLE_ADMIN')" />
    <intercept-url pattern="/login" access="isAnonymous()" />
    <intercept-url pattern="/403" access="permitAll" />
    <intercept-url pattern="/**" access="hasRole('ROLE_USER')" />

    <form-login  login-page="/login"
                 username-parameter="email"
                 password-parameter="password"
                 authentication-failure-url="/login?failed" />

    <!--
    <csrf/>
    -->
</http>

 ..... (authentication)  

AdminController.java

@Controller
@RequestMapping("/admin**")
public class AdminController {

    ... (all my autowired beans)

    @RequestMapping(
        value = "/events/loadEvents",
        method = RequestMethod.POST,
        consumes = MediaType.ALL_VALUE,
        produces = MediaType.ALL_VALUE,
        headers = "Accept=*/*")
    @ResponseBody
    public Event loadEvents(@RequestParam("parentId") long parentId) {
        ... (my logic)
        return event;
    }
}

Request (wireshark capture)

Response (wireshark capture)

EDIT jquery ajax call code

$.ajax({
    type: 'POST',
    cache: false,
    url: /admin/events/loadEvents,
    data: { parentId: 1 },
    dataType = 'json',
    contentType = 'application/json',

    ...
});

解决方案

After many hours of research and tests, I finally got it, ant it was a (very very) stupid situation. So, in my question I said

so I disabled it (csrf on spring-security.xml) and still have the issue.

No, I didn't disabled it. I was trying to disable it doing

<!--
<csrf/>
-->

But I should be doing:

<csrf disabled="true"/>

Commenting csrf tag does NOT disable csrf, this is because csrf is enabled by default! After find the problem is really easy to say that is a stupid mistake, but as I added csrf tag to enable it, I thought that commenting it would disable it. Find the answer on Spring Documentation

Now, back into my problem. To fix the 405 error message in a POST AJAX call WITH CSRF ENABLED, it was really easy. I keep the csrf parameters in JS variables like this:

<script type="text/javascript">
    var csrfParameter = '${_csrf.parameterName}';
    var csrfToken = '${_csrf.token}';
</script>

and then my ajax call looks like this:

var jsonParams = {};
jsonParams['parentId'] = 1;
jsonParams[csrfParameter] = csrfToken;
$.ajax({
    type: 'POST',
    cache: false,
    url: /admin/events/loadEvents,
    data: jsonParams,
    dataType = 'json',
    contentType = 'application/json',

    ...
});

Working like a charme. Hope that helps someone in the future.

这篇关于Ajax POST结果为405(不允许使用方法)-Spring MVC的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆