首页 > 解决方案 > 使用 Spring Security 按角色限制 api 功能

问题描述

我正在尝试在我的项目中实现 SpringSecurity 机制。我有两个角色:成员和管理员。MEMBER 和 ADMIN 都可以访问 api 更新用户,例如。MEMBER只能改名字,头像,ADMIN什么都可以改。我如何应用 SpringSecurity 概念来做到这一点?

标签: javaspring-bootspring-security

解决方案


您首先需要为每个角色提供两个不同的用户。例如,以下将提供用户的内存表示member,并且admin每个都有密码password

@Bean
static InMemoryUserDetailsManager userDetailsManager() {
    UserDetails user = User.withDefaultPasswordEncoder()
        .username("member")
            .password("password")
            .roles("MEMBER")
            .build();
    UserDetails admin = User.withDefaultPasswordEncoder()
            .username("admin")
            .password("password")
            .roles("ADMIN")
            .build();
    return new InMemoryUserDetailsManager(user);
}

现在您可以设置授权规则。对于您希望任一角色起作用hasAnyRole(...)的 URL,您可以使用,对于您只想与您可以使用的管理员一起使用的 URL hasRole(...)。例如,以下内容将允许任一用户使用 URL /user/name,或者/user/avatar管理员可以使用任何以 . 开头的 URL /user/**。所有其他 URL 均被拒绝。

@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
                .mvcMatchers("/user/name", "/user/avatar").hasAnyRole("MEMBER", "ADMIN")
                .mvcMatchers("/user/**").hasRole("ADMIN")
                .anyRequest().denyAll()
                .and()
            .formLogin();
    }
}

需要注意的是,只有第一条规则将用于授权。因此,当/user/name匹配规则/user/name时,将/user/**' (starts with 使用 /user/ ), and anyRequest() only the first rule ofhasAnyRole("MEMBER", "ADMIN")`。

您还可以设置利用 HTTP 方法的规则。例如,以下将允许MEMBERADMIN用于 HTTP GET on/user/address

.mvcMatchers(HttpMethod.GET, "/user/address").hasAnyRole("MEMBER", "ADMIN")

另一种方法是为您的用户分配多个角色。例如,管理员用户可能具有角色MEMBERADMIN.

@Bean
static InMemoryUserDetailsManager userDetailsManager() {
    UserDetails user = User.withDefaultPasswordEncoder()
        .username("member")
            .password("password")
            .roles("MEMBER")
            .build();
    UserDetails admin = User.withDefaultPasswordEncoder()
            .username("admin")
            .password("password")
            .roles("ADMIN", "MEMBER")
            .build();
    return new InMemoryUserDetailsManager(user);
}

然后,您的规则可以简化为对 URL 具有单一角色。

@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
                .mvcMatchers("/user/name", "/user/avatar").hasRole("MEMBER")
                .mvcMatchers("/user/**").hasRole("ADMIN")
                .anyRequest().denyAll()
                .and()
            .formLogin();
    }
}

当您需要考虑很多角色时,这种方法可能更可取。每个操作都是一个角色,但用户可能拥有多个角色。


推荐阅读