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

朱磊
2025-12-13 20:25
阅读 299

作者简介:211高校计算机专业研二学生,主攻后端开发,热衷于写技术博客帮助新人少走弯路。本文基于我当初学习Spring Security时踩过的坑整理而成,特别适合完全零基础的同学。


大家好!最近在帮学弟学妹改简历时,发现很多人写了“熟悉Spring Boot”,但一问到“有没有做过用户登录、权限控制”,就支支吾吾。其实,只要掌握 Spring Security,你就能快速实现一套完整的安全认证系统——这不仅能让项目更专业,还能在简历上写出“实现了基于RBAC的权限控制系统”这样的亮点!

我当初学的时候,被各种AuthenticationAuthorizationFilterChain搞得晕头转向。后来才发现:Spring Security没那么难,关键是动手做一遍。今天这篇教程,我就手把手带你从零搭建一个带登录、登出、权限控制的小系统,全程代码可运行、思路清晰,保证你学完就能写进简历!


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

简单说:Spring Security 是 Spring 家族中专门用来做“安全防护”的框架

它能帮你自动完成:

  • 用户登录(用户名/密码)
  • 密码加密存储
  • 登录状态保持(Session 或 Token)
  • 页面/接口的访问权限控制(比如:只有管理员才能删除用户)
  • 防止CSRF攻击、点击劫持等常见Web安全问题

💡 举个例子
你做一个后台管理系统,普通员工只能看数据,管理员才能删数据。
如果不用 Spring Security,你要手动写一堆 if (user.role == "admin") 的判断;
用了它,一行注解 @PreAuthorize("hasRole('ADMIN')") 就搞定!


二、环境准备(5分钟搞定)

所需工具

工具 版本建议 说明
JDK 17 或 8 Java 开发必备
Maven 3.6+ 项目依赖管理
IDE IntelliJ IDEA(推荐)或 VS Code 写代码用
浏览器 Chrome / Edge 测试用

创建项目(使用 Spring Initializr)

  1. 打开 https://start.spring.io
  2. 填写如下配置:
Project: Maven
Language: Java
Spring Boot: 3.x(最新稳定版)
Group: com.example
Artifact: security-demo
Packaging: Jar
Java: 17
  1. Dependencies 中搜索并添加:

    • Spring Web
    • Spring Security
    • Thymeleaf(用于简单页面展示)
  2. 点击 Generate 下载 ZIP,解压后用 IDEA 打开。

验证是否成功
运行 SecurityDemoApplication.java,启动后访问 http://localhost:8080
如果跳转到一个默认的登录页(用户名 user,密码在控制台打印),说明环境 OK!


三、核心概念(用大白话解释)

别被术语吓到,记住这4个关键词就够了:

概念 大白话解释 类比
Authentication(认证) “你是谁?” —— 验证用户名密码是否正确 刷校园卡进宿舍楼
Authorization(授权) “你能干什么?” —— 判断用户有没有权限访问某个资源 宿管阿姨看你是不是本楼学生
UserDetails 存放用户信息的对象(用户名、密码、角色等) 你的学生证信息
PasswordEncoder 密码加密器,不能明文存密码! 把密码变成“乱码”再存数据库

⚠️ 避坑指南
很多人直接把密码明文存数据库,这是重大安全隐患!
必须用 BCryptPasswordEncoder 加密,Spring Security 默认就支持。


四、实战:5步搭建登录系统

我们将实现:

  • 自定义登录页面
  • 用户名/密码登录
  • 登出功能
  • 角色权限控制(USER / ADMIN)

第1步:创建用户实体和内存用户(简化版)

📌 先不连数据库,用内存模拟用户,降低复杂度。

// src/main/java/com/example/securitydemo/config/SecurityConfig.java
package com.example.securitydemo.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.security.UserDetailsService;
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;

@EnableWebSecurity
public class SecurityConfig {

    // 步骤1:定义两个用户(内存中)
    @Bean
    public UserDetailsService userDetailsService() {
        UserDetails user = User.builder()
                .username("zhangsan")
                .password("{bcrypt}$2a$10$GRLdNijSQMUvl/au9ofL.eDwmoohzzS7.rmNSJZ.0FxO/BTk7fL5y") // 密码: 123456
                .roles("USER")
                .build();

        UserDetails admin = User.builder()
                .username("lisi")
                .password("{bcrypt}$2a$10$GRLdNijSQMUvl/au9ofL.eDwmoohzzS7.rmNSJZ.0FxO/BTk7fL5y") // 同样密码
                .roles("ADMIN", "USER")
                .build();

        return new InMemoryUserDetailsManager(user, admin);
    }

    // 步骤2:配置安全规则
    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
            .authorizeHttpRequests(auth -> auth
                .requestMatchers("/login").permitAll()      // 登录页所有人可访问
                .requestMatchers("/admin/**").hasRole("ADMIN") // /admin/开头的路径需要ADMIN角色
                .anyRequest().authenticated()               // 其他所有请求都要登录
            )
            .formLogin(form -> form
                .loginPage("/login")        // 自定义登录页
                .defaultSuccessUrl("/home") // 登录成功跳转
                .permitAll()
            )
            .logout(logout -> logout
                .logoutSuccessUrl("/login?logout") // 登出后跳回登录页
                .permitAll()
            );

        return http.build();
    }
}

🔑 密码生成说明
上面的 {bcrypt}...123456 经过 BCrypt 加密后的结果。
你可以在测试类中生成自己的密码:

System.out.println("{bcrypt}" + new BCryptPasswordEncoder().encode("你的密码"));

第2步:创建登录页面(Thymeleaf)

<!-- src/main/resources/templates/login.html -->
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>登录</title>
</head>
<body>
<h2>用户登录</h2>

<!-- 显示登出成功提示 -->
<p th:if="${param.logout}" style="color:green;">您已成功退出!</p>

<form th:action="@{/login}" method="post">
    <div>
        <label>用户名:</label>
        <input type="text" name="username" required />
    </div>
    <div>
        <label>密码:</label>
        <input type="password" name="password" required />
    </div>
    <button type="submit">登录</button>
</form>

<p>测试账号:<br/>
    普通用户:zhangsan / 123456<br/>
    管理员:lisi / 123456
</p>
</body>
</html>

第3步:创建首页和管理员页

首页(所有登录用户可见)

<!-- src/main/resources/templates/home.html -->
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head><title>首页</title></head>
<body>
<h1>欢迎回来!</h1>
<p>当前用户:<span th:text="${#authentication.name}"></span></p>

<a th:href="@{/admin}">进入管理后台(仅管理员可见)</a> |
<a th:href="@{/logout}">退出登录</a>
</body>
</html>

管理员页(仅 ADMIN 可访问)

<!-- src/main/resources/templates/admin.html -->
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head><title>管理后台</title></head>
<body>
<h1>管理员专区</h1>
<p>只有 ADMIN 角色才能看到此页面!</p>
<a th:href="@{/home}">返回首页</a>
</body>
</html>

第4步:创建 Controller 路由

// src/main/java/com/example/securitydemo/controller/PageController.java
package com.example.securitydemo.controller;

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

@Controller
public class PageController {

    @GetMapping("/login")
    public String login() {
        return "login";
    }

    @GetMapping("/home")
    public String home() {
        return "home";
    }

    @GetMapping("/admin")
    public String admin() {
        return "admin";
    }
}

第5步:启动测试!

  1. 运行 SecurityDemoApplication
  2. 访问 http://localhost:8080 → 自动跳转到 /login
  3. zhangsan / 123456 登录 → 进入首页
    • 点击“进入管理后台” → 403 Forbidden(因为不是 ADMIN)
  4. lisi / 123456 登录 → 可正常访问 /admin

恭喜!你已经实现了基础认证+权限控制!


五、新手常见问题解答(FAQ)

Q1:为什么登录页样式很丑?能自定义吗?

A:当然可以!Spring Security 不限制前端。你可以用 Bootstrap、Vue 等做漂亮界面,只要表单提交到 /login,字段叫 usernamepassword 即可。

Q2:密码必须用 {bcrypt} 前缀吗?

A:是的!Spring Security 5+ 要求明确指定加密方式。如果你用 BCryptPasswordEncoder,就要加 {bcrypt} 前缀,否则会报错。

Q3:如何禁止自动跳转到默认登录页?

A:在 SecurityConfig 中配置 .formLogin().loginPage("/your-login") 并确保该路径 permitAll(),就不会用默认页了。

Q4:为什么登出后还能访问页面?

A:检查是否配置了 .logout().permitAll(),并且前端链接是 /logout(POST 请求)。Thymeleaf 的 <a> 标签默认是 GET,需用 JS 提交 POST,或改用表单按钮。

Q5:能把用户存在数据库吗?

A:完全可以!后续可替换 InMemoryUserDetailsManagerJdbcUserDetailsManager 或自定义 UserDetailsService 查询数据库。这是进阶内容,先掌握内存版再扩展。


六、学习建议 & 简历加分项

下一步学什么?

方向 推荐内容 简历写法示例
数据库集成 用 MyBatis/JPA 实现用户登录 “基于 Spring Security + MySQL 实现用户认证”
JWT 支持 无状态 Token 认证(适合 API) “集成 JWT 实现前后端分离鉴权”
OAuth2 微信/Google 第三方登录 “支持 OAuth2.0 第三方授权登录”
方法级权限 @PreAuthorize 控制方法调用 “实现细粒度方法级权限控制”

避坑总结(我踩过的雷)

  1. 不要忽略 CSRF:Web 项目默认开启,表单要加 _csrf 字段(Thymeleaf 自动处理)
  2. 密码必须加密:明文密码 = 简历减分项 + 安全事故
  3. 角色命名规范:Spring Security 会自动加 ROLE_ 前缀,所以代码写 hasRole("ADMIN"),实际角色是 ROLE_ADMIN

简历怎么写?

项目经验示例
后台管理系统(Spring Boot + Spring Security)

  • 基于 RBAC 模型实现用户认证与授权,支持 USER/ADMIN 双角色
  • 使用 BCrypt 加密存储密码,防止信息泄露
  • 通过 @PreAuthorize 注解实现接口级权限控制,提升系统安全性
  • 自定义登录/登出流程,优化用户体验

结语

Spring Security 看似复杂,但核心就是“认证 + 授权”两件事。只要你理解了内存用户的配置方式,后续迁移到数据库、JWT、OAuth2 都是水到渠成。

记住:能跑起来的代码,比完美的理论更重要。先把今天这个小项目跑通,你离“有安全模块的简历项目”就只差一步了!

如果你觉得这篇教程帮到了你,欢迎点赞收藏!也欢迎关注我的技术博客,后续我会更新《Spring Security + JWT 实战》《OAuth2 第三方登录详解》等进阶内容。

动手吧!你的第一个安全系统,就从这 100 行代码开始!

评论 0

最热最新
暂无评论
匿名用户Lv.1
0
影响力
0
文章
0
粉丝