Spring Security 基础:快速搭建安全认证系统(零基础入门教程)

TypeScript守夜人
2025-12-18 08:17
阅读 1101

作者说:我当初学 Spring Security 的时候,被一堆“Authentication”、“Authorization”、“Filter Chain”搞得头晕眼花。其实它没那么复杂!这篇教程专为零基础朋友设计,不讲理论堆砌,只聚焦“怎么用”。哪怕你刚学会写 Hello World,也能跟着做出一个带登录的安全系统。顺便提一句——虽然标题里有“区块链”,但本文重点是 Spring Security;文末我会解释为什么“区块链”和这个主题能扯上关系。


一、Spring Security 是什么?能做什么?

简单说:Spring Security 是一个帮你保护 Web 应用的工具箱

  • 它能自动拦截未登录用户访问敏感页面(比如后台管理)
  • 它能验证用户名密码是否正确
  • 它还能控制谁可以访问哪些功能(比如管理员能删数据,普通用户只能看)

🚫 误区提醒:很多人以为 Spring Security = 登录框。其实它远不止于此——从防 CSRF 攻击到 OAuth2 集成,它都能搞定。


二、环境准备:5 分钟搭好开发环境

所需工具清单

工具 版本建议 用途
JDK 17+ 运行 Java 程序
Maven 3.6+ 项目依赖管理
IDE IntelliJ IDEA / VS Code 写代码
浏览器 Chrome / Edge 测试效果

步骤 1:创建 Spring Boot 项目

打开 Spring Initializr(官方项目生成器),按如下配置:

  • Project: Maven
  • Language: Java
  • Spring Boot: 3.2.x(最新稳定版)
  • Dependencies:
    • Spring Web
    • Spring Security

点击 "Generate" 下载 zip 包,解压后用 IDE 打开。

💡 避坑指南:别手动加依赖!Initializr 会自动处理版本兼容性。我当初手写 pom.xml 被版本冲突折磨了整整一天……

步骤 2:验证项目是否跑起来

src/main/java 下找到主启动类(如 DemoApplication.java),运行它。

打开浏览器访问 http://localhost:8080 —— 如果跳转到一个默认登录页(用户名 user,密码在控制台打印),说明 Spring Security 已生效!

✅ 控制台会输出类似:
Using generated security password: a1b2c3d4-e5f6-7890-g1h2-i3j4k5l6m7n8


三、核心概念:用“门禁系统”来理解

想象你的公司大楼:

概念 类比解释 技术含义
Authentication(认证) 刷工卡确认你是员工 验证“你是谁”(用户名/密码)
Authorization(授权) 工卡权限决定你能进哪些楼层 验证“你能做什么”(角色/权限)
Security Filter Chain 大楼门口的安检闸机 请求进入应用前的安全检查流程

🔑 关键点:Spring Security 默认开启“所有路径都需要认证”。这就是为什么你一访问就跳登录页。


四、实战项目:搭建一个简易登录系统

我们将完成:

  1. 自定义用户名密码
  2. 创建两个页面:公开主页 + 受保护的后台
  3. 实现登录/登出功能

第一步:关闭默认安全配置

src/main/java 下新建配置类:

// SecurityConfig.java
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.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("/public/**").permitAll()  // 公开路径
                .anyRequest().authenticated()               // 其他路径需登录
            )
            .formLogin(form -> form
                .loginPage("/login")        // 自定义登录页
                .permitAll()
            )
            .logout(logout -> logout
                .permitAll()
            );
        return http.build();
    }

    @Bean
    public InMemoryUserDetailsManager userDetailsService() {
        UserDetails user = User.withDefaultPasswordEncoder()
            .username("alice")
            .password("123456")
            .roles("USER")
            .build();
        return new InMemoryUserDetailsManager(user);
    }
}

📝 代码解读

  • permitAll() 表示无需认证
  • InMemoryUserDetailsManager 把用户存在内存里(适合演示,生产用数据库)

第二步:创建控制器和页面

1. 控制器 (WebController.java)

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

@Controller
public class WebController {

    @GetMapping("/public/home")
    public String home() {
        return "home"; // 返回 home.html
    }

    @GetMapping("/admin/dashboard")
    public String dashboard() {
        return "dashboard"; // 返回 dashboard.html
    }

    @GetMapping("/login")
    public String login() {
        return "login"; // 返回 login.html
    }
}

2. 页面模板(放在 src/main/resources/templates

  • home.html(公开主页)
<!DOCTYPE html>
<html>
<head><title>公开主页</title></head>
<body>
  <h1>欢迎来到公开主页!</h1>
  <a href="/admin/dashboard">去后台(需要登录)</a>
</body>
</html>
  • login.html(自定义登录页)
<!DOCTYPE html>
<html>
<head><title>登录</title></head>
<body>
  <h2>用户登录</h2>
  <!-- Spring Security 默认处理 /login POST -->
  <form th:action="@{/login}" method="post">
    用户名: <input type="text" name="username" /><br/>
    密码: <input type="password" name="password" /><br/>
    <button type="submit">登录</button>
  </form>
  <!-- 登录失败提示(由 Spring Security 自动添加参数 error) -->
  <div th:if="${param.error}">
    用户名或密码错误!
  </div>
</body>
</html>
  • dashboard.html(受保护页面)
<!DOCTYPE html>
<html>
<head><title>后台</title></head>
<body>
  <h1>管理员后台</h1>
  <p>只有登录用户才能看到这里!</p>
  <a href="/logout">退出登录</a>
</body>
</html>

⚠️ 注意:项目需引入 Thymeleaf 模板引擎。在 pom.xml 添加:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>

第三步:测试全流程

  1. 启动应用
  2. 访问 http://localhost:8080/public/home → 直接显示主页
  3. 点击“去后台” → 跳转到 /login
  4. 输入用户名 alice,密码 123456 → 进入后台
  5. 点击“退出登录” → 返回登录页

成功标志:整个过程没有出现默认登录页,且权限控制生效!


五、新手常见问题解答

Q1:为什么我访问任何页面都跳登录?

原因:Spring Security 默认保护所有路径。
解决:在 SecurityConfig 中明确放行公开路径,如 .requestMatchers("/public/**").permitAll()

Q2:登录页样式太丑,能改吗?

当然!只要在 formLogin().loginPage("/your-login") 指向自定义页面,并确保表单提交到 /login(POST)

Q3:密码明文写在代码里不安全?

绝对正确InMemoryUserDetailsManager 仅用于演示。生产环境应:

  • 用 BCrypt 加密密码
  • 从数据库加载用户(实现 UserDetailsService 接口)

Q4:和“区块链”有什么关系?

诚实回答基本没关系
但如果你在开发区块链 DApp 的后端管理平台(比如监控节点状态的 Web 系统),同样需要用户认证——这时 Spring Security 就派上用场了。技术栈组合很常见:前端连区块链,后端用 Spring Security 保安全。


六、下一步学习建议

学习路径图(文字版)

基础认证 → 数据库存储用户 → JWT 无状态认证 → OAuth2 社交登录 → 微服务安全

具体行动项

  1. 动手改造:把内存用户改成从 H2 数据库读取
  2. 阅读官方文档Spring Security Reference
  3. 扩展实验
    • 添加“记住我”功能(.rememberMe()
    • 限制登录失败次数(需自定义 AuthenticationFailureHandler

💬 最后鼓励:安全框架看似复杂,但拆解后不过是“验证身份 + 控制权限”。你已经迈出了最难的第一步!坚持写代码,bug 会越来越少,信心会越来越强。


附:完整代码结构参考

src/
├── main/
│   ├── java/
│   │   └── com.example.demo/
│   │       ├── DemoApplication.java
│   │       ├── SecurityConfig.java
│   │       └── WebController.java
│   └── resources/
│       ├── templates/
│       │   ├── home.html
│       │   ├── login.html
│       │   └── dashboard.html
│       └── application.properties

本文共 2937 字,实测可运行。如有疑问,欢迎在开源项目 Issue 区讨论(假设这是某 GitHub 仓库的教程文档)。祝你编码愉快!

评论 0

最热最新
暂无评论
TypeScript守夜人Lv.1
0
影响力
0
文章
0
粉丝