403 on JSON PUT请求Tomcat与Spring 3.0.5和Jackson

时间:2011-03-25 13:59:08

标签: spring tomcat spring-security jackson

我的网络应用程序已开始在PUT请求中返回403错误。但是,我没有在日志中看到此请求的任何调试消息,因此我对如何进一步调试这一点感到难过。

此代码曾用于工作,但最近有一些变化: 客户是Sencha JS:

Ext.Ajax.request({
        url       : '/RestWAR/personal/trailSegment/' + trailSegment.id + '.json',
        method    : 'PUT',
        headers   : {'Content-Type': 'application/json'},
        jsonData  : segmentDto
});

容器是Apache Tomcat 6.0。 在转到Spring 3.0.5之前,请求转到Spring Security 3.0.0.RC1。

@Controller
@RequestMapping("/personal")
public class PersonalController {
    @RequestMapping(value = "trailSegment/{trailSegmentId}", method=RequestMethod.PUT)
    public void updateTrailSegment(@PathVariable long trailSegmentId, @RequestBody PersonalTrailSegmentDTO trailSegmentDto) {
    //...
    }
}

最近的变化: Spring在3.0.0.M4上,json库是net.sf.json-lib 1.0.2。 Spring现在是3.0.5,json库现在是Jackson Mapper ASL 1.4.2(即Spring建议的那样)。

GET和POST工作正常。这只是失败的PUT。

如果涉及Spring Security,那么我会看到来自Spring Security的调试消息,但我什么也看不见。似乎Tomcat正在停止请求。

提前感谢您的帮助 - 尤其是在调试方面。

2 个答案:

答案 0 :(得分:1)

  

我很想知道是否有   解决这个问题,我们达到了同样的目标   与Tomcat 6.0.x和Spring有关   3.0.1使用PUT& @RequestParam(我想我们也试过了@RequestBody),PUT   与Jetty合作但不是   与Tomcat,除非你添加   url的参数为?someParam = value。   我们选择只使用它来解决它   而是POST。

我刚刚发布了几分钟之前的评论,现在当我们点击这个时我回想起来,我记得我发现this线程(参数从PUT 中消失)当时问题。阅读它,似乎Tomcat开发人员解释HTTP规范意味着PUT不应该支持参数:

  

嗯,你确定PUT请求吗?   实际上承认“参数”?   http://www.ietf.org/rfc/rfc2616.txt,   第9.6节

     

PUT请求请求   附属实体(在要求机构中)   存储在指示的位置   URI。但我没有看到提及   参数在这里。

-

  

这些方面还有足够的余地   段落,以证明这一事实   Tomcat开发人员可能已经   有理由不实施任何   处理PUT的“参数”   要求;而其他的开发者   servlet引擎可能已经感觉到了   有理由提供这种处理。   我想说的是   如果你创建一个应用程序   取决于正在处理的参数   在PUT请求中,您可能会创建   一个不便携的应用程序   到所有servlet引擎或HTTP   服务器。但那当然是你的   选择。

     

所有这些都引发了一个问题:   在之前的帖子中,你提到了这一点   该请求在POST时工作正常。为什么   然后你坚持把它作为PUT发送   ?

答案 1 :(得分:1)

问题是从updateTrailSegment()方法返回null。这会导致Spring尝试使用InternalResourceView将请求映射到请求中的内容 - 即/RestWAR/personal/trailSegment/1761InternalResourceView表示它尝试将该URL解析为应用程序中的路径。由于没有 - 它失败了。

修复程序用作返回类型:

@ResponseBody ExtResponse

ExtResponse只是一个返回响应代码的简单POJO。

完整的方法现在是:

@RequestMapping(value = "trailSegment/{trailSegmentId}", method=RequestMethod.PUT)
public @ResponseBody ExtResponse updateTrailSegment(@PathVariable long trailSegmentId, @RequestBody PersonalTrailSegmentDTO trailSegmentDto) {
    trailSegmentDto.setId(trailSegmentId);
    PersonalTrailSegment trailSegment = trailSegmentAssembler.assembleDomain(trailSegmentDto);
    trailSegmentDataGateway.update(trailSegment);
    return new ExtResponse("true", "");
}