Sping Boot 和Spring Security:混合角色和权限进行访问控制的问题

ijnw1ujt  于 2023-04-21  发布在  Spring
关注(0)|答案(1)|浏览(174)

我使用的是Sping Boot 2.7.2,并为我的用户设置了角色和权限的安全配置。但是,在访问控制表达式中混合角色和权限时遇到了问题。
以下是我的配置:

@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
    return http
            .httpBasic()
            .and()
            .authorizeRequests()
            .anyRequest().access("isAuthenticated() and hasAuthority('read')")
            .and()
            .build();
}

@Bean
public UserDetailsService userDetailsService(){
    InMemoryUserDetailsManager udm = new InMemoryUserDetailsManager();
    UserDetails ud = User.withUsername("bill")
            .password(passwordEncoder().encode("password"))
            .authorities("read")
            .roles("MANAGER")
            .build();

    UserDetails ud1 = User.withUsername("john")
            .password(passwordEncoder().encode("password"))
            .authorities("write")
            .roles("ADMIN")
            .build();

    udm.createUser(ud);
    udm.createUser(ud1);

    return udm;
}

使用此配置,当尝试访问端点时,两个用户都被拒绝。但是,如果我删除角色并在创建用户时仅使用权限,则可以正常工作:Bill可以访问端点,而John不能。
使用此配置,它将按预期工作:

@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
    return http
            .httpBasic()
            .and()
            .authorizeRequests()
            .anyRequest().access("isAuthenticated() and hasAuthority('read')")
            .and()
            .build();
}

@Bean
public UserDetailsService userDetailsService(){
    InMemoryUserDetailsManager udm = new InMemoryUserDetailsManager();
    UserDetails ud = User.withUsername("bill")
            .password(passwordEncoder().encode("password"))
            .authorities("read")
            .build();

    UserDetails ud1 = User.withUsername("john")
            .password(passwordEncoder().encode("password"))
            .authorities("write")
            .build();

    udm.createUser(ud);
    udm.createUser(ud1);

    return udm;
}

我想了解为什么在混合使用角色和权限时会出现此问题,以及如何在配置中同时使用角色和权限。如有任何帮助或建议,我将不胜感激。

neekobn8

neekobn81#

问题是User的构造。

UserDetails ud = User.withUsername("bill")
            .password(passwordEncoder().encode("password"))
            .authorities("read")
            .roles("MANAGER")
            .build();

如果你已经检查了User的代码,或者更确切地说,UserBuilder和相应的authoritiesroles方法,你会看到每个方法都取代了完整的权限。所以你可以使用其中一个。
如果你看得更仔细,你会发现authoritiesroles实际上都是authorities。唯一的区别是roles的前缀是ROLE_
因此,在初始设置中,您最终只有一个名为ROLE_MANAGER/ROLE_ADMIN的权限,而不是您的read权限。
不需要同时调用这两个方法,只需同时调用readROLE_MANAGER

UserDetails ud = User.withUsername("bill")
            .password(passwordEncoder().encode("password"))
            .authorities("read", "ROLE_MANAGER")
            .build();

相关问题