使用JAX-RS(Jersey)和@RolesAllowed自定义HTTP状态响应

时间:2011-06-29 11:39:40

标签: java jersey jax-rs jsr250

通过我非常简单的JAX-RS服务,我使用Tomcat和JDBC领域进行身份验证,因此我正在使用JSR 250注释。

问题是我想在HTTP状态响应中返回自定义消息体。状态代码(403)应保持不变。例如,我的服务如下所示:

@RolesAllowed({ "ADMIN" })
@Path("/users")
public class UsersService {

    @GET
    @Produces(MediaType.TEXT_PLAIN)
    @Consumes({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
    public String getUsers() {
        // get users ...
        return ...;
    }
}

如果角色与“ADMIN”不同的用户访问该服务,我想将响应消息更改为类似的内容(取决于媒体类型[xml / json]):

<error id="100">
    <message>Not allowed.</message>
</error>

目前泽西岛返回以下机构:

HTTP Status 403 - Forbidden

type Status report
message Forbidden
description Access to the specified resource (Forbidden) has been forbidden.
Apache Tomcat/7.0.12

如何更改默认邮件正文?有没有办法处理(可能抛出)异常来构建我自己的HTTP状态响应?

3 个答案:

答案 0 :(得分:18)

处理此类事情的最简单方法是抛出异常并注册异常映射器以转换为在这种情况下要发送的消息类型。所以,假设你抛出一个AccessDeniedException,你会得到一个像这样的处理程序(为了清楚起见,在地方有完整的类名):

@javax.ws.rs.ext.Provider
public class AccessDeniedHandler
        implements javax.ws.rs.ext.ExceptionMapper<AccessDeniedException> {
    public javax.ws.rs.core.Response toResponse(AccessDeniedException exn) {
        // Construct+return the response here...
        return Response.status(403).type("text/plain")
                .entity("get lost, loser!").build();
    }
}

注册异常映射器的方式因您使用的框架而异,但对于Jersey,只需使用@Provider即可。我会让你自己弄清楚你想要如何生成你想要的那种错误文档,但是我建议把失败当作某种HTTP错误代码处理(那更加RESTful ......)

答案 1 :(得分:9)

通过创建ExceptionMapper(映射WebApplicationException的异常),可以“捕获”应用程序抛出的某些异常:

@Provider
public class MyExceptionMapper implements ExceptionMapper<WebApplicationException> {

    @Override
    public Response toResponse(WebApplicationException weException) {

        // get initial response
        Response response = weException.getResponse();

        // create custom error
        MyError error = ...;

        // return the custom error
        return Response.status(response.getStatus()).entity(error).build();
    }
}

您还需要将软件包添加到应用程序web.xml以注册提供程序:

<init-param>
    <param-name>com.sun.jersey.config.property.packages</param-name>
    <param-value>
        com.myapp.userservice; // semi-colon seperated
        com.myapp.mappedexception
    </param-value>
</init-param>

答案 2 :(得分:2)

REST是基于HTTP构建的,因此您无需更改身份验证失败的默认行为。访问资源时出现403错误足以让客户清楚地了解追加的内容。

您的资源越符合HTTP,其他人就越能理解它。