杰瑞科技汇

spring security教程

Spring Security 全方位教程:从入门到实战

目录

  1. 为什么是 Spring Security?
  2. 核心概念:认证与授权
  3. 快速开始:你的第一个 Spring Security 应用
  4. 深入配置:自定义认证规则
  5. 用户认证:自定义用户DetailsService
  6. 密码加密:BCryptPasswordEncoder
  7. 授权:基于角色的访问控制
  8. 实现注销功能
  9. 实现“记住我”功能
  10. 实践:构建一个完整的 RBAC 系统
  11. 总结与进阶

为什么是 Spring Security?

Spring Security 是一个功能强大、高度可定制的身份验证和访问控制框架,它是 Spring 生态系统的一部分,专注于为 Java 应用程序提供企业级的安全服务。

spring security教程-图1
(图片来源网络,侵删)

主要特点:

  • 全面的安全解决方案:涵盖了认证、授权、攻击防护(如 CSRF、Session Fixation)、方法安全等。
  • 高度可定制:虽然开箱即用,但你可以轻松地替换其任何组件来满足特定需求。
  • 与 Spring 框架无缝集成:与 Spring Boot、Spring MVC 等完美配合,配置简单。
  • 社区活跃,文档丰富:遇到问题很容易找到解决方案。

核心概念:认证与授权

在深入代码之前,必须理解两个最基本的安全概念:

a. 认证

认证“你是谁?” 的过程,系统通过验证用户的凭证(如用户名/密码、令牌、生物特征等)来确认用户的身份。

  • 例子:你输入用户名 admin 和密码 123456,系统验证这个组合是否正确,如果正确,你就被认证了。

b. 授权

授权“你能做什么?” 的过程,在认证之后,系统根据用户的身份和角色,决定其可以访问哪些资源或执行哪些操作。

spring security教程-图2
(图片来源网络,侵删)
  • 例子:认证后,系统知道 admin 角色可以删除文章,而 user 角色只能查看文章,这就是授权。

快速开始:你的第一个 Spring Security 应用

我们将使用 Spring Initializr 快速创建一个项目。

步骤 1:创建项目

访问 start.spring.io,配置如下:

  • Project: Maven Project
  • Language: Java
  • Spring Boot: 3.x.x (推荐最新稳定版)
  • Project Metadata:
    • Group: com.example
    • Artifact: security-demo
    • Name: security-demo
    • Packaging: Jar
    • Java: 17 或更高版本
  • Dependencies:
    • Spring Web: 用于创建 Web 应用。
    • Spring Security: 核心安全依赖。

点击 "GENERATE" 下载项目并导入你的 IDE (如 IntelliJ IDEA 或 VS Code)。

步骤 2:创建一个简单的 Controller

src/main/java/com/example/securitydemo 目录下创建一个 HomeController.java

spring security教程-图3
(图片来源网络,侵删)
package com.example.securitydemo;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HomeController {
    @GetMapping("/hello")
    public String hello() {
        return "Hello, World!";
    }
    @GetMapping("/admin")
    public String admin() {
        return "Welcome, Admin!";
    }
}

步骤 3:运行并测试

  1. 运行 SecurityDemoApplication.java 主类。
  2. 打开浏览器,访问 http://localhost:8080/hello
  3. 你会发现:浏览器没有直接显示 "Hello, World!",而是跳转到了一个 Spring Security 默认的登录页面!

发生了什么? 只要你添加了 Spring Security 依赖,你的应用就会被自动保护,所有 URL 默认都需要身份认证,Spring Security 提供了一个默认的用户名 user 和一个在启动时随机生成的密码(你可以在控制台日志中找到)。

步骤 4:使用默认用户登录

  1. 在登录页面,输入用户名 user 和控制台日志中显示的密码。
  2. 登录成功后,你将被重定向到 /hello 页面,看到 "Hello, World!"。

同样,访问 /admin 也能看到 "Welcome, Admin!",这是因为默认配置下,所有认证用户都可以访问所有路径。


深入配置:自定义认证规则

默认的登录页面和用户名/密码显然不适用于生产环境,我们需要自定义规则,在 Spring Boot 中,最简单的方式是继承 WebSecurityConfigurerAdapter(虽然在新版本中不推荐,但为了理解原理,我们先从这里开始)。

步骤 1:创建安全配置类

创建一个 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.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
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.crypto.password.NoOpPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
@Configuration
@EnableWebSecurity // 启用 Spring Security 的 Web 安全功能
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    // 1. 定义密码编码器(为了简单,我们先使用 NoOpPasswordEncoder,但强烈不推荐!)
    @Bean
    public PasswordEncoder passwordEncoder() {
        return NoOpPasswordEncoder.getInstance(); // 明文密码,仅用于演示
    }
    // 2. 定义用户详情服务
    @Override
    @Bean
    public UserDetailsService userDetailsService() {
        UserDetails user = User.withUsername("user")
                .password("password")
                .roles("USER")
                .build();
        UserDetails admin = User.withUsername("admin")
                .password("admin")
                .roles("ADMIN")
                .build();
        return new InMemoryUserDetailsManager(user, admin);
    }
    // 3. 配置 HTTP 安全规则
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests() // 开启请求权限配置
                .antMatchers("/hello").hasRole("USER") // /hello 需要 USER 角色
                .antMatchers("/admin").hasRole("ADMIN") // /admin 需要 ADMIN 角色
                .anyRequest().authenticated() // 其他所有请求都需要认证
            .and()
            .formLogin() // 启用表单登录
                .loginPage("/login") // 自定义登录页面 (需要自己创建)
                .permitAll() // 允许所有人访问登录页面
            .and()
            .logout() // 启用注销
                .permitAll(); // 允许所有人访问注销
    }
}

代码解析

  • @EnableWebSecurity: 启用安全配置。
  • passwordEncoder(): 定义了如何处理密码。NoOpPasswordEncoder 是不安全的,仅用于演示! 生产环境必须使用加密编码器(如 BCrypt)。
  • userDetailsService(): 在内存中创建了两个用户:user(角色 USER)和 admin(角色 ADMIN)。
  • configure(HttpSecurity): 这是核心,定义了访问控制规则。
    • .antMatchers("/hello").hasRole("USER"): 指定访问 /hello 必须具备 USER 角色。
    • .formLogin(): 启用默认的表单登录机制,并指定了自定义登录页路径。
    • .logout(): 启用注销功能。

步骤 2:创建自定义登录页面

src/main/resources/templates 目录下创建 login.html (需要 Thymeleaf 依赖)。

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>Login</title>
    <style>
        body { font-family: Arial, sans-serif; margin: 40px; }
        .container { max-width: 400px; margin: 0 auto; padding: 20px; border: 1px solid #ccc; border-radius: 5px; }
        input[type="text"], input[type="password"] { width: 100%; padding: 10px
分享:
扫描分享到社交APP
上一篇
下一篇