spring-security Springboot安全性角色不起作用

7d7tgy0s  于 2022-11-11  发布在  Spring
关注(0)|答案(3)|浏览(172)

我无法在@PreAuthorize注解中使用hasRole方法。而且request.isUserInRole(“ADMIN”)给出了false。我遗漏了什么?尽管.hasAuthority(“ADMIN”)工作正常。
我正在从数据库中为用户分配权限。

fsi0uk1n

fsi0uk1n1#

您必须使用前缀ROLE_命名您的授权才能使用isUserInRole,请参见Spring安全参考:
HttpServletRequest.isUserInRole(字符串)将确定SecurityContextHolder.getContext().getAuthentication().getAuthorities()是否包含GrantedAuthority以及传入isUserInRole(String)的角色。通常,用户不应将“ROLE_”前缀传入此方法,因为它是自动添加的。例如,如果要确定当前用户是否具有“ROLE_ADMIN”权限,可以使用以下命令:

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

对于hasRole(也是hasAnyRole)也是如此,请参见Spring安全参考:
如果当前主体具有指定的角色,则返回true。默认情况下,如果提供的角色不是以“ROLE_”开头,则将添加该角色。这可以通过修改DefaultWebSecurityExpressionHandler上的defaultRolePrefix进行自定义。
另请参阅Spring Security Reference

46.3.3“ROLE_”是什么意思?为什么我的角色名称上需要它?

Spring Security具有基于投票器的体系结构,这意味着访问决策是由一系列AccessDecisionVoters做出的。(例如方法调用)。使用这种方法,并非所有属性都与所有表决器相关,表决器需要知道何时应忽略属性最常见的投票器是RoleVoter,它在默认情况下会在找到前缀为“ROLE_”的属性时进行投票。它会对属性进行简单的比较(例如“ROLE_USER”)与当前用户已分配的权限的名称匹配。如果找到匹配项(他们具有名为“ROLE_USER”的权限),则投票授予访问权限,否则投票拒绝访问权限。

iqih9akk

iqih9akk2#

我不得不即兴发挥了一下,也许有其他的方法比我的更简单,但在我工作的时候,我没有其他选择,只能即兴发挥了一点,经过彻底的研究得出了这个解决方案. 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。

swvgeqrz

swvgeqrz3#

您可以使用hasRole()hasAuthority()。不同之处在于,您必须使用ROLE_来执行hasAusthority()方法。
所以对于ROLE_ADMIN

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

相关问题