【问题标题】:How do I create a custom JSON 401 page for my Spring MVC/Security restful web service?如何为我的 Spring MVC/Security RESTful Web 服务创建自定义 JSON 401 页面?
【发布时间】:2012-07-12 00:01:34
【问题描述】:

我正在尝试使用 Servlet 3.0、Spring MVC 和 Spring Security 创建一个安全的宁静 Web 服务。我想在 401 上返回自定义 JSON 消息,而不是 Servlet 容器返回的默认 HTML 消息。

我尝试了几种方法,但似乎无法正常工作。

我的控制器如下所示::

@Controller
@RequestMapping("/")
public class ApplicationController {

    private ApplicationFactory applicationFactory;

    @Inject
    public ApplicationController(ApplicationFactory applicationFactory) {
        super();
        this.applicationFactory = applicationFactory;
    }

    @RequestMapping(method = GET)
    @ResponseBody
    @Secured("ROLE_USER")
    public Application getApplicationInfo() {
        return applicationFactory.buildApplication(this);
    }

}

我的 Spring Security 上下文如下所示:

<security:global-method-security secured-annotations="enabled" mode="aspectj" />

<security:http auto-config="true" use-expressions="true">
<security:http-basic />
</security:http>

我尝试添加以下内容:

@ExceptionHandler(AccessDeniedException.class)
@ResponseBody
public Application accessDenied() {
    return applicationFactory.buildApplication(this);
}

但它被忽略了。我已经尝试将“access-denied-page="/denied"” 添加到我的 security:http 标记中,并在我的控制器中使用以下内容:

@RequestMapping(value = "/denied", method = GET)
@ResponseBody
public Application accessDenied() {
    return applicationFactory.buildApplication(this);
}

但它被忽略了。我尝试了一个自定义访问被拒绝处理程序,如下所示:

<security:http auto-config="true" use-expressions="true">
<security:http-basic />
<security:access-denied-handler ref="jsonAccessDeniedHandler" />
</security:http>

似乎唯一有效的方法如下:

@ExceptionHandler(Exception.class)
@ResponseBody
public Application accessDenied() {
    return applicationFactory.buildApplication(this);
}

但这可以捕获所有内容,我只想自定义失败的身份验证。

最后,将它添加到我的 web.xml 也可以:

<error-page>
<error-code>401</error-code>
<location>/401</location>
</error-page>

但我更愿意以编程方式或通过注释进行配置。

【问题讨论】:

    标签: java spring spring-mvc spring-security


    【解决方案1】:

    要使用@ResponseBody 并操作响应头,我们如下:

    @RequestMapping(value = "/url", method = RequestMethod.GET, headers = { "Accept=application/json" })
    public @ResponseBody
    List handle(HttpServletResponse response,
    @RequestHeader("headerID") String headerString) {
    response.setHeader("responseHeaderProperty", String);
    return service.doSomething();
    }
    

    【讨论】:

    • 这是一个替代方案,但是当 Spring Security 已经为我处理 HTTP 标头时,它似乎打破了 DRY。顺便说一句,您可能可以编辑您的原始答案并将上面的内容复制并粘贴到其中!
    • 好吧,我可以将它添加到评论中(它太大了),这部分并没有反映你原来的问题。但很高兴能提供帮助:X
    【解决方案2】:

    在spring 3.0中有一个注解ResponseStatus

    我是这样使用这个注解的;

    @ResponseStatus(value = 401)
    @ExceptionHandler(value = HttpMessageNotReadableException.class)
    @ResponseBody
    public ErrorResponse handleJsonMappingException(HttpMessageNotReadableException e) {
    

    这有用吗?

    【讨论】:

    • 不幸的是,这似乎不起作用:spring security 忽略了 @ResponseStatus(UNAUTHORIZED) 和 @ExceptionHandler(AccessDeniedException.class) 注释。我还需要什么额外的配置吗?
    • 更正:使用 @ResponseStatus(UNAUTHORIZED) 和 @ExceptionHandler(AccessDeniedException.class) 与 Spring Security 3.1 一起使用。
    • humh 是这么想的,这是 spring 3.1 的特性(我使用的是 spring 3.1.x)
    • 呃哦,刚刚发现上面的解决方案没有将 WWW-Authenticate HTTP 标头添加到 401 响应中,所以客户端不知道要验证哪个领域,所以在我的浏览器中,不会提示用户输入凭据。
    猜你喜欢
    • 2022-09-24
    • 2016-11-16
    • 2015-04-13
    • 2012-11-06
    • 2014-03-22
    • 2016-10-01
    • 2014-07-31
    • 2011-06-13
    • 1970-01-01
    相关资源
    最近更新 更多