一、权限控制核心概念
在企业级项目中,认证 与授权是安全模块的核心:
- 认证:验证用户身份,确认 "你是谁",如用户名密码登录、短信验证码登录。
- 授权:用户认证通过后,分配可访问的资源 / 操作权限,确认 "你能做什么"。
主流 Java 权限框架:Spring Security (Spring 生态原生,功能强大)、Apache Shiro(轻量易用),本文基于 Spring Security 实现权限控制。
二、权限模块数据模型
权限控制依赖 7 张核心数据表,角色表为核心枢纽,用户、权限、菜单均与角色多对多关联:
- 用户表
t_user:存储用户账号、密码等信息 - 角色表
t_role:定义角色(如管理员、普通用户) - 权限表
t_permission:定义具体操作权限(如新增、删除、查询) - 菜单表
t_menu:定义前端可展示菜单 - 用户角色关系表
t_user_role:用户与角色多对多关联 - 角色权限关系表
t_role_permission:角色与权限多对多关联 - 角色菜单关系表
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 启动时自动加载springSecurityFilterChain(FilterChainProxy),包含 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"); // 退出成功跳转页
八、总结
- Spring Security 通过过滤器链实现认证与授权,配置灵活、功能全面。
- 核心配置:匿名资源放行、自定义登录页、数据库认证、BCrypt 加密。
- 权限控制支持配置类 和注解两种方式,适配不同业务场景。
- 生产环境务必使用密码加密 、开启CSRF 防护、精细化权限配置。
需要我帮你补充Spring Security 整合 MyBatis 从数据库查询真实权限的代码吗?