SpringBoot 整合 Spring Security 实现权限控制

一、权限控制核心概念

在企业级项目中,认证授权是安全模块的核心:

  • 认证:验证用户身份,确认 "你是谁",如用户名密码登录、短信验证码登录。
  • 授权:用户认证通过后,分配可访问的资源 / 操作权限,确认 "你能做什么"。

主流 Java 权限框架:Spring Security (Spring 生态原生,功能强大)、Apache Shiro(轻量易用),本文基于 Spring Security 实现权限控制。

二、权限模块数据模型

权限控制依赖 7 张核心数据表,角色表为核心枢纽,用户、权限、菜单均与角色多对多关联:

  1. 用户表t_user:存储用户账号、密码等信息
  2. 角色表t_role:定义角色(如管理员、普通用户)
  3. 权限表t_permission:定义具体操作权限(如新增、删除、查询)
  4. 菜单表t_menu:定义前端可展示菜单
  5. 用户角色关系表t_user_role:用户与角色多对多关联
  6. 角色权限关系表t_role_permission:角色与权限多对多关联
  7. 角色菜单关系表t_role_menu:角色与菜单多对多关联

三、Spring Security 入门搭建

1. 引入 Maven 依赖

XML 复制代码
<!-- Spring Security启动器 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>
<!-- Web依赖 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

2. 核心过滤器链

Spring Boot 启动时自动加载springSecurityFilterChainFilterChainProxy),包含 15 个核心过滤器,关键过滤器作用:

  • UsernamePasswordAuthenticationFilter:处理用户名密码登录认证
  • FilterSecurityInterceptor:权限校验核心过滤器
  • CsrfFilter:防跨站请求伪造
  • LogoutFilter:处理用户退出登录

四、Spring Security 核心配置

1. 自定义安全配置类

继承WebSecurityConfigurerAdapter,实现匿名资源放行、自定义登录页、认证来源、权限规则配置:

java 复制代码
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
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.builders.WebSecurity;
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;
import org.springframework.security.crypto.password.PasswordEncoder;

/**
 * Spring Security核心配置类
 */
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private UserService userService;

    /**
     * 配置静态资源匿名放行
     */
    @Override
    public void configure(WebSecurity web) throws Exception {
        // 放行登录页、静态资源、验证码接口
        web.ignoring().antMatchers("/login.html", "/pages/**", "/validateCode/send4Login.do");
    }

    /**
     * 配置认证来源(关联自定义UserService)
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userService).passwordEncoder(passwordEncoder());
    }

    /**
     * 配置HTTP请求安全(登录、授权、退出)
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // 自定义表单登录
        http.formLogin()
                .loginPage("/login.html") // 自定义登录页
                .loginProcessingUrl("/login") // 登录请求接口
                .usernameParameter("username") // 用户名参数
                .passwordParameter("password") // 密码参数
                .defaultSuccessUrl("/index.html"); // 登录成功跳转页

        // 权限配置
        http.authorizeRequests()
                .antMatchers("/pages/b.html").hasAuthority("add") // 需add权限
                .antMatchers("/pages/c.html").hasRole("ADMIN") // 需ADMIN角色
                .anyRequest().authenticated(); // 其余资源需登录

        // 退出登录配置
        http.logout()
                .logoutUrl("/logout") // 退出接口
                .logoutSuccessUrl("/login.html"); // 退出成功跳转页

        // 关闭CSRF防护(前后端分离可关闭)
        http.csrf().disable();
    }

    /**
     * 密码加密器(BCrypt加密)
     */
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
}

五、数据库认证与密码加密

1. 自定义 UserDetailsService

实现UserDetailsService接口,重写loadUserByUsername方法,从数据库查询用户信息:

java 复制代码
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
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 org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

@Component
public class UserService implements UserDetailsService {

    // 模拟数据库用户数据
    private static Map<String, UserInfo> userMap = new HashMap<>();

    @Autowired
    private BCryptPasswordEncoder passwordEncoder;

    // 初始化加密用户数据
    static {
        userMap.put("admin", new UserInfo("admin", new BCryptPasswordEncoder().encode("admin")));
        userMap.put("user", new UserInfo("user", new BCryptPasswordEncoder().encode("123456")));
    }

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        // 从数据库查询用户
        UserInfo userInfo = userMap.get(username);
        if (userInfo == null) {
            throw new UsernameNotFoundException("用户名不存在");
        }

        // 封装权限/角色
        ArrayList<GrantedAuthority> authorities = new ArrayList<>();
        if ("admin".equals(username)) {
            authorities.add(new SimpleGrantedAuthority("add"));
            authorities.add(new SimpleGrantedAuthority("ROLE_ADMIN"));
        }

        // 返回Spring Security规范用户对象
        return new User(userInfo.getUsername(), userInfo.getPassword(), authorities);
    }
}

// 用户实体类
class UserInfo {
    private String username;
    private String password;

    public UserInfo(String username, String password) {
        this.username = username;
        this.password = password;
    }

    // getter/setter
}

2. BCrypt 密码加密

  • 加密:passwordEncoder.encode("明文密码")
  • 匹配:passwordEncoder.matches("明文密码", "加密后密码")
  • 特点:同一密码每次加密结果不同,自带随机盐,安全系数高

六、两种权限控制方式

方式 1:配置类权限控制

HttpSecurity中直接配置 URL 权限规则:

java 复制代码
http.authorizeRequests()
        .antMatchers("/pages/b.html").hasAuthority("add") // 需add权限
        .antMatchers("/pages/c.html").hasRole("ADMIN") // 需ADMIN角色
        .anyRequest().authenticated();

方式 2:注解式权限控制

1. 开启注解支持
java 复制代码
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true) // 开启权限注解
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
}
2. 接口添加权限注解
java 复制代码
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/permission")
public class PermissionController {

    // 需add权限才可访问
    @RequestMapping("/add")
    @PreAuthorize("hasAuthority('add')")
    public String add() {
        return "新增权限验证通过";
    }

    // 需ADMIN角色才可访问
    @RequestMapping("/delete")
    @PreAuthorize("hasRole('ADMIN')")
    public String delete() {
        return "删除权限验证通过";
    }
}

七、用户退出登录

配置退出接口,请求/logout即可自动清除认证信息,跳转至登录页:

java 复制代码
http.logout()
        .logoutUrl("/logout") // 退出请求路径
        .logoutSuccessUrl("/login.html"); // 退出成功跳转页

八、总结

  1. Spring Security 通过过滤器链实现认证与授权,配置灵活、功能全面。
  2. 核心配置:匿名资源放行、自定义登录页、数据库认证、BCrypt 加密
  3. 权限控制支持配置类注解两种方式,适配不同业务场景。
  4. 生产环境务必使用密码加密 、开启CSRF 防护、精细化权限配置。

需要我帮你补充Spring Security 整合 MyBatis 从数据库查询真实权限的代码吗?

相关推荐
垚垚学技术_聚焦云原生12 小时前
K8s Pod 完整生命周期详解
后端
JavaGuide12 小时前
Github 史诗级故障,与此同时,Cursor 版「GitHub」正式上线!
前端·后端
不一样的少年_12 小时前
修了 Bug、做了重构,为什么老板还是觉得你没产出?
前端·后端·程序员
水深火乐12 小时前
安全地生成验证码、密码和 Token
后端
小强198813 小时前
SQL Server 慢查询怎么定位?一套从“卡”到“快”的完整排查流程
后端
水深火乐13 小时前
interface和any
后端
步行cgn13 小时前
MyBatis Error evaluating expression ‘ids‘. Return value (3) was not iterable 错误详
java·后端
神奇小汤圆13 小时前
Spring Boot + LangChain4j实现RAG——从零搭建企业级知识库问答系统
后端
H_Peak13 小时前
Python运算符与流程控制:if条件判断
后端
H_Peak13 小时前
Python字符串操作:从基础到正则入门
后端