程序员scholar 程序员scholar
首页
  • Java 基础

    • JavaSE
    • JavaIO
    • JavaAPI速查
  • Java 高级

    • JUC
    • JVM
    • Java新特性
    • 设计模式
  • Web 开发

    • Servlet
    • Java网络编程
  • Web 标准

    • HTML
    • CSS
    • JavaScript
  • 前端框架

    • Vue2
    • Vue3
    • Vue3 + TS
    • 微信小程序
    • uni-app
  • 工具与库

    • jQuery
    • Ajax
    • Axios
    • Webpack
    • Vuex
    • WebSocket
    • 第三方登录
  • 后端与语言扩展

    • ES6
    • Typescript
    • node.js
  • Element-UI
  • Apache ECharts
  • 数据结构
  • HTTP协议
  • HTTPS协议
  • 计算机网络
  • Linux常用命令
  • Windows常用命令
  • SQL数据库

    • MySQL
    • MySQL速查
  • NoSQL数据库

    • Redis
    • ElasticSearch
  • 数据库

    • MyBatis
    • MyBatis-Plus
  • 消息中间件

    • RabbitMQ
  • 服务器

    • Nginx
  • Spring框架

    • Spring6
    • SpringMVC
    • SpringBoot
    • SpringSecurity
  • SpringCould微服务

    • SpringCloud基础
    • 微服务之DDD架构思想
  • 日常必备

    • 开发常用工具包
    • Hutoll工具包
    • IDEA常用配置
    • 开发笔记
    • 日常记录
    • 项目部署
    • 网站导航
    • 产品学习
    • 英语学习
  • 代码管理

    • Maven
    • Git教程
    • Git小乌龟教程
  • 运维工具

    • Docker
    • Jenkins
    • Kubernetes
  • 算法笔记

    • 算法思想
    • 刷题笔记
  • 面试问题常见

    • 十大经典排序算法
    • 面试常见问题集锦
关于
GitHub (opens new window)
首页
  • Java 基础

    • JavaSE
    • JavaIO
    • JavaAPI速查
  • Java 高级

    • JUC
    • JVM
    • Java新特性
    • 设计模式
  • Web 开发

    • Servlet
    • Java网络编程
  • Web 标准

    • HTML
    • CSS
    • JavaScript
  • 前端框架

    • Vue2
    • Vue3
    • Vue3 + TS
    • 微信小程序
    • uni-app
  • 工具与库

    • jQuery
    • Ajax
    • Axios
    • Webpack
    • Vuex
    • WebSocket
    • 第三方登录
  • 后端与语言扩展

    • ES6
    • Typescript
    • node.js
  • Element-UI
  • Apache ECharts
  • 数据结构
  • HTTP协议
  • HTTPS协议
  • 计算机网络
  • Linux常用命令
  • Windows常用命令
  • SQL数据库

    • MySQL
    • MySQL速查
  • NoSQL数据库

    • Redis
    • ElasticSearch
  • 数据库

    • MyBatis
    • MyBatis-Plus
  • 消息中间件

    • RabbitMQ
  • 服务器

    • Nginx
  • Spring框架

    • Spring6
    • SpringMVC
    • SpringBoot
    • SpringSecurity
  • SpringCould微服务

    • SpringCloud基础
    • 微服务之DDD架构思想
  • 日常必备

    • 开发常用工具包
    • Hutoll工具包
    • IDEA常用配置
    • 开发笔记
    • 日常记录
    • 项目部署
    • 网站导航
    • 产品学习
    • 英语学习
  • 代码管理

    • Maven
    • Git教程
    • Git小乌龟教程
  • 运维工具

    • Docker
    • Jenkins
    • Kubernetes
  • 算法笔记

    • 算法思想
    • 刷题笔记
  • 面试问题常见

    • 十大经典排序算法
    • 面试常见问题集锦
关于
GitHub (opens new window)
npm

(进入注册为作者充电)

  • SpringSecurity

    • Spring Security是什么
    • 认证与授权的基本概念
    • Spring Security 的默认配置
    • SpringSecurity的默认登录页
    • Spring Security 的 Filter 机制
    • HttpSecurity 与自定义登录页面
    • Spring Security 的核心组件与扩展
    • Spring Security 中的用户认证与角色管理
      • 1. 用户认证配置
        • 1.1 内存中的用户配置
        • 1.2 数据库中的用户配置
      • 2. 角色管理与路径权限控制
        • 2.1 基于路径的角色控制
        • 2.2 基于方法的权限控制
    • Spring Security 的授权机制与安全表达式
    • Security 的 Session 与 Token 管理
    • Spring Security 集成第三方登录
    • Spring Security 集成 QQ 登录与 JWT 认证
    • Spring Security 登录认证源码
    • Spring Security - JWT认证实战
    • Spring Security - JWT授权实战
    • Spring Security 异常处理与自定义逻辑
  • SpringSecurity
  • SpringSecurity
scholar
2024-08-20
目录

Spring Security 中的用户认证与角色管理

# Spring Security 中的用户认证与角色管理

前言

Spring Security 提供了一套全面的用户认证与角色管理机制,允许开发者灵活地配置用户、角色,并通过路径或方法进行权限控制。本节将详细介绍如何在 Spring Security 中配置用户、角色,并对路径或方法进行权限控制。

# 1. 用户认证配置

用户认证是 Spring Security 的核心部分,可以通过多种数据源(如内存、数据库、自定义认证源)进行配置。

# 1.1 内存中的用户配置

在小型项目或快速测试时,可以使用内存中的用户信息进行认证配置。这种方式适合开发阶段的调试和概念验证。

代码示例:

import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

@Configuration
@EnableWebSecurity  // 启用 Spring Security
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication()  // 配置内存中的用户信息
            .withUser("admin")  // 定义用户名为 "admin"
            .password("{noop}admin123")  // 定义密码为 "admin123"。{noop} 表示不进行加密
            .roles("ADMIN")  // 分配角色 "ADMIN"
            .and()
            .withUser("user")  // 定义另一个用户 "user"
            .password("{noop}user123")  // 定义密码为 "user123"
            .roles("USER");  // 分配角色 "USER"
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

重要参数说明:

  • inMemoryAuthentication():用于配置内存中的用户信息。适用于快速开发或测试场景。
  • password("{noop}password"):{noop} 是一个密码编码器标识符,表示不进行加密。在实际生产环境中应使用如 BCryptPasswordEncoder 来加密密码。
  • roles("ROLE_NAME"):为用户分配角色。Spring Security 默认会在角色前添加 ROLE_ 前缀,如 roles("ADMIN") 实际上匹配 ROLE_ADMIN。

使用场景: 内存中的用户配置适用于开发阶段、概念验证或需要快速测试用户认证的情况。

# 1.2 数据库中的用户配置

在实际项目中,用户信息通常存储在数据库中。为了从数据库中加载用户信息,你需要实现 UserDetailsService 接口。

代码示例:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

@Service
public class MyUserDetailsService implements UserDetailsService {

    @Autowired
    private UserRepository userRepository;  // 用户数据源,通常连接数据库

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        // 从数据库加载用户信息
        User user = userRepository.findByUsername(username);
        if (user == null) {
            throw new UsernameNotFoundException("用户未找到");
        }
        // 将用户信息转换为 Spring Security 的 UserDetails 对象
        return new org.springframework.security.core.userdetails.User(user.getUsername(), user.getPassword(), getAuthorities(user));
    }

    private Collection<? extends GrantedAuthority> getAuthorities(User user) {
        // 将用户的角色信息转换为 GrantedAuthority 对象
        return user.getRoles().stream()  // 假设 User 中有一个 roles 字段,存储用户的角色集合
                   .map(role -> new SimpleGrantedAuthority("ROLE_" + role.getName()))  // 为每个角色添加 "ROLE_" 前缀,并封装为 SimpleGrantedAuthority 对象
                   .collect(Collectors.toList());  // 将结果收集为一个 List
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

关键点说明:new org.springframework.security.core.userdetails.User(...)

  • 这是 Spring Security 提供的一个 UserDetails 实现类,用于构建用户的认证信息对象。
  • 构造方法的参数分别为:用户名、密码、权限集合(GrantedAuthority 列表)。
  • 你需要将从数据库中查询到的用户信息(如用户名、密码)传递给这个构造方法。

注意事项

SimpleGrantedAuthority 是 Spring Security 提供的一个实现 GrantedAuthority 接口的类,用于表示用户的权限(如角色)。Spring Security 中默认会为角色添加 ROLE_ 前缀,所以我们在这里手动添加该前缀,以确保角色匹配。

配置 UserDetailsService:

import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private MyUserDetailsService myUserDetailsService;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(myUserDetailsService)  // 使用自定义的 UserDetailsService 进行用户认证
            .passwordEncoder(new BCryptPasswordEncoder());  // 使用 BCrypt 进行密码加密
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

重要参数说明:

  • UserDetailsService:Spring Security 提供的接口,用于从任意数据源(如数据库)加载用户信息。
  • BCryptPasswordEncoder:常用的密码编码器,提供安全的密码加密,适合生产环境。

使用场景: 适用于实际生产环境中的用户管理系统,其中用户数据存储在数据库中,并需要安全的密码加密。

# 2. 角色管理与路径权限控制

Spring Security 提供了强大的角色管理与权限控制功能,可以基于路径或方法对访问进行控制。

# 2.1 基于路径的角色控制

在路径权限控制中,Spring Security 允许你通过 HttpSecurity 进行路径与角色的绑定,实现精细化的访问控制。

代码示例:

import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()  // 配置路径访问权限
                .antMatchers("/admin/**").hasRole("ADMIN")  // 只有 ADMIN 角色的用户可以访问 /admin/**
                .antMatchers("/user/**").hasAnyRole("USER", "ADMIN")  // USER 和 ADMIN 角色的用户可以访问 /user/**
                .antMatchers("/", "/home", "/public/**").permitAll()  // 公开访问路径,无需认证
                .anyRequest().authenticated()  // 其他所有路径都需要认证
            .and()
            .formLogin()  // 启用表单登录
                .loginPage("/login")  // 自定义登录页面路径
                .permitAll()  // 允许所有用户访问登录页面
            .and()
            .logout()  // 启用注销功能
                .permitAll();  // 允许所有用户访问注销路径
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

重要参数说明:

  • antMatchers(String... paths):匹配指定路径并配置访问规则。支持通配符,如 /admin/** 匹配所有以 /admin/ 开头的路径。
  • hasRole(String role):指定访问该路径需要的角色。默认情况下,Spring Security 会为角色添加 ROLE_ 前缀。
  • hasAnyRole(String... roles):指定多个角色中任意一个角色即可访问该路径。
  • permitAll():允许所有用户(包括未认证用户)访问。

使用场景: 基于路径的角色控制适用于需要根据用户角色进行页面或资源访问控制的场景,如管理员页面、用户专属页面等。

# 2.2 基于方法的权限控制

除了路径权限控制,Spring Security 还支持方法级别的权限控制。你可以通过注解对服务方法或控制器方法进行权限限制。

代码示例:

import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Service;

@Service
public class MyService {

    @PreAuthorize("hasRole('ADMIN')")  // 只有 ADMIN 角色的用户可以访问此方法
    public void adminOnlyMethod() {
        // 只有管理员可以执行的业务逻辑
    }

    @PreAuthorize("hasAnyRole('USER', 'ADMIN')")  // USER 和 ADMIN 角色的用户都可以访问
    public void userAndAdminMethod() {
        // 用户和管理员都可以执行的业务逻辑
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

启用方法级权限控制:

import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;

@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)  // 启用方法级权限控制
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    // 其他配置
}
1
2
3
4
5
6
7

重要参数说明:

  • @PreAuthorize:在方法执行前进行权限检查,支持使用 SpEL 表达式进行更复杂的权限判断。
  • @Secured:Spring Security 提供的另一种注解,用于指定允许访问该方法的角色。
  • @PostAuthorize:在方法执行后进行权限检查,适用于返回结果后进行权限过滤的场景。

使用场景: 基于方法的权限控制适用于需要对业务逻辑进行更细粒度的权限控制的场景,例如只有特定角色的用户才能执行某些关键操作。

总结

Spring Security 提供了灵活的用户认证和角色管理功能。通过 HttpSecurity 配置路径权限控制,结合方法级别的注解如 @PreAuthorize,你可以实现基于角色的精细化访问控制。无论是简单的内存用户配置还是复杂的数据库用户管理,Spring Security 都能满足不同项目的需求。

编辑此页 (opens new window)
上次更新: 2024/12/28, 18:32:08
Spring Security 的核心组件与扩展
Spring Security 的授权机制与安全表达式

← Spring Security 的核心组件与扩展 Spring Security 的授权机制与安全表达式→

Theme by Vdoing | Copyright © 2019-2025 程序员scholar
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式