2014-03-26 58 views
2

與彈簧安全彈簧安全訪問被拒絕,我有一個問題例外

@Secured(value = { "LIST_GIFT" }) 

的@Secured註釋的方法,該方法已被放置在一個彈簧MVC Web應用程序的控制方法。

當我通過我們在loadByUserName方法結束時的UserDetailsS​​ervice實現調試,我有以下UserDetails對象:

SecurityDetails [userId=106, [email protected], enabled=true, accountNonLocked=true, accountNonExpired=true, credentialsNonExpired=true] 

用下面授予authoroties列表:

[LOCK_SERIAL, CALCULATE_BALANCE, REGISTER_FOR_PUSH_NOTIFICATION, TOPUP_BY_POS, LIST_PRODUCTS, LIST_COUPON_ASSIGNMENT, BALANCE, BALANCE_HISTORY, LIST_GIFT, LIST_PROGRAMS, ASSIGN_COUPON, DISTRIBUTE_COUPON, CAN_CONFIGURE_GIFTS] 

的HTTP總是返回403 Forbidden。當我打開日誌記錄,我看到以下內容:

DEBUG: org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor - Secure object: ReflectiveMethodInvocation: public com.foo.products.sva.cc.customer.domain.AccountBalance com.foo.products.sva.cc.customer.controllers.AccountController.getBalance(java.lang.String); target is of class [com.foo.products.sva.cc.customer.controllers.AccountController]; Attributes: [LIST_GIFT] 
    DEBUG: org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor - Previously Authenticated: org.springframew[email protected]380cef3f: Principal: SecurityDetails [userId=106, [email protected], enabled=true, accountNonLocked=true, accountNonExpired=true, credentialsNonExpired=true]; Credentials: [PROTECTED]; Authenticated: true; Details: org.sprin[email protected]fffed504: RemoteIpAddress: 127.0.0.1; SessionId: F5EAAB76CD6CC8530F3E7E844A13D635; Granted Authorities: CALCULATE_BALANCE, REGISTER_FOR_PUSH_NOTIFICATION, TOPUP_BY_POS, CAN_CONFIGURE_GIFTS, DISTRIBUTE_COUPON, ASSIGN_COUPON, LIST_COUPON_ASSIGNMENT, LIST_GIFT, BALANCE_HISTORY, LIST_PRODUCTS, LOCK_SERIAL, LIST_PROGRAMS, BALANCE 
    DEBUG: org.springframework.security.access.vote.AffirmativeBased - Voter: [email protected], returned: 0 
    DEBUG: org.springframework.security.access.vote.AffirmativeBased - Voter: [email protected]3b26, returned: 0 
    DEBUG: org.springframework.security.web.access.ExceptionTranslationFilter - Access is denied (user is not anonymous); delegating to AccessDeniedHandler 
    org.springframework.security.access.AccessDeniedException: Access is denied 
      at org.springframework.security.access.vote.AbstractAccessDecisionManager.checkAllowIfAllAbstainDecisions(AbstractAccessDecisionManager.java:70) 
      at org.springframework.security.access.vote.AffirmativeBased.decide(AffirmativeBased.java:88) 
      at org.springframework.security.access.intercept.AbstractSecurityInterceptor.beforeInvocation(AbstractSecurityInterceptor.java:205) 
      at org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor.invoke(MethodSecurityInterceptor.java:59) 
      at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) 
      at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:110) 
      at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) 
      at org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept(Cglib2AopProxy.java:622) 
      at com.foo.products.sva.cc.customer.controllers.AccountController$$EnhancerByCGLIB$$b72ae4b0.getBalance(<generated>) 

我不知道爲什麼會發生這種情況。

回答

2

它看起來好像沒有一個AccessDecisionVoter您投票授予訪問權限(他們都棄權),因此您被拒絕訪問。

原因是,默認情況下,作爲默認配置一部分的RoleVoter只會響應以「ROLE_」前綴開頭的權限。由於你們都不這樣做,所以它沒有發現任何它知道的事情。 This FAQ has some more information

另一種方法是啓用基於表達式的安全性並使用@PreAuthorize annotation代替,這更靈活。類似於

@PreAuthorize("hasRole('LIST_GIFT')") 

如果按照說明啓用註釋,應該可以開箱即用。

2

問題是,當您在會話中加載用戶GrantedAuthority元素時,應根據用戶配置文件的差異權限以不同方式命名它們。

  • ROLE前綴爲用戶配置文件
  • PERM前綴的用戶權限

所以,你應該爲您的許可,爲PERM_LIST_GIFT和使用hasAuthority註解來替代。我也建議將該許可作爲CRUD;所以爲了列出禮物,您將有權讀取禮物:PERM_READ_GIFT。爲了改善這種訪問,您可以創建一個自定義註釋來指示某人有權訪問(至少只讀)您的禮品對象。喜歡的東西:

/** 
* Grants permissions of accessing to Gifts module 
* 
*/ 
@Target(
     { 
      ElementType.TYPE, ElementType.METHOD 
     }) 
@Component 
@Retention(RetentionPolicy.RUNTIME) 
@Inherited 
@Documented 
@PreAuthorize("hasAuthority('PERM_READ_GIFT')") 
public @interface GiftsAuthorized 
{ 

} 

所以,你可以註釋的所有功能與此,如果政策變化來訪問你的禮物元素,你將只需要更改一次。它更好,更容易處理。