2014-05-09 14 views
5

Sto implementando la restrizione/autorizzazione del livello metodo (nei servizi REST) utilizzando la sicurezza Spring.
Ho utilizzato il linguaggio di espressione primaverile e implementato l'Expression Evaluator personalizzato.Restituisce JSON su richiesta di servizio REST non autorizzato utilizzando Spring Security 'hasPermission()'

Sta funzionando bene per me. Tuttavia, se un utente non autorizzato tenta di accedere al servizio, risponde con una pagina di accesso. Poiché la mia applicazione è REST basata solo su, voglio restituire solo i dati JSON per tutte le richieste.

Come faccio a farlo tornare JSON, invece della pagina di login (ad esempio: {status : Denied})?

Ecco il frammento di codice:

CustomEvaluator

public boolean hasPermission(Authentication authentication, Object userId, Object permissionId) { 
     List<String> permList = new MyDAO().getPermissionsForUser((String) userId); 
     if(permList.contains(((String) permissionId))){ 
      return true; 
     }else{ 
      return false; 
     } 
    } 

Servizio

@PreAuthorize("hasPermission(#userId, '3')") 
    public String testAuthorization(Object obj, String userId){ 

     System.out.println("Has access to the service method...."); 

     return "success"; 
    } 

controller

public @ResponseBody String testAuthorization(Object o,@RequestParam("userId") String userId){ 
     System.out.println("User ID = "+userId); 
     String abc = service.testAuthorization(o,userId); 
     return "{\"status\":\"success\"}"; 
    } 

primavera-security.xml

<?xml version="1.0" encoding="UTF-8"?> 
<beans xmlns="http://www.springframework.org/schema/beans" 
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
     xmlns:security="http://www.springframework.org/schema/security" 
     xsi:schemaLocation="http://www.springframework.org/schema/beans 
      http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 
      http://www.springframework.org/schema/security 
      http://www.springframework.org/schema/security/spring-security-3.0.xsd"> 


    <security:global-method-security secured-annotations="enabled" pre-post-annotations="enabled"> 
     <security:expression-handler ref="expressionHandler"/> 
    </security:global-method-security> 

    <!-- This is where we configure Spring-Security --> 
    <security:http auto-config="true" use-expressions="true" access-denied-page="/auth/auth/denied" > 
     <security:intercept-url pattern="/auth/auth/login" access="permitAll"/> 
     <security:intercept-url pattern="/auth/main/admin" access="hasRole('ROLE_ADMIN')"/> 
     <security:intercept-url pattern="/auth/main/common" access="hasRole('ROLE_USER')"/> 


    </security:http> 

    <security:authentication-manager> 
     <security:authentication-provider user-service-ref="customUserDetailsService"> 
      <security:password-encoder ref="passwordEncoder"/> 
     </security:authentication-provider> 
    </security:authentication-manager> 

    <!-- Use a Md5 encoder since the user's passwords are stored as Md5 in the database --> 
    <bean class="org.springframework.security.authentication.encoding.Md5PasswordEncoder" id="passwordEncoder"/> 

    <!-- A custom service where Spring will retrieve users and their corresponding access levels --> 
    <bean id="customUserDetailsService" class="com.cjl.security.service.CustomUserDetailsService"/> 

    <bean id="expressionHandler" class="org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler"> 
     <property name="permissionEvaluator" ref="permissionEvaluator"/> 
    </bean> 

    <bean id="permissionEvaluator" class="com.cjl.security.evaluators.MethodPermissionEvaluator"/> 


</beans> 

risposta

5

Quello che sta accadendo è un AccessDeniedException viene gettato, così si vuole configurare il sistema per intercettare questa eccezione e invece ritorno JSON.

È possibile impostare un metodo @ExceptionHandler all'interno del controller che cattura lo AccessDeniedException. Tuttavia, probabilmente vorrai fare la stessa cosa in tutti i tuoi controller, quindi se utilizzi Spring 3.2, puoi utilizzare l'annotazione @ControllerAdvice in una classe separata "advice" e includere il metodo @ExceptionHandler.

@ControllerAdvice 
public class ExceptionControllerAdvice { 

    @ExceptionHandler(AccessDeniedException.class) 
    @ResponseBody 
    public String exception(AccessDeniedException e) { 
     return "{\"status\":\"access denied\"}"; 
    } 
} 
+0

Sto usando la versione di sicurezza 3.0.5. Ho aggiunto @ExceptionHandler (AccessDeniedException.class) al mio controller. Sempre ottenendo la stessa pagina di accesso. –

+0

Mi dispiace, mio ​​errore. Funziona ora. Nella versione 3.0.5, se devo gestire la stessa eccezione in un altro controller, qual è il modo? La duplicazione della gestione delle eccezioni è l'unico modo? –

+0

È possibile duplicare il gestore oppure è possibile creare un controllo astratto che si estende a tutti gli altri controller. Potresti anche essere in grado di creare un aspetto itd che dichiari il gestore per tutti i tuoi controller, anche se ammetto di non averlo provato. – DavidA

Problemi correlati