Spring Security 基础:快速搭建安全认证系统

锦上添花
2025-06-13 17:29
阅读 256

一、开篇:什么是 Spring Security?它能做什么?

一、开篇:什么是 Spring Security?它能做什么?

想象你正在开发一个网站或后台管理系统,比如商城、博客、管理平台等。这类系统通常都会有“登录”这个功能:用户输入用户名和密码后才能进入后台,访问一些受保护的内容。

Spring Security 就是帮助我们实现这些安全功能的工具包。它可以:

  • 给你的网页或接口加上登录验证
  • 控制不同用户的访问权限(谁可以看什么内容)
  • 防止非法请求(比如未授权的 API 请求)
  • 管理用户信息(如用户名、密码、角色等)

简单来说,Spring Security 是保障我们 Web 应用安全的“门卫”,帮你把不需要的人挡在外面。

本教程面向的是完全零基础的同学,我们会从头开始一步步教你如何搭建一个最简单的安全认证系统。


二、环境准备

二、环境准备

在正式写代码之前,我们需要先准备好开发环境:

1. 安装 Java(JDK)

Spring Boot 是基于 Java 的,所以首先要安装 JDK:

  • 推荐版本:JDK 17 或者 JDK 21(社区版即可)
  • 下载地址:Oracle JDKOpenJDK
  • 安装完成后,在命令行输入:
    java -version
    

2. 安装 IDE(推荐 IntelliJ IDEA)

IntelliJ IDEA 是开发 Spring Boot 最常用的编辑器之一。

3. 创建 Spring Boot 项目(使用 Spring Initializr)

你可以直接访问官方网站生成项目骨架:

  • 地址:start.spring.io
  • 配置如下:
    • Project: Maven
    • Language: Java
    • Spring Boot Version: 3.x(建议最新稳定版)
    • Project Metadata:
      • Group: com.example
      • Artifact: demo-security
      • Name: demo-security
      • Description: Demo project for Spring Security
      • Package name: com.example.demosecurity
    • Dependencies:
      • Spring Web
      • Spring Security
      • Thymeleaf(可选,用于展示页面)

点击 "Generate" 按钮下载压缩包,解压后用 IntelliJ IDEA 打开。


三、核心概念通俗讲解

三、核心概念通俗讲解

为了让新手更容易理解,我们来聊聊几个 Spring Security 中非常重要的术语,并用生活中的例子类比说明。

1. 用户(User)

就是使用我们系统的“人”。例如张三、李四,他们各自有自己的账号和密码。

2. 角色(Role / Authority)

代表用户身份或权限。比如:

  • ROLE_ADMIN:管理员,可以操作所有功能
  • ROLE_USER:普通用户,只能查看部分功能

可以把角色理解为公司里不同的职位:经理、员工、实习生。

3. 认证(Authentication)

就是判断用户是不是他自己。比如用户输入用户名和密码是否正确的过程。

就像进公司打卡时刷脸一样,系统要确认你是谁。

4. 授权(Authorization)

是指根据用户的角色,决定他能不能访问某些页面或接口。

比如只有经理(ROLE_ADMIN)可以进财务室,而实习生不能。

5. 过滤器链(Filter Chain)

Spring Security 使用一系列“过滤器”,像安检通道一样拦截每个请求,检查是否有权限访问。


四、实战项目:手把手搭建一个安全认证系统

四、实战项目:手把手搭建一个安全认证系统

我们将完成以下步骤:

  1. 实现最简登录页面(带用户名、密码输入框)
  2. 实现内存中用户认证(不连接数据库)
  3. 添加角色并限制访问权限
  4. 实现退出登录功能

第一步:添加依赖项

打开 pom.xml 文件,确保已经引入了以下两个依赖:

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

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

如果你没有用 Thymeleaf,这里也可以不用添加。


第二步:配置内存用户(In-Memory User)

为了方便学习,我们暂时将用户信息写在代码中,而不是数据库里。

新建一个配置类 SecurityConfig.java

package com.example.demosecurity;

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.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.web.SecurityFilterChain;

@Configuration
public class SecurityConfig {

    // 密码编码器,用于加密密码
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    // 创建两个测试用户
    @Bean
    public InMemoryUserDetailsManager userDetailsService(PasswordEncoder encoder) {
        UserDetails user = User.builder()
                .username("user")
                .password(encoder.encode("123456"))
                .roles("USER")
                .build();

        UserDetails admin = User.builder()
                .username("admin")
                .password(encoder.encode("admin123"))
                .roles("ADMIN")
                .build();

        return new InMemoryUserDetailsManager(user, admin);
    }

    // 配置安全规则
    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
            .authorizeHttpRequests(auth -> auth
                .requestMatchers("/").permitAll()
                .requestMatchers("/admin").hasRole("ADMIN")
                .anyRequest().authenticated()
            )
            .formLogin(login -> login
                .defaultSuccessUrl("/home")
                .permitAll()
            )
            .logout(logout -> logout
                .permitAll()
            );

        return http.build();
    }
}

解释一下做了什么:

  • 配置了两个用户:useradmin,分别对应普通用户和管理员
  • 使用 BCryptPasswordEncoder 加密密码(更安全)
  • / 页面无需登录即可访问
  • /admin 页面只能由拥有 ROLE_ADMIN 角色的用户访问
  • 其他请求需要登录才可以访问
  • 启用了默认登录页面和注销功能

第三步:编写控制器和页面(简易)

创建一个控制器类 HomeController.java

package com.example.demosecurity;

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

@Controller
public class HomeController {

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

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

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

然后在 src/main/resources/templates 目录下创建三个 HTML 页面:

index.html(主页)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>主页</title>
</head>
<body>
<h2>欢迎来到首页!</h2>
<a href="/home">进入用户界面</a> |
<a href="/admin">进入管理员界面</a>
</body>
</html>

home.html(登录后访问)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>用户中心</title>
</head>
<body>
<h2>你好,用户!</h2>
<p>这是普通用户可见的页面。</p>
<form action="/logout" method="post">
    <input type="submit" value="退出登录">
</form>
</body>
</html>

admin.html(管理员专用)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>管理员中心</title>
</head>
<body>
<h2>你好,管理员!</h2>
<p>这是只有管理员才能访问的页面。</p>
<form action="/logout" method="post">
    <input type="submit" value="退出登录">
</form>
</body>
</html>

第四步:运行程序并测试

  1. 点击 IDEA 的 Run 按钮启动项目
  2. 浏览器访问 http://localhost:8080
  3. 点击链接进入 /admin 页面,会被自动跳转到 /login 登录页
  4. 输入我们定义好的用户名和密码进行测试:
  • 普通用户:

    • 用户名:user
    • 密码:123456
  • 管理员:

    • 用户名:admin
    • 密码:admin123

你会发现:

  • user 只能访问 /home
  • admin 可以访问 /home/admin

这就完成了我们的第一个 Spring Security 安全认证系统!


五、常见问题解答

Q1:为什么我输入的密码不是明文存储?

A:出于安全性考虑,Spring Security 不允许使用明文密码,必须使用加密方式(如 BCrypt)。我们在示例中使用了 BCryptPasswordEncoder,你也可以换成别的加密方式。


Q2:登录失败怎么办?

A:可能的原因有:

  • 用户名错误
  • 密码输入错误(注意大小写)
  • 密码没正确加密
  • 没有启用 .formLogin() 配置
  • 没有添加 CSRF 支持(如果是自定义登录页面)

Q3:我的页面一直跳转不到正确的路径?

A:请检查:

  • 是否配置了 .defaultSuccessUrl() 指定登录成功跳转地址
  • 是否开启了 .permitAll() 允许所有人访问登录页
  • 自定义页面是否缺少 <form action="/login" method="post"> 标签

Q4:怎样查看当前用户的信息?

你可以在控制器方法中加入参数来获取当前用户:

@GetMapping("/home")
public String home(Principal principal) {
    System.out.println("当前用户:" + principal.getName());
    return "home";
}

Q5:我可以自定义登录页面吗?

当然可以!只需创建自己的登录 HTML 页面,并告诉 Spring Security 使用它:

.loginPage("/my-login")   // 指向你自定义的登录页
.permitAll()

然后创建对应的路由和页面即可。


六、学习建议:下一步学什么?

恭喜你完成了第一个安全认证系统!

接下来你可以继续深入学习以下内容:

学习模块 推荐方向
数据库存储用户 把用户数据存入 MySQL,使用 JDBCJPA 来做用户验证
OAuth2 / JWT 学习第三方登录(微信、QQ)、Token 认证(常用于 App 接口)
权限细粒度控制 使用 @PreAuthorize, @Secured 注解对方法级别的权限控制
多种登录方式 如手机号验证码登录、二维码登录、LDAP 认证等

建议资源:


总结

通过本教程,你学会了:

  • Spring Security 是什么,用来做什么
  • 如何快速搭建一个带有登录功能的 Web 应用
  • 内存中用户的创建与配置
  • 简单的页面访问权限控制
  • 登录、退出功能的实现
  • 初学者常见问题的解决思路

现在你已经入门了 Spring Security,接下来只需要多练习、多实践,就能越来越熟练地使用它来保护你的项目啦!

祝你编程愉快,学有所成!🎉

评论 0

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