Spring Boot 整合 OAuth2 Authorization Server 的核心在于把授权服务器过滤链和普通的资源服务器过滤链分开注册,同时正确提供客户端仓库和用户详情服务。很多第一次配置的开发者会把两个安全过滤链的顺序写反,或者漏掉 clientSecret 的编码规则,导致授权端点直接返回 401 或 404。

本文基于 Spring Security 的 DSL 配置方式,从依赖引入到令牌获取完整走一遍。所有配置均以 Java 代码为主,不涉及 XML,适合已经会用 Spring Boot 基础安全配置的读者。读完可以快速在本地搭建一个可运行的授权码模式授权服务器,并理解每个环节的作用。
一、引入依赖与最小化配置
首先在 pom.xml 中添加官方 starter。这个 starter 封装了 Spring Authorization Server 的核心自动配置,版本由 Spring Boot 父工程统一管理,不需要手动指定具体版本号。依赖声明如下:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-authorization-server</artifactId>
</dependency>
引入依赖后,项目会具备授权服务器的基础设施,但并不会自动注册任何客户端或用户。至少需要提供一个 RegisteredClientRepository 和一个 UserDetailsService,否则启动时会报缺少 Bean 的错误。另一个容易忽略的点是密码编码器:在测试环境可以用 {noop}secret 这种前缀表示明文密码,但生产环境必须替换为 BCrypt 等强编码。
application.yml 中只需配置服务端口即可,授权服务器不会自动开放任何端点。真正的端点暴露和访问控制都通过 SecurityFilterChain 完成。这种设计让授权端点和资源端点可以独立配置,不必把所有规则塞进一个链里。
二、注册客户端与用户信息
客户端信息决定哪些外部系统可以发起授权流程。创建配置类并提供 RegisteredClientRepository 的 Bean,测试阶段使用内存实现足够。每个客户端需要指定 clientId、clientSecret、授权模式、回调地址和作用域,其中 clientSecret 必须与全局 PasswordEncoder 的规则一致。下面是一个完整的注册示例:
@Bean
public RegisteredClientRepository registeredClientRepository() {
RegisteredClient registeredClient = RegisteredClient.withId(UUID.randomUUID().toString())
.clientId("demo-client")
.clientSecret("{noop}secret")
.clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC)
.authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)
.authorizationGrantType(AuthorizationGrantType.REFRESH_TOKEN)
.redirectUri("http://127.0.0.1:8080/login/oauth2/code/demo-client")
.scope("openid")
.scope("profile")
.build();
return new InMemoryRegisteredClientRepository(registeredClient);
}
这里的 redirectUri 必须和后续测试时浏览器跳转的地址完全一致,否则授权服务器会拒绝回调。授权码模式通常还会加上 REFRESH_TOKEN 授权类型,方便客户端在访问令牌过期后刷新。
用户信息对应的是登录表单里输入的用户名和密码。同样使用内存实现,示例如下:
@Bean
public UserDetailsService userDetailsService() {
UserDetails user = User.withUsername("admin")
.password("{noop}admin")
.roles("USER")
.build();
return new InMemoryUserDetailsManager(user);
}
这两个 Bean 的意义不同:RegisteredClientRepository 用于校验发起授权请求的客户端身份,UserDetailsService 用于校验最终用户在登录页输入的凭据。二者在授权码流程中分别承担不同的认证步骤。
三、授权端点与令牌生成策略
授权服务器的端点需要通过 OAuth2AuthorizationServerConfigurer 显式启用,并放在独立的过滤链中,优先级为最高。这样做的原因是授权服务器端点必须优先于普通表单登录,否则 /oauth2/authorize 等地址会被通用安全规则拦截。典型配置如下:
@Bean
@Order(1)
public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
OAuth2AuthorizationServerConfigurer authorizationServer = OAuth2AuthorizationServerConfigurer.authorizationServer();
http
.securityMatcher(authorizationServer.getEndpointsMatcher())
.with(authorizationServer, authServer ->
authServer
.oidc(Customizer.withDefaults())
)
.authorizeHttpRequests(authorize ->
authorize.anyRequest().authenticated()
)
.formLogin(Customizer.withDefaults());
return http.build();
}
同时还需要一个优先级较低的过滤链来处理其他请求,避免所有访问都被授权服务器规则管理。最简单的做法是对非授权端点启用基于表单的认证,后续再逐步替换为资源服务器配置。
@Bean
@Order(2)
public SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(authorize ->
authorize.anyRequest().authenticated()
)
.formLogin(Customizer.withDefaults());
return http.build();
}
令牌生成方面,Spring Authorization Server 默认使用内存中的 RSA 密钥对并对 JWT 签名,不需要额外配置即可工作。但如果希望在多次重启后保持签名稳定,需要提供自己的 JWKSource 并持久化密钥。测试环境可以忽略这个问题,因为重启后客户端会重新获取新的令牌,不影响功能验证。
四、运行测试与常见问题
启动项目后,打开浏览器访问授权端点,URL 中包含 response_type、client_id、redirect_uri 和 scope 参数。例如:
http://localhost:8080/oauth2/authorize?response_type=code&client_id=demo-client&redirect_uri=http://127.0.0.1:8080/login/oauth2/code/demo-client&scope=openid
浏览器会先跳转到登录页,输入 admin/admin 后进入授权确认页,点击授权后携带 code 跳回 redirect_uri。拿到 code 后,可以用 curl 向令牌端点换取 access_token:
curl -u demo-client:secret -X POST http://localhost:8080/oauth2/token \ -d "grant_type=authorization_code&code=替换为实际code&redirect_uri=http://127.0.0.1:8080/login/oauth2/code/demo-client"
常见问题主要集中在三个方面。第一是授权端点 404,基本是过滤链顺序错误或者没有使用 securityMatcher 限定授权服务器端点。第二是客户端认证失败,检查 clientSecret 是否和全局 PasswordEncoder 规则一致,测试阶段可保留 {noop} 前缀。第三是 JWT 签名不稳定,每次重启造成已签发令牌无法验证,这是内存密钥的正常表现,配置持久化 JWKSource 即可解决。理清这些问题后,授权服务器就能稳定支持后续的微服务接入。
Spring BootOAuth2授权服务器修改时间:2026-10-04 10:04:02