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>
Sto usando la versione di sicurezza 3.0.5. Ho aggiunto @ExceptionHandler (AccessDeniedException.class) al mio controller. Sempre ottenendo la stessa pagina di accesso. –
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? –
È 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