如何将OAuth2客户端与Spring Authorization Server打包为单应用
你之前复制login应用(Web OAuth2客户端)的配置到授权服务器中导致授权码流失效,核心原因是你的场景不需要额外的Web客户端,而是要让同一应用同时承担OAuth2授权服务器和资源服务器的角色,直接对接Android客户端。以下是正确的实现步骤和框架建议:
一、正确整合授权服务器与资源服务器
1. 依赖配置
在项目的pom.xml(Maven)或build.gradle(Gradle)中引入必要的starter,无需额外的OAuth2客户端依赖:
<!-- Spring Authorization Server --> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-oauth2-authorization-server</artifactId> </dependency> <!-- 资源服务器(保护API接口) --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-oauth2-resource-server</artifactId> </dependency> <!-- Spring Security核心依赖 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency>
2. 授权服务器配置
创建配置类,为你的Android客户端注册授权信息:
@Configuration @EnableAuthorizationServer public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter { @Autowired private AuthenticationManager authenticationManager; @Override public void configure(ClientDetailsServiceConfigurer clients) throws Exception { clients.inMemory() // 为Android客户端分配唯一标识 .withClient("android-first-party") // 客户端密钥,生产环境需用BCrypt加密 .secret("{noop}android-secret-123") // 启用授权码模式和刷新令牌模式 .authorizedGrantTypes("authorization_code", "refresh_token") // 客户端可访问的资源范围 .scopes("api:read", "api:write") // Android应用的回调URI,需和Android端配置一致 .redirectUris("com.your.android.app://oauth2/callback") // 第一方应用可自动批准授权,无需用户手动确认 .autoApprove(true); } @Override public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { endpoints.authenticationManager(authenticationManager); } }
3. 资源服务器配置
配置资源服务器的令牌验证逻辑,保护你的API接口:
@Configuration @EnableResourceServer public class ResourceServerConfig extends ResourceServerConfigurerAdapter { @Override public void configure(HttpSecurity http) throws Exception { http.authorizeRequests() // 开放OAuth2相关端点,允许客户端访问 .antMatchers("/oauth/**").permitAll() // 所有API接口需认证后访问 .anyRequest().authenticated(); } @Override public void configure(ResourceServerSecurityConfigurer resources) throws Exception { resources.resourceId("backend-api") .tokenServices(tokenServices()); } @Bean public DefaultTokenServices tokenServices() { DefaultTokenServices tokenServices = new DefaultTokenServices(); tokenServices.setTokenStore(tokenStore()); return tokenServices; } @Bean public TokenStore tokenStore() { // 开发阶段用内存存储,生产环境建议改用JdbcTokenStore或JWT令牌 return new InMemoryTokenStore(); } }
4. 用户认证配置
配置用户账号信息,可对接数据库或内存用户:
@Configuration public class SecurityConfig extends WebSecurityConfigurerAdapter { // 暴露AuthenticationManager给授权服务器使用 @Override @Bean public AuthenticationManager authenticationManagerBean() throws Exception { return super.authenticationManagerBean(); } @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { // 开发阶段用内存用户,生产环境替换为数据库认证 auth.inMemoryAuthentication() .withUser("test-user") .password("{noop}test-pass") .roles("USER"); } }
配置完成后,Android客户端即可按授权码流流程与该应用交互:
- 跳转至应用的
/oauth/authorize端点完成用户登录 - 登录成功后回调Android应用,获取授权码
- 携带授权码调用
/oauth/token端点换取访问令牌 - 用访问令牌调用后端API接口
二、替代框架建议
如果觉得Spring Authorization Server配置繁琐,针对第一方Android应用,可考虑以下轻量化方案:
- Spring Security OAuth2(旧版):配置比新版Authorization Server更简洁,适合快速搭建,虽已进入维护模式,但小型应用完全够用。
- JWT直接认证:跳过完整OAuth2流程,用户登录后返回JWT令牌,后续请求携带JWT验证,实现简单、资源消耗低。
- 嵌入式Keycloak:将Keycloak嵌入Spring Boot应用,作为内置授权服务器,提供可视化配置界面,无需自行编写大量授权逻辑。
内容的提问来源于stack exchange,提问作者DevDengChao
合著者:他10个月大的女儿
相关产品推荐
相关产品推荐

