Ajax POST 导致 405(不允许的方法) - Spring MVC

Posted

技术标签:

【中文标题】Ajax POST 导致 405(不允许的方法) - Spring MVC【英文标题】:Ajax POST results in a 405 (Method Not Allowed) - Spring MVC 【发布时间】:2016-03-19 08:26:10 【问题描述】:

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

1。 经过一些研究,我发现一些答案表明问题可能与 csrf 机制有关,所以我禁用了它,但问题仍然存在。 (下面的spring-security.xml)

2。 我制作了一个wireshark 捕获来检查请求/响应。我的 ajax 请求没问题,我的控制器声明没问题,但我不明白为什么,405 响应表明 > Allow: GET(捕获波纹管)

3。 我尝试通过浏览器访问我的控制器操作(即发出 GET 请求),我收到错误 HTTP Status 405 - Request method 'GET' not supported

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

5。 更改了 RequestMapping(consumes,produces,headers) 以接受所有类型的数据,但仍然是 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',

    ...
);

【问题讨论】:

我看不到您发送任何凭据?你的 403 是如何实现的? 我是在认证后才到达应用程序的这个区域,即第一步是认证,然后会话认证由Spring Security管理。正如我所提到的,如果我将 jquery 调用和控制器操作方法更改为 GET,它可以正常工作。问题是,如果一切都配置好,为什么我会在 POST 中得到 405。 谁能解释为什么它必须给出 405 而不是任何其他状态?当 URI 不支持给定的 HTTP 方法时应该显示 405 对吗? 【参考方案1】:

在我的情况下,有同样的问题,可以帮助解决这个问题:

添加标签库:
 <%@ taglib prefix="sec" uri="http://www.springframework.org/security/tags" %>
在jsp正文中添加:
<sec:csrfMetaTags />
在 ajax 中添加
headers: "X-CSRF-TOKEN": $("meta[name='_csrf']").attr("content")

附:感谢 Illya Shulgin,很酷的答案,现在就在这里。

【讨论】:

【参考方案2】:

$.ajaxSetup(
    dataType: "json",
    beforeSend: function(xhr, settings)
        var csrftoken = $.cookie('CSRF-TOKEN');
        xhr.setRequestHeader("X-CSRF-TOKEN", csrftoken);
    ,
);

【讨论】:

【参考方案3】:

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

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

不,我没有禁用它。我试图禁用它

<!--
<csrf/>
-->

但我应该这样做:

<csrf disabled="true"/>

评论csrf标签NOT禁用csrf,这是因为csrf默认启用!发现问题后真的很容易说这是一个愚蠢的错误,但是当我添加 csrf 标签来启用它时,我认为评论它会禁用它。在Spring Documentation找到答案

现在,回到我的问题。要修复 POST AJAX 调用 WITH CSRF ENABLED 中的 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',

    ...
);

像魅力一样工作。希望对以后的人有所帮助。

【讨论】:

感谢它对我帮助很大 谢谢。这对我有帮助。我希望您对以下内容发表意见 - 我很少有返回 JSON 响应和返回视图的 RestControllers。如果我启用 csrf,当我对休息控制器进行 ajax 调用时,如果失败并出现 405 错误。我应该做什么?禁用csrf?或在 ajax 调用中发送 csrf 令牌?推荐哪一个? 您应该在每次通话中发送您的 csrf 令牌。只是出于安全原因。如果你不介意安全问题,那么你可以禁用 csrf

以上是关于Ajax POST 导致 405(不允许的方法) - Spring MVC的主要内容,如果未能解决你的问题,请参考以下文章

带有ajax jQuery的405(不允许方法)(POST)方法

jQuery .ajax() POST 请求抛出 405(不允许的方法)但 GET 不会

Laravel 5.1 AJAX - 即使我发送 POST 请求,也不允许返回 405 GET 方法

“405 方法不允许” - 使用 ASP.NET jQuery ajax POST 时

使用 requests.post 登录导致“错误 405 不允许”

选项 405(不允许的方法)