web-dev-qa-db-ja.com

JAX-RS(ジャージー)および@RolesAllowedを使用したカスタムHTTPステータス応答

私の非常に単純なJAX-RSサービスでは、認証にJDBCレルムを備えたTomcatを使用しているため、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ステータス応答を作成する方法はありますか?

16
Stefan

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

例外マッパーを登録する方法は、使用しているフレームワークによって異なりますが、ジャージーの場合は、@Providerを使用するだけで問題ありません。私はあなたがあなたが望む種類のエラードキュメントをどのように生成したいかをあなたに理解させますが、私は失敗をある種のHTTPエラーコードとして処理することをお勧めします(それはよりRESTfulです...)

20
Donal Fellows

ExceptionMapperWebApplicationExceptionの例外のマッピング)を作成すると、アプリケーションによってスローされた特定の例外を「キャッチ」できます。

@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>
9
Stefan

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

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

1
yves amsellem