2011-06-29 9 views
15

Z moją bardzo prostą usługą JAX-RS używam Tomcat z dziedziną JDBC do uwierzytelniania, dlatego używam adnotacji JSR 250.Niestandardowa odpowiedź o statusie HTTP za pomocą JAX-RS (Jersey) i @RolesAllowed

Chodzi o to, że chcę zwrócić niestandardową treść wiadomości w odpowiedzi na stan HTTP. Kod statusu (403) powinien pozostać taki sam. Na przykład, mój serwis wygląda następująco:

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

Jeśli użytkownik z innej roli niż „admin” dostęp do usługi, chcę zmienić komunikat odpowiedzi na coś takiego (w zależności od typu nośnika [ xml/json]):

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

Obecnie Jersey powraca następujące ciała:

HTTP Status 403 - Forbidden 

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

Jak mogę zmienić domyślną treść wiadomości? Czy istnieje sposób obsłużenia wyjątku (może być zgłoszony) do zbudowania mojej własnej odpowiedzi na stan HTTP?

+0

Kompletny przykład: https://www.bhaveshthaker.com/25/customize-handling-server-side-exceptions-with-error-codes-using-exceptionmapper-with-jersey-jax-rs-in-java/ – RAS

Odpowiedz

17

Najprostszym sposobem radzenia sobie z takimi rzeczami jest zgłoszenie wyjątku i zarejestrowanie programu odwzorowującego wyjątki w celu przekonwertowania na rodzaj wiadomości, którą chcesz wysłać w takim przypadku. Więc załóżmy, że rzucić AccessDeniedException, byś potem mają obsługi takiego (z pełnych nazw klas w miejscach, dla jasności):

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

Sposób, w jaki się zarejestrować program mapowania wyjątek zmienia się zgodnie z ramami you” Ponownie używaj, ale dla Jersey powinieneś mieć się dobrze używając tylko @Provider. Pozwolę ci samemu dowiedzieć się, jak chcesz generować żądane dokumenty błędów, ale zalecam obsługę błędów jako kodów błędów HTTP (to jest bardziej RESTOWN ...)

+0

Chodzi o to, że Jersey zwraca niestandardową odpowiedź 403. Nie jestem w stanie rzucić 'AccessDeniedException' dla autoryzacji, ponieważ rzeczy @RolesAllowed obsługuje to. Kod błędu HTTP powinien być tym, który po prostu chcę zmienić treść wiadomości. – Stefan

+0

Myślałem, że możesz to zrobić w Jersey z ExceptionMapper; Wiem, że możesz z Apache CXF (chociaż jest to inaczej skonfigurowane z powodów, które doceniłem), więc uznałem za rozsądne przynajmniej _tak, biorąc pod uwagę, że oba są silnikami JAX-RS, a to jest po prostu użycie interfejsu API JAX-RS , ale nie mam bezpośredniego doświadczenia z Jersey, więc może jest coś nieoczekiwanego. –

9

Z tworzeniem an ExceptionMapper (wyjątki odwzorowywanie WebApplicationException) możliwe jest, aby „złapać” pewne wyjątki rzucane przez aplikację:

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

trzeba także dodać pakiet do web.xml aplikacji do rejestracji dostawcy:

<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

Miałem do czynienia z tym samym problemem iw moim przypadku była to doskonała odpowiedź. Dzięki Stefan! – Lars

1

REST opiera się na protokole HTTP, więc nie trzeba zmieniać domyślnego zachowania niepowodzenia uwierzytelnienia. Wystąpienie błędu 403 podczas uzyskiwania dostępu do zasobu jest wystarczające, aby klient dokładnie zrozumiał, co dołącza.

Im więcej zasobów jest zgodnych z protokołem HTTP, tym więcej osób może je zrozumieć.

+2

Problem polega na tym, że mogą występować różne sytuacje, w których występuje jeden błąd http.Jednym z nich może być limit czasu sesji (wyniki 403) zarządzany przez AS. Innym może być nieautoryzowany dostęp do zasobu odpoczynku (403). Jeśli musisz programowo reagować na te błędy w różny sposób, to jest to dobry sposób na ich personalizację. – Lars

Powiązane problemy