2011-06-29 9 views
15

私は非常にシンプルなJAX-RSサービスで、私は認証のためにJDBCレルムでTomcatを使用していますので、私はJSR 250アノテーションを使っています。JAX-RS(ジャージー)と@RolesAllowedでのカスタムHTTPステータス応答

問題は、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ステータスレスポンスを構築するために(おそらく投げられる)例外を処理する方法はありますか?

+0

完全な例:https://www.bhaveshthaker.com/25/customize-handling-server-side-exceptions-with-error-codes-using-exceptionmapper-with-jersey-jax-rs-in-java/ – RAS

答えて

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

あなたは例外マッパーを登録する方法は、あなたの「フレームワークによって異なります再使用しますが、ジャージーの場合はちょうど@Providerを使用すると問題ありません。あなたが望むような種類のエラー文書を生成する方法を自分で判断できるようにしますが、何らかのHTTPエラーコードとしてエラーを処理することをお勧めします(よりリーズナブルです...)

+0

ジャージーがカスタム403の返品を返すことです。 @RolesAllowedスタッフがこれを処理するため、承認のための 'AccessDeniedException'をスローすることができません。 HTTPエラーコードは、私がボディメッセージを変更したいだけのものでなければなりません。 – Stefan

+0

私はあなたがExceptionMapperを使ってジャージーでそれをできると思った。私はあなたがApache CXFを使ってできることを知っています(それは感謝してきた理由で異なって構成されていますが)ので、JAX-RSエンジンでJAX-RS APIを使用していることを考えると、少なくとも_しかし、私はジャージーとの直接の経験はないので、おそらく予期せぬことが起こっているかもしれません。 –

9

作成中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> 
+0

私は同じ問題に直面していて、私の場合は完璧な答えでした。ステファンありがとう! – Lars

1

RESTはHTTPをベースにしているため、認証エラーのデフォルト動作を変更する必要はありません。リソースにアクセスする際に403エラーが発生すると、クライアントが追加する内容を明確に理解するだけで十分です。

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

+2

問題は、単一のHTTPエラーが発生するさまざまな状況が存在する可能性があることです。1つは、ASによって管理されるセッションタイムアウト(403の結果)とすることができる。別のものは、休憩リソースへの不正な試み(403)であり得る。これらのエラーに対してさまざまな方法でプログラム的に反応させる必要がある場合は、それらをカスタマイズする良い方法です。 – Lars

関連する問題