OAuth2 Engine 是一个轻量级、配置驱动的通用 OAuth2 客户端集成库。
它的核心目标是解决第三方平台(GitHub, 微信, 支付宝, 钉钉等)OAuth2 实现标准不统一的问题。通过 Pipeline 机制 和 声明式配置,开发者无需为每个平台编写独立的 Service 或 Util 代码,仅需一份 YAML 配置即可完成接入。
- 声明式接入:通过 YAML 定义授权地址、Token 位置(Header/Query/Body)、字段映射关系,无需编写 Java 代码适配。
- 管道式架构:采用
Merge->PreHook->Execute->PostHook->Map五阶段处理流程,逻辑清晰。 - 高度可扩展:内置 Hook 机制,支持签名、解密等复杂场景(如支付宝签名、微信解密);支持自定义 HTTP 客户端(SPI)。
- 无状态设计:引擎本身无状态,原生支持集群部署与微服务环境。
在 Maven 项目中引入依赖:
<dependency>
<groupId>com.oauth2.engine</groupId>
<artifactId>oauth2-engine-spring-boot-starter</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>| 平台 | Provider ID | 特性说明 |
|---|---|---|
| GitHub | github |
标准 OAuth2 流程 |
| Gitee | gitee |
标准 OAuth2 流程 |
| Baidu | baidu |
非标:Token 接口强制 GET / Token 位于 Query |
以下示例展示了如何配置 标准 OAuth2 (GitHub) 和 非标准 OAuth2 (百度 - GET 请求获取 Token) 两种场景。
spring:
oauth2:
engine:
providers:
# 场景 1:标准 OAuth2 协议 (GitHub)
github:
client-id: ${GITHUB_ID}
client-secret: ${GITHUB_SECRET}
redirect-uri: http://localhost/callback/github
authorize-endpoint:
url: "https://github.com/login/oauth/authorize"
token-endpoint:
url: "https://github.com/login/oauth/access_token"
method: POST
param-location: BODY # 参数在 Body 中提交
user-info-endpoint:
url: "https://api.github.com/user"
token-location: HEADER # Token 放在 Header (Authorization: Bearer ...)
mapping:
response-map: # 统一响应字段映射
id: "$.id"
name: "$.login"
avatar: "$.avatar_url"
# 场景 2:非标准实现 (百度 - Token 接口强制 GET,Token 在 Query 参数中)
baidu:
client-id: ${BAIDU_ID}
client-secret: ${BAIDU_SECRET}
redirect-uri: http://localhost/callback/baidu
authorize-endpoint:
url: "https://openapi.baidu.com/oauth/2.0/authorize"
token-endpoint:
url: "https://openapi.baidu.com/oauth/2.0/token"
method: GET # <--- 差异点:使用 GET
user-info-endpoint:
url: "https://openapi.baidu.com/rest/2.0/passport/users/getInfo"
token-location: QUERY # <--- 差异点:Token 拼在 URL 后
token-param-name: access_token
mapping:
response-map: { id: "$.userid", name: "$.username" }只需注入 OAuth2Engine 即可处理所有已配置的平台。
@RestController
@RequestMapping("/oauth")
public class AuthController {
@Resource
private OAuth2Engine engine;
/**
* 1. 获取授权跳转地址
* @param type 对应配置文件中的 provider key (e.g., "github", "baidu")
*/
@GetMapping("/login/{type}")
public void login(@PathVariable String type, HttpServletResponse response) throws IOException {
String authorizeUrl = engine.getAuthorizeUrl(type);
response.sendRedirect(authorizeUrl);
}
/**
* 2. 统一回调处理
* 自动完成 Code -> Token -> UserInfo 的全流程
*/
@GetMapping("/callback/{type}")
public StandardUser callback(@PathVariable String type, String code, String state) {
return engine.login(type, AuthCallback.success(code, state));
}
}对于像 支付宝 或 微信 这样需要参数签名或特定加密的平台,可以使用 Hook 进行扩展。
1. 配置文件中声明 Hook
spring:
oauth2:
engine:
providers:
alipay:
# ... 基础配置 ...
hooks:
sign-request: # 自定义 Hook 名称
bean-name: alipaySignHook
phase: PRE # 在请求发送前执行2. 实现 Hook 逻辑
@Component("alipaySignHook")
public class AlipaySignHook implements AuthHook {
@Override
public boolean supports(String providerId) {
return "alipay".equals(providerId);
}
@Override
public void execute(PipelineContext ctx) {
// 获取当前请求的所有参数
Map<String, String> params = ctx.getRequestParams();
// 执行签名逻辑
String sign = SignUtils.rsa2(params, privateKey);
// 将签名写回请求参数
ctx.setRequestParam("sign", sign);
}
}如果内置的 HttpURLConnection 无法满足需求(例如需要连接池、代理等),可以实现 HttpExecutor 接口替换底层 HTTP 客户端。
@Bean
public HttpExecutor httpExecutor() {
return new OkHttpExecutor(); // 示例:使用 OkHttp 实现
}