16

私の非常に単純な 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 ステータス応答を作成する方法はありますか?

4

3 に答える 3

21

この種のことを処理する最も簡単な方法は、例外をスローし、例外マッパーを登録して、その場合に送信したい種類のメッセージに変換することです。したがって、 をスローする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 です...)。

于 2011-06-29T21:26:00.563 に答える
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>
于 2011-06-30T09:30:35.137 に答える
1

REST は HTTP に基づいて構築されているため、認証失敗のデフォルトの動作を変更する必要はありません。リソースにアクセスするときに 403 エラーが発生するだけで、クライアントは何を追加するかを明確に理解できます。

リソースが HTTP に準拠していればいるほど、他の人が理解できるようになります。

于 2011-07-01T13:14:57.763 に答える