【问题标题】:403 on JSON PUT request to Tomcat with Spring 3.0.5 and Jackson403 对带有 Spring 3.0.5 和 Jackson 的 Tomcat 的 JSON PUT 请求
【发布时间】:2011-07-22 22:48:41
【问题描述】:

我的 Web 应用程序已开始在 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 似乎正在停止请求。

在此先感谢您的帮助 - 特别是在调试方面。

【问题讨论】:

  • 为什么还在使用测试版的 Spring Security?
  • 我很想看看是否有解决方案,我们使用 PUT 和 @RequestParam 对 Tomcat 6.0.x 和 Spring 3.0.1 进行了同样的处理(我想我们也尝试过 @RequestBody) ,PUT 可以在 Jetty 上正常工作,但不能在 Tomcat 上正常工作,除非您将参数作为 ?someParam=value 添加到 url。我们选择使用 POST 来绕过它。
  • 我正在使用 beta 版本,因为我升级了 Spring 上一个版本,并且不想通过升级 Spring Security 来关闭太多。当我查看更改日志时,我没有看到任何有关的内容。我一定会在某个阶段解决这个问题。

标签: spring tomcat spring-security jackson


【解决方案1】:

问题是从 updateTrailSegment() 方法返回 null。这会导致 Spring 尝试使用 InternalResourceView 与请求中内容的 url 映射请求 - 即 /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", "");
}

【讨论】:

  • 很高兴听到你让它工作了,有时我自己必须尝试这样的事情,看看它是否可以解决我们的 Tomcat-PUT-403 -问题(尽管现在一切都可以正常使用 POST,所以并不是说我们真的需要它了,只是出于好奇)
【解决方案2】:

我有兴趣看看是否有 解决这个问题,我们遇到了同样的问题 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 发送 ?

【讨论】:

  • 我正在做一个 RESTful 接口。 POST 意味着创建一个文档。 PUT 表示替换它。您的评论表明我需要确保将文档发送回请求正文,但我相信我已经通过使用 @RequestBody 完成了这项工作。不过需要仔细检查。
  • 我想通了。如果您的意思是“所有这一切都会引发一个问题:在较早的帖子中,您提到该请求可以作为 POST 正常工作。那你为什么坚持把它作为 PUT 发送?'-部分,这是我链接到的线程中的一个位置,并且是在线程的 OP 处。
  • 如果可能的话,我想继续使用 PUT,以保持界面的意识形态清洁。 :-) 更重要的是,我想了解它为什么会失败,而不是盲目地尝试。
  • 很好的回应——“链接”又名markmail.org/thread/bqb44tqnhmvtlji6 非常有用,尽管线程中有 37 条消息!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-04-18
  • 2011-06-13
  • 1970-01-01
  • 2014-10-31
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多