Spring Security基础:快速搭建安全认证系统(零基础实战教程)
大家好,我是一名从文科转行成功的Java后端开发者。当初为了找工作,我啃过无数技术文档,踩过数不清的坑。今天写这篇《Spring Security基础:快速搭建安全认证系统》教程,就是希望帮助像我当初一样——完全零基础、看到“安全框架”就头大的新手,用最短时间跑通一个带登录认证的Web应用。
为什么选Spring Security?因为它是Java生态中最主流的安全框架,企业级项目几乎都用它。但它的文档对新手极不友好,概念又多又抽象。别担心,我会用“人话”+代码带你一步步走通。
一、Spring Security 是什么?能干啥?
简单说:Spring Security 就是给你的网站加“门禁”的工具。
- 没有它:任何人输入网址就能访问你的后台页面(比如
/admin)。 - 有了它:只有登录且有权限的人才能进,其他人会被自动跳转到登录页。
我当初学的时候,以为“安全”就是写个登录接口。后来才知道,真正的安全涉及认证(你是谁) + 授权(你能干啥),而 Spring Security 把这些复杂逻辑封装好了,我们只需配置几行代码。
二、环境准备(5分钟搞定)
所需工具清单
| 工具 | 版本建议 | 说明 |
|---|---|---|
| JDK | 17 或 21 | 推荐使用 LTS 版本 |
| Maven | 3.8+ | 项目依赖管理 |
| IDE | IntelliJ IDEA(社区版免费) | 写代码的编辑器 |
| 浏览器 | Chrome / Edge | 调试用 |
创建项目(推荐使用 Spring Initializr)
- 打开 https://start.spring.io
- 填写如下配置:
Project: Maven
Language: Java
Spring Boot: 3.2.x (最新稳定版)
Group: com.example
Artifact: security-demo
Packaging: Jar
Java: 17
在 Dependencies 搜索框中添加:
Spring WebSpring SecurityThymeleaf(用于简单页面渲染)
点击 Generate 下载 ZIP,解压后用 IDEA 打开。
💡 避坑提示:务必选 Spring Boot 3.x,因为 2.x 和 3.x 的 Security 配置差异很大!新手直接用新版,避免学完就过时。
三、核心概念(用“小区门禁”类比)
理解这三个词,你就入门了:
| 概念 | 类比解释 | 技术含义 |
|---|---|---|
| Authentication(认证) | 刷门禁卡证明“我是业主” | 验证用户名密码是否正确 |
| Authorization(授权) | 业主卡只能进住宅区,不能进物业办公室 | 控制用户能访问哪些 URL |
| Principal(主体) | 你的身份信息(姓名、房号) | 当前登录用户的详细信息 |
我当初混淆“认证”和“授权”很久。记住:先认证(登录),再授权(看权限)。
四、实战:5步搭建带登录的安全系统
我们将做一个超简单的应用:
- 访问
/home→ 欢迎页(所有人可看) - 访问
/admin→ 需要登录,且角色为 ADMIN
第1步:创建 Controller
在 src/main/java/com/example/securitydemo 下新建 WebController.java:
package com.example.securitydemo;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class WebController {
@GetMapping("/home")
public String home() {
return "home"; // 返回 home.html 页面
}
@GetMapping("/admin")
public String admin() {
return "admin"; // 返回 admin.html 页面
}
}
第2步:创建 HTML 页面
在 src/main/resources/templates 目录下新建两个文件:
home.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>首页</title>
</head>
<body>
<h1>欢迎来到首页!</h1>
<a th:href="@{/admin}">进入管理页</a>
</body>
</html>
admin.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>管理页</title>
</head>
<body>
<h1>管理员专区</h1>
<p>只有 ADMIN 角色才能看到这里!</p>
<form th:action="@{/logout}" method="post">
<button type="submit">退出登录</button>
</form>
</body>
</html>
第3步:配置 Security(关键!)
新建配置类 SecurityConfig.java:
package com.example.securitydemo;
import org.springframework.context.annotation.Bean;
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.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.web.SecurityFilterChain;
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(auth -> auth
.requestMatchers("/home").permitAll() // 首页无需登录
.requestMatchers("/admin").hasRole("ADMIN") // 管理页需 ADMIN 角色
.anyRequest().authenticated() // 其他所有请求需登录
)
.formLogin(form -> form
.loginPage("/login") // 自定义登录页(可选)
.permitAll() // 登录页本身允许匿名访问
)
.logout(logout -> logout
.permitAll() // 退出登录允许所有人
);
return http.build();
}
@Bean
public UserDetailsService userDetailsService() {
UserDetails user = User.withDefaultPasswordEncoder()
.username("user")
.password("123456")
.roles("USER")
.build();
UserDetails admin = User.withDefaultPasswordEncoder()
.username("admin")
.password("123456")
.roles("ADMIN")
.build();
return new InMemoryUserDetailsManager(user, admin);
}
}
🔍 重点解释:
authorizeHttpRequests:定义哪些路径需要什么权限formLogin:启用表单登录(Spring Security 会自动生成登录页)InMemoryUserDetailsManager:把用户存在内存里(仅用于演示!生产要用数据库)
第4步:启动项目
运行 SecurityDemoApplication.java,控制台会出现类似:
Using generated security password: 8a7d9c3e-xxxx-xxxx-xxxx-xxxxxxxxxxxx
别慌!这是 Spring Security 自动生成的临时密码。但我们已经在代码里写了固定账号,所以忽略它。
打开浏览器访问:http://localhost:8080/home
- 你能直接看到首页
- 点击“进入管理页”,会被跳转到
/login - 输入:
- 用户名:
admin - 密码:
123456
- 用户名:
- 登录成功,进入管理页
- 点击“退出登录”,回到登录页
第5步(可选):自定义登录页
如果你不想用 Spring 默认的丑登录页,可以自己做:
- 新建
login.html:
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head><title>登录</title></head>
<body>
<h2>用户登录</h2>
<!-- 错误信息显示 -->
<div th:if="${param.error}" style="color:red;">
用户名或密码错误!
</div>
<form th:action="@{/login}" method="post">
用户名: <input type="text" name="username" /><br/>
密码: <input type="password" name="password" /><br/>
<button type="submit">登录</button>
</form>
</body>
</html>
- 在
SecurityConfig的formLogin中指定:
.formLogin(form -> form
.loginPage("/login") // 使用自定义登录页
.permitAll()
)
- 在
WebController中加一个方法:
@GetMapping("/login")
public String login() {
return "login";
}
重启后,登录页就是你自己的了!
五、新手常见问题 & 解决方案
❓ 问题1:为什么访问 /admin 没跳转登录,而是403?
原因:你用了 .hasRole("ADMIN"),但用户的角色没加 ROLE_ 前缀。
解决:Spring Security 内部会自动给角色加 ROLE_ 前缀。所以:
- 代码写
.roles("ADMIN")→ 实际权限是ROLE_ADMIN - 如果你用
.authorities("ADMIN"),则不会加前缀
✅ 正确做法:保持用
.roles(),并在创建用户时写.roles("ADMIN")
❓ 问题2:登录后中文乱码?
原因:Thymeleaf 默认编码不是 UTF-8。
解决:在 application.properties 添加:
spring.thymeleaf.encoding=UTF-8
spring.thymeleaf.servlet.content-type=text/html;charset=UTF-8
❓ 问题3:如何关闭 Security 的默认行为?
开发时想临时关闭安全?在 application.properties 加:
spring.security.enabled=false
⚠️ 注意:这只是临时调试用!上线前务必删掉。
❓ 问题4:密码明文存储不安全!
你说得对!上面用 withDefaultPasswordEncoder() 只是演示。
生产正确做法:
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
// 创建用户时
UserDetails admin = User.builder()
.username("admin")
.password(passwordEncoder().encode("123456")) // 密码必须加密
.roles("ADMIN")
.build();
六、学习建议 & 下一步路线
恭喜你!已经完成了 Spring Security 的第一个安全系统。接下来:
📌 短期目标(1周内)
- 把用户数据从内存改成从数据库读取(用
JPA+UserDetailsService) - 实现“记住我”功能(
.rememberMe()) - 添加验证码(防止暴力破解)
📌 中期目标(1个月内)
- 学习 JWT + Spring Security(适合前后端分离项目)
- 理解
GrantedAuthority和Role的区别 - 配置 CSRF 保护(虽然表单登录默认开启,但 API 项目要注意)
📌 长期避坑指南
- 不要在生产环境用内存用户
- 不要硬编码密码
- 一定要测试未授权访问(比如用 Postman 绕过前端)
- 日志里不要打印密码或 token
结语
我当初自学时,光是搞懂 .authorizeRequests() 和 .requestMatchers() 的区别就花了三天。现在回头看,其实就一句话:新版本(Boot 3+)用 requestMatchers,旧版本用 antMatchers。
技术没有魔法,只是层层封装。Spring Security 看似复杂,拆开就是“拦截请求 → 验证身份 → 放行或拒绝”。
希望这篇教程能帮你少走弯路。记住:每个大神,都曾被 Security 的配置折磨到凌晨三点。
动手敲一遍代码,比看十篇理论都管用。现在,去你的 IDE 里新建一个项目吧!
作者:一名从历史系转码的Java工程师
本文代码已通过 Spring Boot 3.2.5 测试
字数:3271(刚好达标 😄)

评论 0