一、什么是 spring security?
spring security 是一个功能强大、高度可定制的身份验证(authentication)和访问控制(authorization)框架,是保护基于 spring 的应用的事实标准。
✅ 核心功能:
- 用户登录认证(authentication)
- 权限控制、角色控制(authorization)
- 防止 csrf、会话固定、点击劫持等攻击
- 支持多种登录方式:表单登录、http basic、oauth2、jwt、ldap 等
- 与 spring boot 无缝集成
二、spring security 核心概念
1.authentication(认证)
- 代表“当前用户是谁”,包含用户名、密码、权限等。
- 由
authenticationmanager管理认证过程。
2.userdetails&userdetailsservice
userdetails:封装用户信息(用户名、密码、权限、是否锁定等)userdetailsservice:根据用户名加载userdetails
@override
public userdetails loaduserbyusername(string username) {
// 从数据库查用户 → 返回 userdetails(含加密密码 + 权限)
}3.passwordencoder
- 用于加密密码和比对密码。
- 永远不要存储明文密码!
- 常用实现:
bcryptpasswordencoder,scryptpasswordencoder,pbkdf2passwordencoder
// 注册时: user.setpassword(passwordencoder.encode(rawpassword)); // 登录时(框架自动调用): passwordencoder.matches(rawpassword, encodedpassword); // true/false
4.grantedauthority
- 代表一个权限,如
"role_admin"、"user:delete"。 - 通常以
role_开头表示角色,其它表示具体权限。
5.securitycontext&securitycontextholder
- 存储当前登录用户的信息(
authentication对象)。 - 可在任何地方获取当前用户:
authentication auth = securitycontextholder.getcontext().getauthentication(); string username = auth.getname();
三、spring security 工作流程(认证过程)

sequencediagram
participant user
participant filter as filterchain (spring security)
participant provider as authenticationprovider
participant service as userdetailsservice
participant encoder as passwordencoder
user->>filter: 提交用户名/密码
filter->>provider: 调用 authenticate()
provider->>service: loaduserbyusername(username)
service-->>provider: 返回 userdetails(含加密密码)
provider->>encoder: matches(输入密码, 数据库加密密码)
alt 匹配成功
encoder-->>provider: true
provider-->>filter: 返回认证成功 authentication
filter->>user: 登录成功,跳转
else 匹配失败
encoder-->>provider: false
provider-->>filter: 抛出异常
filter->>user: 登录失败
end四、常用配置方式(spring boot)
1. 引入依赖(maven)
<dependency>
<groupid>org.springframework.boot</groupid>
<artifactid>spring-boot-starter-security</artifactid>
</dependency>2. 基础配置类(启用 web 安全)
@configuration
@enablewebsecurity
public class securityconfig {
@bean
public securityfilterchain filterchain(httpsecurity http) throws exception {
http
.authorizehttprequests(authz -> authz
.requestmatchers("/login", "/register", "/css/**").permitall()
.requestmatchers("/admin/**").hasrole("admin")
.requestmatchers("/user/**").hasanyrole("user", "admin")
.anyrequest().authenticated()
)
.formlogin(form -> form
.loginpage("/login") // 自定义登录页
.defaultsuccessurl("/home") // 登录成功跳转
.permitall()
)
.logout(logout -> logout
.logoutsuccessurl("/login?logout")
.permitall()
);
return http.build();
}
@bean
public passwordencoder passwordencoder() {
return new bcryptpasswordencoder(); // 推荐使用 bcrypt
}
}3. 自定义 userdetailsservice
@component
public class myuserserviceimpl implements userdetailsservice {
@autowired
private usermapper usermapper;
@override
public userdetails loaduserbyusername(string username) throws usernamenotfoundexception {
user user = usermapper.finduserbyname(username);
if (user == null) throw new usernamenotfoundexception("用户不存在");
// ✅ 直接返回数据库中的加密密码(注册时已加密存储!)
return user.builder()
.username(user.getusername())
.password(user.getsupwd()) // ← 不要再 encode!
.roles("user") // 或者 .authorities(getauthorities())
.build();
}
}五、权限控制(授权 authorization)
1. 方法级别权限(推荐)
@service
public class articleservice {
@preauthorize("hasrole('admin')") // 需要 admin 角色
public void deletearticle(long id) {
// ...
}
@preauthorize("hasauthority('article:edit')") // 需要具体权限
public void editarticle(article article) {
// ...
}
@postauthorize("returnobject.owner == authentication.name")
public article getarticle(long id) {
// 返回后检查:只有文章主人才能看
}
}⚠️ 要启用方法级权限,需在配置类加:
@enablemethodsecurity
@configuration
@enablewebsecurity
@enablemethodsecurity // ← 启用 @preauthorize 等注解
public class securityconfig { ... }2. 页面级别权限(thymeleaf)
<!-- 只有 admin 能看到 -->
<div sec:authorize="hasrole('admin')">
<a href="/admin" rel="external nofollow" >管理后台</a>
</div>
<!-- 显示当前用户名 -->
<span sec:authentication="name"></span>需引入:
<dependency>
<groupid>org.thymeleaf.extras</groupid>
<artifactid>thymeleaf-extras-springsecurity6</artifactid>
</dependency>六、常见自定义扩展
1. 自定义登录成功/失败处理器
@component
public class myauthenticationsuccesshandler implements authenticationsuccesshandler {
@override
public void onauthenticationsuccess(httpservletrequest request,
httpservletresponse response,
authentication authentication) throws ioexception {
response.sendredirect("/home?loginsuccess");
}
}在配置中使用:
.formlogin(form -> form
.successhandler(mysuccesshandler)
.failurehandler(myfailurehandler)
)2. 自定义权限异常处理
@component
public class myaccessdeniedhandler implements accessdeniedhandler {
@override
public void handle(httpservletrequest request, httpservletresponse response, accessdeniedexception accessdeniedexception) throws ioexception {
response.sendredirect("/403");
}
}配置:
.exceptionhandling(ex -> ex
.accessdeniedhandler(myaccessdeniedhandler)
)七、与 jwt / 前后端分离集成(简要)
如果你是前后端分离项目(如 vue + spring boot),通常不用 session,改用 jwt:
- 用户 post
/login提交用户名密码 - 后端验证成功 → 生成 jwt token 返回
- 前端后续请求在 header 中携带
authorization: bearer <token> - 后端用 filter 解析 token → 设置
securitycontext
⚠️ 此时
userdetailsservice依然有用 —— 用于从 token 中的用户名加载用户权限!
八、最佳实践 & 注意事项
| 项目 | 建议 |
|---|---|
| 密码存储 | 必须加密(bcrypt 最常用) |
| 密码比对 | 交给 spring security,不要手动比对 |
| 权限设计 | 角色(role_) + 细粒度权限(user:delete)结合 |
| 登录页 | 可自定义,但路径要 permitall |
| csrf | 表单登录默认开启,jwt 项目可关闭 |
| 调试 | 可临时 .authorizehttprequests(authz -> authz.anyrequest().permitall()) 放行所有 |
✅ 总结一句话:
spring security = 认证(你是谁)+ 授权(你能干什么)+ 安全防护,你只需要提供“用户数据”和“权限规则”,框架自动完成验证和拦截。
📚 学习路径建议:
- 先跑通表单登录 + 自定义 userdetailsservice
- 学会配置 url 权限控制
- 掌握方法级权限
@preauthorize - 学习自定义处理器(登录成功/失败、无权限)
- 进阶:jwt、oauth2、方法权限表达式、动态权限
💡 送你一个完整可运行的最小示例结构:
src/
├── controller/
│ └── logincontroller.java // 登录页、首页
├── service/
│ └── myuserserviceimpl.java // loaduserbyusername
├── config/
│ └── securityconfig.java // 权限配置 + passwordencoder
└── entity/
└── user.java // 用户实体(含加密密码字段)到此这篇关于spring security 框架的文章就介绍到这了,更多相关spring security 框架内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论