2014-05-09 22 views
5

我實現方法級別限制/授權(在REST服務)使用Spring的安全性未經授權的REST服務請求。
我已經使用了spring表達式語言並實現了自定義Expression Evaluator。返回JSON使用Spring Security的 '調用hasPermission()'

這是爲我工作的罰款。但是,如果未經授權的用戶嘗試訪問該服務,它將以登錄頁面進行響應。由於我的應用程序只基於REST ,我要爲所有請求僅返回JSON數據。

我如何讓它返回而不是登錄頁面JSON(如:{status : Denied})?

這裏是代碼片段:

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

服務

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

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

     return "success"; 
    } 

控制器

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\"}"; 
    } 

彈簧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> 

回答

5

正在發生的事情是AccessDeniedException被拋出,所以你要配置你的系統來攔截異常,而不是返回JSON。

您可以在您的控制器中設置一個@ExceptionHandler方法,該方法捕獲AccessDeniedException。不過,你可能想要做同樣的事情在所有的控制器,所以如果你使用Spring 3.2,你可以在一個單獨的「忠告」類中使用@ControllerAdvice註釋,然後包括@ExceptionHandler方法在那裏。

@ControllerAdvice 
public class ExceptionControllerAdvice { 

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

我正在使用spring-security版本3.0.5。我添加了@ExceptionHandler(AccessDeniedException.class)到我的控制器。仍然獲得相同的登錄頁面。 –

+0

對不起,我的錯。它正在工作。在3.0.5版本中,如果我必須在另一個控制器中處理相同的異常,那麼方式是什麼?複製異常處理是唯一的方法? –

+0

您可以複製處理程序,也可以創建所有其他控制器擴展的abstractController。你也可能能夠創建一個方面itd哪些聲明所有控制器的處理程序,但我承認我沒有嘗試過。 – DavidA

相關問題