【问题标题】:Springboot Security hasRole not workingSpring Boot Security hasRole 不起作用
【发布时间】:2017-06-16 05:37:00
【问题描述】:

我无法在 @PreAuthorize 注释中使用 hasRole 方法。 request.isUserInRole(“ADMIN”) 也提供 false。我错过了什么? 虽然.hasAuthority(“ADMIN”) 工作正常。

我正在为数据库中的用户分配权限。

【问题讨论】:

    标签: spring-boot spring-security


    【解决方案1】:

    您必须使用前缀ROLE_ 命名您的权限才能使用isUserInRole,请参阅Spring Security Reference

    HttpServletRequest.isUserInRole(String) 将确定SecurityContextHolder.getContext().getAuthentication().getAuthorities() 是否包含GrantedAuthority,并将角色传递给isUserInRole(String)。通常,用户不应将“ROLE_”前缀传递给此方法,因为它是自动添加的。例如,如果要确定当前用户是否具有“ROLE_ADMIN”权限,可以使用以下命令:

    boolean isAdmin = httpServletRequest.isUserInRole("ADMIN");
    

    hasRole(也称为hasAnyRole)相同,参见Spring Security Reference

    如果当前主体具有指定角色,则返回 true。默认情况下,如果提供的角色不以“ROLE_”开头,它将被添加。这可以通过修改DefaultWebSecurityExpressionHandler上的defaultRolePrefix来定制。

    【讨论】:

    • 非常感谢。我为此浪费了几个小时。但是 PreAuthorize 在我的控制器中仍然不起作用。它不应该在控制器层工作而只在服务层工作吗?
    • 这个问题也解决了,在安全配置中使用@EnableGlobalMethodSecurity(prePostEnabled = true)。
    【解决方案2】:

    我不得不即兴发挥一点,也许还有其他比我更简单的方法,但在我研究这个的时候,我别无选择,只能即兴发挥一点,经过彻底的研究提出了这个解决方案。 Spring Security 有一个名为AccessDecisionManager 的接口,您需要实现它。

    @Component
    public class RolesAccessDecisionManager implements AccessDecisionManager {
        private final static String AUTHENTICATED = "authenticated";
        private final static String PERMIT_ALL = "permitAll";
    
        @Override
        public void decide(Authentication authentication, Object o, Collection<ConfigAttribute> collection) throws AccessDeniedException, InsufficientAuthenticationException {
            collection.forEach(configAttribute -> {
                if (!this.supports(configAttribute))
                    throw new AccessDeniedException("ACCESS DENIED");
            });
        }
    
        @Override
        public boolean supports(ConfigAttribute configAttribute) {
            Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
            if (authentication != null && authentication.isAuthenticated()) {
                String rolesAsString = authentication.getAuthorities().stream().map(GrantedAuthority::getAuthority).collect(Collectors.joining(","));
                if (configAttribute.toString().contains(rolesAsString))
                    return true;
                else
                    return (configAttribute.toString().contains(PERMIT_ALL) || configAttribute.toString().contains(AUTHENTICATED));
            }
            return true;
        }
    
        @Override
        public boolean supports(Class<?> aClass) {
            return true;
        }
    }
    

    现在要使用您的安全配置支持此自定义访问决策管理器,请在安全配置中执行以下操作:

    @Override
            protected void configure(HttpSecurity http) throws Exception {
                http.csrf().disable()
    // other configs
        .accessDecisionManager(this.accessDecisionManager)
    

    accessDecisionManager 是您创建的 AccessDecisionManager 实现的自动装配 bean。

    【讨论】:

      【解决方案3】:

      您可以使用hasRole()hasAuthority()。不同之处在于,您必须使用ROLE_ 才能使用hasAusthority() 方法。

      所以对于ROLE_ADMIN

       @PreAuthorize("hasRole('ADMIN')") == @PreAuthorize("hasAuthority('ROLE_ADMIN')")
      

      【讨论】:

        猜你喜欢
        • 2015-08-27
        • 2015-12-09
        • 2020-07-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-07-10
        相关资源
        最近更新 更多