Skip to content

toby1123yjh/oauth2-engine

Repository files navigation

OAuth2 Engine

License Maven Central

OAuth2 Engine 是一个轻量级、配置驱动的通用 OAuth2 客户端集成库。

它的核心目标是解决第三方平台(GitHub, 微信, 支付宝, 钉钉等)OAuth2 实现标准不统一的问题。通过 Pipeline 机制声明式配置,开发者无需为每个平台编写独立的 ServiceUtil 代码,仅需一份 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

🚀 快速开始

1. 基础配置 (application.yml)

以下示例展示了如何配置 标准 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" }

2. 业务代码调用

只需注入 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 机制)

对于像 支付宝微信 这样需要参数签名或特定加密的平台,可以使用 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);
    }
}

🧩 扩展 SPI

如果内置的 HttpURLConnection 无法满足需求(例如需要连接池、代理等),可以实现 HttpExecutor 接口替换底层 HTTP 客户端。

@Bean
public HttpExecutor httpExecutor() {
    return new OkHttpExecutor(); // 示例:使用 OkHttp 实现
}

📄 License

Apache License 2.0

About

轻量级、配置驱动的通用 OAuth2 客户端集成库。

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages