Spring Security 深度学习(一): 基础入门与默认行为分析

在这里插入图片描述

目录

    • 1. 引言:为何选择Spring Security?
    • 2. 核心概念:认证 (Authentication) 与 授权 (Authorization)
      • 2.1 什么是认证 (Authentication)?
      • 2.2 什么是授权 (Authorization)?
      • 2.3 安全性上下文 (SecurityContext)
    • 3. Spring Boot与Spring Security的“魔法”:自动配置
      • 3.1 引入依赖
      • 3.2 默认行为分析
    • 4. Spring Security 6.x+ 核心配置:SecurityFilterChain
      • 4.1 告别 WebSecurityConfigurerAdapter
      • 4.2 定义 SecurityFilterChain Bean
    • 5. 用户管理初窥:UserDetailsService 与 PasswordEncoder
      • 5.1 UserDetailsService:加载用户详情
      • 5.2 PasswordEncoder:密码加密的守护者
    • 6. 实战演练:配置内存用户与基础访问控制
      • 6.1 创建Spring Boot项目
      • 6.2 默认行为体验
      • 6.3 配置内存用户
      • 6.4 定制URL访问权限
    • 7. 进一步定制:禁用默认登录页与基础CSRF防护
    • 8. 常见陷阱与注意事项
    • 9. 阶段总结与进阶展望

1. 引言:为何选择Spring Security?

在当今互联网应用中,安全性是任何系统都必须优先考虑的要素。无论是用户数据、业务逻辑还是系统资源,都需要得到严密的保护。Spring Security作为Spring生态体系中功能强大且高度可定制的安全框架,为Java EE应用程序提供了全面的安全解决方案。它不仅仅是一个认证授权框架,更是一个完整的安全生态,涵盖了从数据保护、跨站请求伪造(CSRF)防护到会话管理等方方面面。

作为一名资深Java开发工程师,我深知在企业级应用开发中,Spring Security的重要性不言而喻。它能帮助我们:

  • 简化开发: 提供大量的开箱即用功能和Spring Boot Starter,大大减少安全模块的开发量。
  • 高度可定制: 允许我们根据具体业务需求,灵活定制认证源、授权策略、过滤器链等。
  • 安全性高: 默认遵循最佳实践,提供多种攻击防护机制。
  • 生态融合: 无缝集成Spring Framework、Spring Boot、Spring Cloud,是现代化微服务架构的理想选择。

本阶段,你的目标是理解Spring Security如何“魔幻般”地工作,从最基础的默认行为开始,逐步揭开它的面纱。

2. 核心概念:认证 (Authentication) 与 授权 (Authorization)

理解这两个核心概念是学习Spring Security的敲门砖。它们虽密切相关,但职责泾渭分明。

2.1 什么是认证 (Authentication)?

认证,简单来说就是 “你是谁?”。它是验证用户身份的过程,确认用户是否是其声称的本人。常见的认证方式包括:

  • 用户名密码登录: 最常见的方式,用户提供用户名和密码,系统验证其是否匹配。
  • 指纹/面部识别: 生物识别认证。
  • 短信/邮件验证码: 双因素认证的一部分。
  • 数字证书: 用于客户端或服务器身份验证。
  • Token认证: 如JWT,通过验证Token的有效性来确认用户身份。

在Spring Security中,认证的核心接口是Authentication,它代表着用户身份信息。当一个用户成功登录后,其身份信息就会被封装成一个Authentication对象。

2.2 什么是授权 (Authorization)?

授权,在用户身份被确认之后发生,它关注的是 “你能做什么?”。它是判断已认证用户是否有权限访问某个资源(如某个页面、某个API接口、某个数据记录)或执行某个操作的过程。

  • 角色 (Roles): 粗粒度的权限管理,如ADMIN(管理员)、USER(普通用户)。
  • 权限 (Authorities): 细粒度的权限管理,如PRODUCT_VIEW(查看商品)、PRODUCT_EDIT(编辑商品)。

例如,一个ADMIN角色可能拥有PRODUCT_VIEWPRODUCT_EDIT权限,而一个USER角色只有PRODUCT_VIEW权限。

在Spring Security中,授权通常通过表达式(如hasRole('ADMIN'))或投票器(AccessDecisionVoter)来完成。

2.3 安全性上下文 (SecurityContext)

理解了认证和授权,那么这些认证信息和授权结果保存在哪里呢?答案就是SecurityContext

SecurityContext 是Spring Security存储当前用户认证信息的核心容器。

  • 它通常与当前线程绑定,确保在一次请求链中,无论代码在何处执行,都能方便地获取到当前用户的认证详情。
  • SecurityContext 默认存储在 ThreadLocal 中,因此在同一个请求线程的任何地方,都可以通过 SecurityContextHolder 获取到 SecurityContext
  • 大部分情况下,SecurityContext 在用户会话(如HTTP Session)中进行存储和管理,这样用户在多个请求之间就不需要重复认证。

如何获取当前认证信息?
在你的代码中,可以通过以下方式获取:

import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;public class CurrentUserUtil {public static String getCurrentUsername() {Authentication authentication = SecurityContextHolder.getContext().getAuthentication();if (authentication == null || !authentication.isAuthenticated()) {return "anonymousUser"; // 或者抛出未认证异常}// authentication.getPrincipal() 返回的通常是 UserDetails 对象或字符串Object principal = authentication.getPrincipal();if (principal instanceof UserDetails) {return ((UserDetails) principal).getUsername();} else {return principal.toString();}}
}

3. Spring Boot与Spring Security的“魔法”:自动配置

Spring Boot的自动配置能力大大简化了Spring Security的集成。你只需要引入一个Starter依赖,Spring Boot就会帮你完成大部分基础配置。

3.1 引入依赖

首先,在你的pom.xml中添加Spring Security Starter依赖:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>3.2.5</version> <relativePath/></parent><groupId>com.example</groupId><artifactId>spring-security-stage1</artifactId><version>0.0.1-SNAPSHOT</version><name>spring-security-stage1</name><description>Demo project for Spring Security Stage 1</description><properties><java.version>17</java.version></properties><dependencies><!-- Spring Boot Web Starter --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- Spring Security Starter --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId></dependency><!-- Spring Boot Test Starter --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><!-- Spring Security Test for testing security configurations --><dependency><groupId>org.springframework.security</groupId><artifactId>spring-security-test</artifactId><scope>test</scope></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build>
</project>

3.2 默认行为分析

一旦你引入了spring-boot-starter-security依赖并启动Spring Boot应用,Spring Security会自动生效,并提供以下默认行为:

  1. 全局拦截: 所有HTTP请求默认都会被Spring Security拦截。
  2. 默认登录页: 如果用户未经认证就访问受保护资源,Spring Security会自动跳转到一个默认生成的登录页面 (/login)。
  3. 默认用户: 自动创建一个用户名为 user、密码随机生成的内存用户。这个密码会在应用启动时打印在控制台。
  4. 基本认证: 默认提供基于表单的登录功能。
  5. CSRF防护: 默认开启跨站请求伪造 (CSRF) 防护。
  6. 会话管理: 基于HTTP Session,默认提供会话固定攻击防护。

这些默认行为对于快速上手和测试非常方便,但在生产环境中,我们通常需要进行大量的定制。

4. Spring Security 6.x+ 核心配置:SecurityFilterChain

随着Spring Frameowrk 6和Spring Boot 3的发布,Spring Security也迎来了重大更新,其中一个主要变化就是 WebSecurityConfigurerAdapter 被弃用。现在,我们推荐使用配置SecurityFilterChain Bean的方式来定义安全规则。

4.1 告别 WebSecurityConfigurerAdapter

在Spring Security 5.x及更早版本中,我们通常会创建一个类继承WebSecurityConfigurerAdapter并重写configure()方法来配置Spring Security。

// Spring Security 5.x 及更早版本,现在已弃用!
@Configuration
@EnableWebSecurity
public class OldSecurityConfig extends WebSecurityConfigurerAdapter {@Overrideprotected void configure(HttpSecurity http) throws Exception {http.authorizeRequests().antMatchers("/public/**").permitAll().anyRequest().authenticated().and().formLogin();}// ... 其他配置
}

现在,这种方式已经不再推荐。 请务必使用新的配置方式。

4.2 定义 SecurityFilterChain Bean

在Spring Security 6.x+ 中,你需要在配置类中定义一个或多个SecurityFilterChain类型的@Bean

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.web.SecurityFilterChain;@Configuration
@EnableWebSecurity // 启用Spring Security的Web安全功能
public class CustomSecurityConfig {@Beanpublic SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {http.authorizeHttpRequests(authorize -> authorize.anyRequest().authenticated() // 默认所有请求都需要认证).formLogin(form -> form // 开启表单登录.permitAll() // 允许所有用户访问登录页).httpBasic(org.springframework.security.config.Customizer.withDefaults()); // 开启HTTP Basic认证return http.build();}
}
  • @Configuration 标识这是一个Spring配置类。
  • @EnableWebSecurity 启用Spring Security的Web安全功能。
  • securityFilterChain(HttpSecurity http) 方法返回一个SecurityFilterChain对象,Spring Security将使用这个Bean来构建安全过滤器链。
  • HttpSecurity 对象提供了链式API,用于配置各种安全特性,例如:
    • authorizeHttpRequests():配置授权规则。
    • formLogin():配置表单登录。
    • httpBasic():配置HTTP Basic认证。
    • csrf():配置CSRF防护。
    • logout():配置登出功能。

5. 用户管理初窥:UserDetailsService 与 PasswordEncoder

即使是默认行为,Spring Security也离不开用户详情服务密码编码器

5.1 UserDetailsService:加载用户详情

UserDetailsService 是一个核心接口,负责根据用户名获取用户的详细信息(如用户名、密码、角色/权限等)。它返回一个UserDetails对象。

  • UserDetails接口: 代表一个已认证用户的主要信息,包括用户名 (username)、密码 (password)、权限列表 (authorities),以及账户是否过期、是否被锁定、凭证是否过期、是否启用等状态。
// UserDetails 接口的主要方法
public interface UserDetails extends Serializable {Collection<? extends GrantedAuthority> getAuthorities(); // 获取用户的权限列表String getPassword(); // 获取用户密码String getUsername(); // 获取用户名boolean isAccountNonExpired(); // 账户是否未过期boolean isAccountNonLocked(); // 账户是否未锁定boolean isCredentialsNonExpired(); // 凭证是否未过期boolean isEnabled(); // 账户是否启用
}

在默认情况下,Spring Security提供了一个内存实现,如果你不配置任何UserDetailsService,它会自动创建一个内存用户。

5.2 PasswordEncoder:密码加密的守护者

密码加密是认证环节中至关重要的一环! 永远不要以明文形式存储或比较密码。PasswordEncoder接口定义了密码的编码和匹配方法。

  • encode(charSequence rawPassword) 对原始密码进行编码。
  • matches(charSequence rawPassword, String encodedPassword) 比较原始密码与编码后的密码是否匹配。

Spring Security 推荐使用BCryptPasswordEncoder。它使用BCrypt强哈希函数,对密码进行单向加密,并且每次加密的结果都会不同(因为加入了随机盐值),大大增加了破解难度。

重要提示:

  • 不要使用NoOpPasswordEncoder(不进行任何加密),它仅为测试目的而存在,并且Spring Security 6.x+ 已经强制要求必须配置一个PasswordEncoder
  • Spring Security 5.x 及更早版本如果使用内存用户并且不配置PasswordEncoder,可以通过User.withDefaultPasswordEncoder()来快速创建用户,但那仅仅是为了快速演示,生产环境严禁使用!
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; // 导入BCryptPasswordEncoder
import org.springframework.security.crypto.password.PasswordEncoder;@Configuration
public class PasswordEncoderConfig {@Beanpublic PasswordEncoder passwordEncoder() {return new BCryptPasswordEncoder(); // 推荐使用BCryptPasswordEncoder}
}

6. 实战演练:配置内存用户与基础访问控制

现在,让我们亲手实践,创建一个Spring Boot Web项目,并逐步配置Spring Security。

6.1 创建Spring Boot项目

使用Spring Initializr (https://start.spring.io/) 创建一个新项目,选择以下依赖:

  • Spring Boot Version: 3.2.5 (或最新稳定版)
  • Dependencies: Spring Web, Spring Security

6.2 默认行为体验

  1. 创建项目后,不添加任何安全配置类,直接运行main方法。
  2. 观察控制台输出,你会看到类似如下的信息,其中包含一个随机生成的密码:

在这里插入图片描述

  1. 打开浏览器访问 http://localhost:8080/,Spring Security会重定向到默认的登录页 http://localhost:8080/login

在这里插入图片描述

  1. 使用默认用户名 user 和控制台打印的密码进行登录。登录成功后,你会回到之前尝试访问的页面。

6.3 配置内存用户

接下来,我们将在内存中配置一个自定义用户,并移除默认生成的随机密码。

CustomSecurityConfig.java (替换掉之前简单的SecurityFilterChain配置)

package com.example.springsecuritystage1.config;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.Customizer;
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.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.web.SecurityFilterChain;@Configuration
@EnableWebSecurity
public class CustomSecurityConfig {// 配置密码编码器,让Spring Security知道如何加密和验证密码@Beanpublic PasswordEncoder passwordEncoder() {// BCryptPasswordEncoder是Spring Security推荐的密码编码器return new BCryptPasswordEncoder();}// 配置内存用户@Beanpublic UserDetailsService userDetailsService(PasswordEncoder passwordEncoder) {// 创建一个普通用户UserDetails user = User.builder().username("user").password(passwordEncoder.encode("password")) // 使用编码器对密码进行加密.roles("USER") // 分配USER角色.build();// 创建一个管理员用户UserDetails admin = User.builder().username("admin").password(passwordEncoder.encode("adminpass")).roles("ADMIN", "USER") // 分配ADMIN和USER角色.build();// 将这些用户配置到内存中return new InMemoryUserDetailsManager(user, admin);}// 配置安全过滤器链@Beanpublic SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {http.authorizeHttpRequests(authorize -> authorize.requestMatchers("/public/**").permitAll() // 允许/public/**路径下的所有请求.requestMatchers("/admin/**").hasRole("ADMIN") // 只有ADMIN角色可以访问/admin/**.anyRequest().authenticated() // 其他所有请求都需要认证).formLogin(Customizer.withDefaults()) // 开启表单登录,使用默认配置.httpBasic(Customizer.withDefaults()); // 开启HTTP Basic认证,使用默认配置return http.build();}
}

为了测试,我们还需要一些Controller:

HelloController.java

package com.example.springsecuritystage1.controller;import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
public class HelloController {@GetMapping("/")public String home() {return "Welcome to the home page!";}@GetMapping("/public")public String publicPage() {return "This is a public page, accessible to everyone.";}@GetMapping("/user/profile")public String userProfile() {Authentication authentication = SecurityContextHolder.getContext().getAuthentication();String username = authentication != null ? authentication.getName() : "Anonymous";return "Hello, " + username + "! This is your user profile.";}@GetMapping("/admin/dashboard")public String adminDashboard() {return "Welcome to the admin dashboard! Only administrators can see this.";}
}

6.4 定制URL访问权限

根据SecurityFilterChain中的配置:

  • GET /:需要认证。
  • GET /publicpermitAll(),所有人都可以访问,不需要认证。
  • GET /user/profile:需要认证(因为未被明确指定permitAll(),所以符合anyRequest().authenticated())。useradmin都可以访问。
  • GET /admin/dashboardhasRole("ADMIN"),只有拥有ADMIN角色的用户才能访问。user用户无权访问,admin用户可以访问。

测试步骤:

  1. 启动应用。
  2. 访问 http://localhost:8080/public:直接显示“This is a public page, accessible to everyone.”,无需登录。
  3. 访问 http://localhost:8080/http://localhost:8080/user/profile:会重定向到登录页。
    • 使用 user/password 登录,可以成功访问 /user/profile,但访问 /admin/dashboard 会显示403 Forbidden。
    • 使用 admin/adminpass 登录,可以成功访问 /user/profile/admin/dashboard
  4. 访问 /admin/dashboard 时,如果你以 user 身份登录,你会得到一个 403 Forbidden 响应,表明授权失败。

7. 进一步定制:禁用默认登录页与基础CSRF防护

有些场景下,我们可能不希望使用Spring Security提供的默认登录页,而是希望提供自己的自定义登录页(例如使用React、Vue等前端框架,或者自定义Thymeleaf页面)。

同时,对CSRF防护的默认开启也要有所了解。

package com.example.springsecuritystage1.config;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.Customizer;
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.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.web.SecurityFilterChain;@Configuration
@EnableWebSecurity
public class CustomSecurityConfig {@Beanpublic PasswordEncoder passwordEncoder() {return new BCryptPasswordEncoder();}@Beanpublic UserDetailsService userDetailsService(PasswordEncoder passwordEncoder) {UserDetails user = User.builder().username("user").password(passwordEncoder.encode("password")).roles("USER").build();UserDetails admin = User.builder().username("admin").password(passwordEncoder.encode("adminpass")).roles("ADMIN", "USER").build();return new InMemoryUserDetailsManager(user, admin);}@Beanpublic SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {http.authorizeHttpRequests(authorize -> authorize.requestMatchers("/public/**", "/login").permitAll() // 允许/public/** 和 /login 所有请求.requestMatchers("/admin/**").hasRole("ADMIN").anyRequest().authenticated()).formLogin(form -> form // 开启表单登录.loginPage("/login")        // 指定自定义登录页的URL.defaultSuccessUrl("/user/profile", true) // 登录成功后默认跳转的URL.permitAll() // 允许所有用户访问自定义登录页)// CSRF防护默认是开启的,如果你的前端是传统的表单提交,需要注意在表单中包含CSRF令牌。// 例如:<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" />// 如果是纯API项目,考虑禁用CSRF,但这通常在JWT或OAuth2阶段进行// .csrf(csrf -> csrf.disable()) // 禁用CSRF,非必要不要禁用,生产环境需谨慎.httpBasic(Customizer.withDefaults()); // 开启HTTP Basic认证return http.build();}
}

再添加一个Controller来渲染自定义的登录页(如果你是前后端分离,此部分可能由前端框架完成):
LoginController.java

package com.example.springsecuritystage1.controller;import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;@Controller
public class LoginController {@GetMapping("/login")public String login() {return "login"; // 返回名为 "login" 的视图(例如login.html),确保你在resources/templates目录下有此文件}
}

并在 src/main/resources/templates 目录下创建一个 login.html (使用Thymeleaf为例):

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head><meta charset="UTF-8"><title>Custom Login</title><style>body { font-family: Arial, sans-serif; display: flex; justify-content: center; align-items: center; height: 100vh; background-color: #f4f4f4; }.login-container { background-color: #fff; padding: 20px; border-radius: 8px; box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); }h2 { text-align: center; color: #333; }label { display: block; margin-bottom: 8px; color: #555; }input[type="text"], input[type="password"] { width: calc(100% - 20px); padding: 10px; margin-bottom: 15px; border: 1px solid #ddd; border-radius: 4px; }input[type="submit"] { width: 100%; padding: 10px; background-color: #007bff; color: white; border: none; border-radius: 4px; cursor: pointer; font-size: 16px; }input[type="submit"]:hover { background-color: #0056b3; }.error-message { color: red; text-align: center; margin-bottom: 15px; }</style>
</head>
<body><div class="login-container"><h2>Custom Login Page</h2><!-- 登录失败信息 --><div th:if="${param.error}" class="error-message">Invalid username or password.</div><!-- 登出成功信息 (可选) --><div th:if="${param.logout}" class="error-message" style="color: green;">You have been logged out.</div><form th:action="@{/login}" method="post"><div><label for="username">Username:</label><input type="text" id="username" name="username" required/></div><div><label for="password">Password:</label><input type="password" id="password" name="password" required/></div><!-- CSRF token 默认开启时非常重要,保护你的FORM表单 --><input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}" /><div><input type="submit" value="Log In"/></div></form></div>
</body>
</html>
  • loginPage("/login"):告诉Spring Security,登录页的URL是 /login
  • defaultSuccessUrl("/user/profile", true):登录成功后,强制跳转到 /user/profile。如果不加true,则会跳转到用户登录前访问的页面。
  • requestMatchers("/login").permitAll():确保自定义的登录页(/login)可以被所有人访问,否则会陷入重定向循环。
  • th:if="${param.error}"th:if="${param.logout}"用于显示Spring Security在登录失败或成功登出后在URL中添加的参数信息。
  • CSRF Tokenth:name="${_csrf.parameterName}" th:value="${_csrf.token}"这行代码至关重要。当CSRF防护默认开启时,Spring Security要求所有POST请求(包括登录表单提交)必须携带一个有效的CSRF Token。Thymeleaf会从SecurityContext中自动获取并填充这个Token。如果你在生产环境中禁用了CSRF,则应移除此行,但生产环境禁用CSRF需极其谨慎,通常只在无状态的REST API中使用。

8. 常见陷阱与注意事项

  • Spring Security 6.x+ 配置迁移: 务必适应新的SecurityFilterChain配置方式,避免使用已弃用的WebSecurityConfigurerAdapter
  • 密码编码器 (PasswordEncoder): 生产环境必须使用安全的密码编码器,如BCryptPasswordEncoder。永远不要使用NoOpPasswordEncoder
  • permitAll() 的滥用: 只有确实不需要认证的资源才使用permitAll()。例如,静态资源、登录页、注册页等。对其他资源,应保持authenticated()或更严格的权限控制。
  • 默认密码: 默认生成的密码只用于快速启动体验,请勿在生产环境中使用。通过UserDetailsService配置自定义用户。
  • CSRF防护: 默认开启且强烈建议保持开启,尤其对于传统的Web应用。对于RESTful API,如果采用JWT等无状态认证机制,通常会禁用CSRF,但需确保理解其安全影响。
  • 依赖冲突: 确保spring-boot-starter-security版本与你的Spring Boot版本兼容。

9. 阶段总结与进阶展望

恭喜你完成了Spring Security深度学习的第一阶段!通过本阶段的学习,你已经掌握了:

  • 认证与授权的核心概念,以及SecurityContext的作用。
  • 如何在Spring Boot项目中快速集成Spring Security。
  • 分析Spring Security的默认行为,包括登录页、默认用户和访问控制。
  • 使用Spring Security 6.x+ 的SecurityFilterChain配置方式。
  • 配置内存用户并使用BCryptPasswordEncoder进行密码加密。
  • 定制URL级别的访问权限,并初步了解CSRF防护。

你现在应该能够搭建一个基础的Spring Security保护的Web应用。然而,这仅仅是开始。在接下来的阶段,我们将深入探索更复杂的认证机制(如数据库用户认证)、更细粒度的授权管理、会话管理、JWT以及微服务安全等高级主题。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/pingmian/94490.shtml
繁体地址,请注明出处:http://hk.pswp.cn/pingmian/94490.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数学建模--模糊综合评价法

一、概念 模糊综合评价法是一种基于模糊数学的综合评价方法。它针对评价过程中存在的模糊性&#xff08;如 “好”“较好”“差” 等模糊概念&#xff09;&#xff0c;通过建立模糊集合&#xff0c;将定性评价转化为定量评价&#xff0c;从而对具有多种属性的评价对象做出全面、…

科普 | 5G支持的WWC架构是个啥(2)?

为解决有线固定宽带与无线移动宽带融合问题&#xff0c;3GPP在5G中推出了WWC系统架构。它将两种接入类型统一融合到5G核心网络。这有助于运营商简化控制、简化管理并为终端用户提供一致服务&#xff1b;其中&#xff1a;一、5G核心组件包括&#xff1a;AMF(接入和移动性管理功能…

达梦数据库配置文件-COMPATIBLE_MODE

达梦数据库配置文件-COMPATIBLE_MODE 获取系统参数 SQL 语句: select distinct para_type from v$dm_ini;这句的意思是:从达梦数据库的参数视图 v$dm_ini 中,查询所有不同类型的参数分类(去重)。 ✅ 输出结果解析 行号 PARA_TYPE ---------- --------- 1 RE…

能源行业数据库远程运维安全合规实践:Web化平台的落地经验

背景&#xff1a;远程运维下的数据管理挑战在能源行业&#xff0c;企业通常在全国范围内部署分布式设施。每个电站或运维中心都有独立数据库&#xff0c;用于&#xff1a;记录设备状态、传感器数据和维护日志&#xff1b;存储实时生产指标和能耗统计&#xff1b;生成定期运维报…

数据结构Java--8

二叉搜索树像上图这样满足&#xff0c;任意一棵子树的左子树小于该子树的根结点&#xff0c;右子树大于该子树的根结点&#xff0c;满足这样的条件&#xff0c;则这种树就被称为二叉搜索树。public class BinarySearchTree {static class TreeNode {public int val;public Tree…

使用Spring Boot和EasyExcel导出Excel文件,并在前端使用Axios进行请求

在现代企业应用中&#xff0c;Excel文件的导出是一项常见且重要的功能。Spring Boot作为Java开发中的热门框架&#xff0c;结合EasyExcel这样的高效库&#xff0c;能够轻松实现Excel的导出功能。而在前端&#xff0c;使用Axios进行HTTP请求&#xff0c;可以方便地与后端进行数据…

图论水题5

cf796D 题意 n个点n-1条边&#xff0c;k个特殊点以及整数d&#xff0c;要求删除最多的边保证每个点都可以在d步之内到达一个特殊点&#xff0c;输入保证每个点都可以在d步内到达特殊点 思路 考虑什么时候可以删除一条边&#xff0c;即这条边连接的两个点可以在d步内到达两个不同…

像WPS Office 一样处理pdf页面尺寸

1. 修改页面尺寸import os import shutil import fitz # PyMuPDFdef cm_to_px(cm):# 厘米转换成像素"""doc fitz.open(input_file)page0 doc[0]width_px page0.mediabox.widthheight page0.mediabox.heightprint(fwidth_px&#xff1a;{width_px} height&a…

Linux 基础开发工具

在 Linux 环境下进行开发&#xff0c;熟练掌握基础工具是提升效率、解决问题的核心前提。无论是软件安装、代码编辑&#xff0c;还是编译调试、版本管理&#xff0c;一套 “趁手” 的工具链能让开发过程事半功倍。本文将从 Linux 开发最核心的七大工具模块入手&#xff0c;一步…

TapData vs Kafka ETL Pipeline:竞争?共存?——企业实时数据策略的正确打开方式

【引言】企业实时数据流转&#xff0c;迎来“集成计算”新范式 企业 IT 架构的演进&#xff0c;从最初的数据孤岛&#xff0c;到集中式数据仓库&#xff0c;再到如今的实时数据驱动架构。在这一过程中&#xff0c;数据的集成&#xff08;数据源→目标&#xff09;与数据的计算&…

十九、云原生分布式存储 CubeFS

十九、云原生分布式存储 CubeFS 文章目录十九、云原生分布式存储 CubeFS1、分布式存储初识1.1 分布式存储主要特性1.2 为什么要在K8s上落地存储平台1.3 云原生存储平台CubeFS介绍1.4 分布式存储平台落地架构1.4.1 混合部署1.4.2 独立部署-基础设施集群1.5 资源分配建议1.6 硬件…

如何拯救一家濒临破产的科技公司?

从谷底爬起&#xff1a;Medium 的生死重生之路 2022年的 Medium&#xff0c;正坠入一个深不见底的深渊。 每月亏损260万美元&#xff0c;订阅用户持续流失——这不是增长&#xff0c;而是在消耗资本。更致命的是内容质量&#xff1a;平台充斥着“快速致富学”等空洞内容&#x…

数据结构-算法(一)

一、已知无向图的邻接矩阵&#xff0c;求无向图的邻接表。 &#xff08;1&#xff09;提示&#xff1a;无向图如下图(a)所示&#xff0c;已知邻接矩阵如图(b)所示&#xff0c;求对应的邻接表(c)。&#xff08;2&#xff09;请定义void adjMatrix_2_adjList(int b[4][4], AdjLis…

2025年嵌入式通信电源系统品牌有哪些?

现在科技跑得飞快&#xff0c;嵌入式通信电源系统可是越来越吃香了&#xff0c;尤其是在5G、物联网、智能家居这些热门地方。这玩意儿不光能让设备稳稳当当干活儿&#xff0c;还特省电、贼聪明&#xff0c;优势杠杠的&#xff01;既然大家伙儿都这么需要它&#xff0c;那到了20…

Ubuntu24.04环境下causal_conv1d和mamba_ssm安装

环境&#xff1a;WSL的Ubuntu24.041.创建conda环境&#xff0c;其中python版本为3.10.132.当前conda环境依次执行下面命令&#xff1a;conda install cudatoolkit11.8 -c nvidia pip install torch2.1.1 torchvision0.16.1 torchaudio2.1.1 -f https://mirrors.aliyun.com/pyto…

Python爬虫实战: 爬虫常用到的技术及方案详解

爬虫是获取网络数据的重要工具,Python因其丰富的库生态系统而成为爬虫开发的首选语言。下面我将详细介绍Python爬虫的常用技术和方案。 一、基础技术栈 1. 请求库 Requests - 同步HTTP请求库 import requests# 基本GET请求 response = requests.get(https://httpbin.org/g…

k8s——持久化存储 PVC

目录 k8s持久化存储&#xff1a; PVC 1 k8s PV是什么&#xff1f; 2 k8s PVC是什么&#xff1f; 3 k8s PVC和PV工作原理 4 创建pod&#xff0c;使用pvc作为持久化存储卷 ​三种回收策略详解​ 1、创建nfs共享目录 2、如何编写pv的资源清单文件 3、创建pv 更新资源清单文…

【系统架构设计师】数据库设计(一):数据库技术的发展、数据模型、数据库管理系统、数据库三级模式

数据库技术是研究数据库的结构、存储、设计、管理和应用的一门软件学科。 数据库系统本质上是一个用计算机存储信息的系统。 数据库管理系统是位于用户与操作系统之间的一层数据管理软件&#xff0c;其基本目标是提供一个可以方便、有效地存取数据库信息的环境。 数据库就是信息…

深入理解 Structured Outputs:基于 JSON Schema 的结构化输出实践指南

深入理解 Structured Outputs&#xff1a;基于 JSON Schema 的结构化输出实践指南 目录 引言Structured Outputs 概述应用场景与优势核心用法&#xff1a;结构化响应的获取功能对比&#xff1a;Structured Outputs 与 JSON 模式典型应用示例链式思维&#xff08;Chain of Tho…