繁体   English   中英

春季安全访问被拒绝异常

[英]spring-security access denied exception

我在使用@secured of spring-security注释的方法时遇到问题

@Secured(value = { "LIST_GIFT" })

该方法已放置在spring-mvc Web应用程序的Controller方法上。

当我通过UserDetailsS​​ervice实现进行调试时,我们在loadByUserName方法的末尾有以下UserDetails对象:

SecurityDetails [userId=106, username=john@doe.com, enabled=true, accountNonLocked=true, accountNonExpired=true, credentialsNonExpired=true]

具有以下授予的权限列表:

[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禁止。 当我打开日志记录时,我看到以下内容:

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.springframework.security.authentication.UsernamePasswordAuthenticationToken@380cef3f: Principal: SecurityDetails [userId=106, username=john@doe.com, enabled=true, accountNonLocked=true, accountNonExpired=true, credentialsNonExpired=true]; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@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: org.springframework.security.access.vote.RoleVoter@2059dcd9, returned: 0
    DEBUG: org.springframework.security.access.vote.AffirmativeBased - Voter: org.springframework.security.access.vote.AuthenticatedVoter@6bb23b26, 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>)

我已经不知道为什么会发生这种情况了。

您似乎没有投票赞成授予访问权限的AccessDecisionVoter (它们都弃权),因此您被拒绝访问。

原因是,默认情况下,作为默认配置一部分的RoleVoter将仅响应以前缀“ ROLE_”开头的权限。 既然您都没有,它找不到任何已知的信息。 此常见问题解答具有更多信息

一种替代方法是启用基于表达式的安全性,而改用@PreAuthorize批注 ,这更加灵活。 就像是

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

如果您按照说明启用了注释,则应该可以立即使用。

问题在于,当您在会话中加载User 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
{

}

因此,您可以以此来注释所有功能,并且如果对访问礼品元素的策略进行了更改,则只需更改一次即可。 它更好,更容易处理。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM