Spring Security6 基于角色和权限管理方法

除了之前介绍的内置基础权限控制外。Spring Security 中还支持很多其他权限控制。这些方法一般都用于用户已经被认证成功后(登录成功后),判断用户是否具有特定的权限,如角色、菜单权限等。

hasAuthority(String) 拥有某个权限

判断用户是否具有特定的权限,用户的权限是在自定义登录逻辑中创建User对象时指定的。例如:

package com.hxstrive.spring_security.config;

import com.hxstrive.spring_security.service.UserService;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;

import java.util.List;

/**
 * 自定义实现 UserDetailsService 接口
 * @author hxstrive.com
 */
public class CustomUserDetailsService implements UserDetailsService {
    // 用户服务
    private final UserService userService;

    public CustomUserDetailsService(UserService userService) {
        this.userService = userService;
    }

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        System.out.println("loadUserByUsername(String username) :: " + username);

        // 从数据库中加载用户信息
        com.hxstrive.spring_security.model.UserModel user = userService.getByCount(username);
        if(null == user){
            // 用户名不存在。抛出异常
            throw new UsernameNotFoundException("用户名 [" + username + "] 不存在");
        }

        // 【看这里】
        // 获取用户权限信息,返回一个字符串集合
        List<String> authorities = userService.getUserAuthorities(user.getId());

        // 创建 UserDetails 对象
        return new User(username, user.getPassword(), AuthorityUtils.createAuthorityList(authorities));
    }

}

上述 userService.getUserAuthorities(user.getId()) 代码将根据用户 ID 到数据库获取用户拥有的所有角色和菜单权限。

注意,角色需要在角色名称前面添加“ROLE_”前缀。

示例:

http.authorizeHttpRequests(authorize -> authorize
    // 需要具有 menu:sys:add 权限才能访问 /sys/add 路径的请求
    .requestMatchers("/sys/add").hasAuthority("menu:sys:add")
    // 需要具有 role_admin 角色才能访问 /sys 路径的请求
    // hasAuthority() 也可以使用 hasRole(),二者是等价的
    .requestMatchers("/sys/**").hasAuthority("role_admin")
    .anyRequest().authenticated() // 其他请求需认证
)

上述代码,配置访问 /sys 开头的路径,需要 “admin”角色权限,访问 /sys/add 需要“menu:sys:add”权限。

 

hasAnyAuthority(String ...) 拥有任意权限

用于检查用户是否拥有任意一个指定的权限。它允许你定义多个权限选项,只要用户拥有其中之一即可访问资源。

示例:

http.authorizeHttpRequests(authorize -> authorize
    // 需要具有 menu:sys:add 或 role_admin 权限才能访问 /sys/add 路径的请求
    .requestMatchers("/sys/add").hasAnyAuthority("menu:sys:add", "role_admin")
    .anyRequest().authenticated() // 其他请求需认证
)

 

hasRole(String) 拥有某个角色

如果用户具备给定角色就允许访问,否则出现 403。

参数取值来源于自定义登录逻辑 UserDetailsService 实现类中创建 User 对象时给 User 赋予的授权。

在给用户赋予角色时角色需要以:ROLE_ 开头,后面添加角色名称。例如:ROLE_admin 其中 admin 是角色名,ROLE_ 是固定的字符开头。使用 hasRole() 时参数也只写 admin 即可。

给用户赋予角色:

@Override
public List<String> getUserAuthorities(int userId) {
    final List<String> retList = new ArrayList<>();

    // 用户拥有的角色
    List<RoleModel> roleModelList = roleService.getUserAllRole(userId);
    roleModelList.forEach(roleModel -> retList.add("ROLE_" + roleModel.getCode()));

    // 用户拥有的菜单
    List<MenuModel> menuCodeList = menuService.getUserAllMenu(userId);
    menuCodeList.forEach(menuModel -> retList.add(menuModel.getPermission()));

    return retList;
}

示例:

http.authorizeHttpRequests(authorize -> authorize
    // 需要具有 admin 角色权限才能访问 /sys 路径的请求
    .requestMatchers("/sys/**").hasRole("admin")
    .anyRequest().authenticated() // 其他请求需认证
)

 

hasAnyRole(String ...) 任意角色

用于判断用户是否拥有任意一个指定角色。与 hasAnyAuthority 相比,它会自动为角色名添加 ROLE_ 前缀,使权限配置更简洁。

示例:

http.authorizeHttpRequests(authorize -> authorize
    // 需要具有 admin 或 normal 角色权限才能访问 /user 路径的请求
    .requestMatchers("/user/**").hasAnyRole("admin", "normal")
    // 需要具有 admin 角色权限才能访问 /sys 路径的请求
    .requestMatchers("/sys/**").hasRole("admin")
    .anyRequest().authenticated() // 其他请求需认证
)

注意,上面介绍的四个权限或角色判断方法其底层实际上使用的是 access() 方法,如下图:

Spring Security6 基于角色和权限描述的管理方法

我们将在下一章节详细介绍 access() 方法的使用。

说说我的看法
全部评论(
没有评论
关于
本网站专注于 Java、数据库(MySQL、Oracle)、Linux、软件架构及大数据等多领域技术知识分享。涵盖丰富的原创与精选技术文章,助力技术传播与交流。无论是技术新手渴望入门,还是资深开发者寻求进阶,这里都能为您提供深度见解与实用经验,让复杂编码变得轻松易懂,携手共赴技术提升新高度。如有侵权,请来信告知:hxstrive@outlook.com
其他应用
公众号