Spring Security 7: MFA, Modular Config, and What Breaks
Spring Security 7: MFA, Modular Config, and What Breaks
Spring Security 7 dropped at Spring I/O 2026. Daniel Erno from the Spring Security team gave a talk covering the biggest changes. Here’s what matters if you’re building Java apps with Spring Boot. Spring Security 7 在 Spring I/O 2026 大会上正式发布。来自 Spring Security 团队的 Daniel Erno 发表了演讲,涵盖了此次版本更新中的重大变更。如果你正在使用 Spring Boot 构建 Java 应用,以下内容至关重要。
Multi-Factor Authentication (MFA) — The Big One
多因素身份验证 (MFA) —— 重头戏
This feature was requested 12 years ago (issue #2603, opened November 2013). It finally shipped. What it does: You can now enforce MFA at the application level or per-endpoint. Spring Security tracks which authentication factors each user has completed and when they authenticated. 这项功能早在 12 年前(2013 年 11 月开启的 issue #2603)就被提出,如今终于正式上线。它的作用是:你现在可以在应用级别或针对特定端点强制执行 MFA。Spring Security 会追踪每个用户已完成的身份验证因素以及他们的验证时间。
Key classes: 核心类包括:
FactorGrantedAuthority— records what factor you used (password, one-time token, etc.) and when you used itFactorGrantedAuthority— 记录你使用的验证因素(密码、一次性令牌等)及其使用时间@EnableMultiFactorAuthentication— enables MFA across your app@EnableMultiFactorAuthentication— 在整个应用中启用 MFAAllRequiredFactorsAuthorizationManager— combine multiple MFA rulesAllRequiredFactorsAuthorizationManager— 组合多种 MFA 规则
Site-wide MFA example: 全站 MFA 示例:
@EnableMultiFactorAuthentication(authorities = {
FactorGrantedAuthority.PASSWORD_AUTHORITY,
FactorGrantedAuthority.OTT_AUTHORITY
})
Now every protected endpoint requires both password login AND a one-time token. 现在,每个受保护的端点都需要同时通过密码登录和一次性令牌验证。
Per-endpoint MFA (more practical): 针对特定端点的 MFA(更具实用性):
@Bean
SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
var mfa = new AllRequiredFactorsAuthorizationManager.Builder()
.requiredFactor(FactorGrantedAuthority.PASSWORD_AUTHORITY)
.requiredFactor(FactorGrantedAuthority.OTT_AUTHORITY)
.build();
http.authorizeHttpRequests(authZ -> authZ
.requestMatchers("/public.html").permitAll()
.requestMatchers("/admin.html").access(mfa.hasRole("admin"))
.anyRequest().authenticated()
);
return http.build();
}
Time-based rules: You can require that an authentication is recent. For example, force users to re-authenticate before changing their password: 基于时间的规则:你可以要求身份验证必须是“近期”的。例如,强制用户在修改密码前重新进行身份验证:
var recentPassword = AllRequiredFactorsAuthorizationManager.builder()
.requiredFactor(FactorGrantedAuthority.PASSWORD_AUTHORITY, Duration.ofMinutes(5))
.build();
http.authorizeHttpRequests(authZ -> authZ.requestMatchers("/change-password")
.access(recentPassword)
);
If a user logged in 30 minutes ago, they get redirected back to login before accessing the password change page. 如果用户是在 30 分钟前登录的,他们在访问密码修改页面前会被重定向回登录界面。
Why this matters: Before Spring Security 7, you had to implement MFA yourself or use a third-party library. Now it’s built into the framework. 为何重要:在 Spring Security 7 之前,你必须自行实现 MFA 或使用第三方库。现在,它已内置于框架中。
Modular Configuration — Stop Replacing Boot Defaults
模块化配置 —— 不再需要覆盖 Boot 默认设置
The old problem: When you created a SecurityFilterChain bean, you replaced Spring Boot’s entire security configuration. You had to manually add form login, session management, CSRF protection, and OAuth2 defaults. Miss one, and your app breaks.
旧问题:当你创建一个 SecurityFilterChain bean 时,你会替换掉 Spring Boot 的整个安全配置。你必须手动添加表单登录、会话管理、CSRF 保护和 OAuth2 默认设置。漏掉任何一个,应用就会出错。
The new way: Instead of a full SecurityFilterChain bean, provide a customizer that changes only what you need:
新方式:不再需要完整的 SecurityFilterChain bean,只需提供一个仅修改必要部分的定制器(Customizer):
// NEW: keeps Boot defaults, only changes what you need
@Bean
Customizer<HttpSecurity> httpSecurityCustomizer() {
return http -> http.authorizeHttpRequests(authZ -> authZ.requestMatchers("/public.html").permitAll() );
}
Spring Boot’s form login, CSRF, session management, and OAuth2 Authorization Server defaults stay intact. You only customize the parts you change. Spring Boot 的表单登录、CSRF、会话管理和 OAuth2 授权服务器默认设置将保持不变。你只需定制你想要修改的部分。
Targeted customizers: You can also customize specific configurers without touching the full HTTP security: 针对性定制:你还可以定制特定的配置器,而无需触及完整的 HTTP 安全配置:
@Bean
Customizer<OAuth2AuthorizationServerConfigurer> authServerCustomizer() {
return authz -> authz.oidc(oidc -> oidc.providerConfiguration(pc -> pc.claims(c -> c.claim("conference", "Spring I/O 2026")) ) );
}
This is cleaner. No more SecurityFilterChain beans unless you really need to override everything.
这种方式更简洁。除非你确实需要覆盖所有内容,否则不再需要定义 SecurityFilterChain bean。
What Got Removed
移除的内容
- OAuth2 Password Grant — gone. If you’re using password grant type, migrate to authorization code. The OAuth 2.1 spec calls password grant “legacy.” Spring Security removed it from the client library.
- OAuth2 密码授权模式 — 已移除。如果你正在使用密码授权类型,请迁移到授权码模式。OAuth 2.1 规范已将密码授权称为“遗留”模式。Spring Security 已将其从客户端库中移除。
- and() DSL — gone. The old chain-style configuration with
.and()is removed. Use lambdas instead. Open Rewrite can automate this migration for you. - and() DSL — 已移除。旧的链式配置
.and()已被移除,请改用 Lambda 表达式。Open Rewrite 可以为你自动完成此迁移。 - Module reorganization:
AccessDecisionVoterManagermoved tospring-security-accesspackage. Kerberos and Authorization Server modules now share the same version number (7.x). - 模块重组:
AccessDecisionVoterManager已移动到spring-security-access包中。Kerberos 和 Authorization Server 模块现在共享相同的版本号 (7.x)。
OAuth2 Changes
OAuth2 变更
- PKCE is now the default. The Authorization Server enforces Proof Key for Code Exchange. Clients must send a code challenge. If you have legacy clients that can’t support PKCE, you can turn it off.
- PKCE 现在是默认设置。 授权服务器强制要求使用代码交换证明密钥 (PKCE)。客户端必须发送代码质询。如果你有不支持 PKCE 的遗留客户端,可以将其关闭。
- Dynamic Client Registration. Authorization Servers can now register clients through a REST endpoint (
/oauth2/register). This was added mainly for MCP (Model Context Protocol) support, where AI tools like Claude Desktop need to dynamically register themselves as clients. - 动态客户端注册。 授权服务器现在可以通过 REST 端点 (
/oauth2/register) 注册客户端。此功能主要为了支持 MCP(模型上下文协议),例如 Claude Desktop 等 AI 工具需要动态注册为客户端。
Warning: Don’t open this endpoint without access control. The spec authors recommend authenticated registration, not open registration. Open registration is a denial-of-service risk. 警告:请勿在没有访问控制的情况下开放此端点。规范作者建议使用经过身份验证的注册,而非开放注册。开放注册存在拒绝服务攻击的风险。
HTTP Service Clients with OAuth2
带有 OAuth2 的 HTTP 服务客户端
Spring Framework 7 introduced HTTP Service Clients (declarative, interface-based HTTP clients). Spring Security 7 adds OAuth2 token injection support. Spring Framework 7 引入了 HTTP 服务客户端(声明式、基于接口的 HTTP 客户端)。Spring Security 7 增加了对 OAuth2 令牌注入的支持。