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

发布于 2024-11-18 04:47:17 字数 889 浏览 2 评论 0原文

通过我非常简单的 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>

如果具有与“ 当 Jersey 返回以下正文时:

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 状态响应?

With my very simple JAX-RS service I'm using Tomcat with JDBC realm for authentication, therefore I'm working the the JSR 250 annotations.

The thing is that I want to return a custom message body in the HTTP status response. The status code (403) should stay the same. For example, my service looks like the following:

@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 ...;
    }
}

If a user with a different role than "ADMIN" access the service, I want to change the response message to something like that (depending on the media type [xml/json]):

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

At the moment Jersey returns the following body:

HTTP Status 403 - Forbidden

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

How can I change the default message body? Is there a way to handle the (maybe thrown) exception to build my own HTTP status response?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

寒尘 2024-11-25 04:47:17

处理此类事情的最简单方法是抛出异常并注册异常映射器以转换为您想要在这种情况下发送的消息类型。因此,假设您抛出一个 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...)

The easiest way to handle this sort of thing is to throw an exception and to register an exception mapper to convert into the kind of message you want to send in that case. So, suppose you throw an AccessDeniedException, you would then have a handler like this (with full class names in places for clarity):

@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();
    }
}

The way in which you register the exception mapper varies according to the framework you're using, but for Jersey you should be fine with just using @Provider. I'll let you figure out for yourself how you want to generate the kind of error documents that you want, but I do recommend handling failures as HTTP error codes of some kind (that's more RESTful...)

若能看破又如何 2024-11-25 04:47:17

通过创建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>

With creating an ExceptionMapper (mapping exceptions of WebApplicationException) it is possible to "catch" certain exceptions thrown by the application:

@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();
    }
}

You also need to add the package to your application web.xml for registering the provider:

<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>
深爱不及久伴 2024-11-25 04:47:17

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

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

REST is build upon HTTP so you don't have to change the default behavior of an authentication failure. Having a 403 error when accessing a resource is enough for the client to clearly understand what appends.

The more your resources are HTTP compliant, the more others can understand it.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文