Open API 授权&鉴权机制设计

概述

基于 OAuth2 建设 Open API 平台授权机制,通过安全标准的方式授权给外部,保证部门应用数据的安全性。

OAuth2 定义了4种授权方式,但目前只需要供客户端在后台调用即可,所以仅考虑凭证式授权方式。

设计方案

整体流程示意图:

下面按照上面提到的四大模块来进行分析:

客户端

客户端通常是第三方服务,通过 Open API 获取资源。

客户端获取资源步骤:

第一步,用户需要在开放平台登录,然后注册客户端凭证,注册过程中给该凭证指定权限范围(Scope),注册完后会生成 client_id 和 client_secret,其中 client_secret 需要保密管理。

第二步,利用上一步拿到的 client_id 和 client_secret 发起请求获取令牌。

第三步,调用 API ,并在请求头上附带令牌。

令牌会过期,过期后重新请求获取令牌即可。

区分两种权限类型:

  1. API 权限,用户创建客户端凭证时指定(Scope)
  2. 数据权限,继承用户的数据权限

授权服务

授权服务负责授权和维护客户端凭证与权限的关系。

依赖 spring-security-oauth2-authorization-server 组件来构建该服务。

spring-security-oauth2-authorization-server 组件里面提供了基于 OAuth2 实现的授权服务,开箱即用.

库表介绍

  1. oauth2_registered_client:spring-security-oauth2-authorization-server 组件依赖的表,记录已注册了的客户端凭证。
  2. oauth2_authorization:spring-security-oauth2-authorization-server 组件依赖的表,记录已生成的令牌。
  3. oauth2_user_registered_client_relation:记录用户和客户端凭证的关系。
  4. oauth2_scope:权限范围(模块),支持两个层级。
  5. oauth2_open_api:记录对外API清单以及与 scope 的关系。

各个表的关系如下:

授权

目前仅支持凭证式授权方式,不需要刷新令牌,令牌过期后重新获取即可。

spring-security-oauth2-authorization-server 组件内置了授权接口 /oauth/token.

JWT

令牌使用 JWT 生成,使用 JWT 的好处是:

  1. JWT 是一种自包含结构,可以存放一些关键信息,不需要额外查询。仅使用 JWT 令牌即可完成校验令牌有效性的动作。
  2. JWT 令牌由客户端来保管,且在里面存放客户端信息,服务器端不需要维护客户端状态,有利于服务端的无状态化和水平扩展。
  3. JWT 令牌通过签名来防止信息被篡改。

坏处是:

  1. 虽然信息不能被篡改,但是还是有泄漏的风险,建议对内容进行加密。

JWT 可以到 JWT.IO 网站解析。

网关

网关是客户端访问的唯一入口,是外部请求连接内部服务的桥梁,授权,鉴权,路由都在这里完成。

网关处理两类请求,一类是授权(获取令牌)请求,一类是获取资源请求。

授权(获取令牌)请求

这类请求逻辑比较简单,网关接收到后直接路由到授权服务。

获取资源请求

此类请求需要网关先到授权服务获取到权限信息,鉴权通过后再路由到资源服务。

注意,网关对鉴权通过的请求在路由前会设置请求头 Open-Api-Client-IdOpen-Api-User-Id,作用有两个:

  1. 可以通过这两个请求头判断是否是 Open API 请求。
  2. 资源服务可以从这两个请求头获取到 client_id 和 user_id 信息。

资源服务

资源服务是实际的资源提供者。

请求来到资源服务代表鉴权已经通过,可以通过请求头 Open-Api-Client-IdOpen-Api-User-Id 来获取 Open API 调用者 client_id 和对应的 user_id 信息。

附录

请求

获取令牌

请求接口:/oauth2/token

请求方式:POST

请求头:

Content-Type application/x-www-form-urlencoded

请求参数:

名称 类型 描述
client_id string client_id
client_secret string client_secret
grant_type string 授权方式,目前仅支持 client_credentials

响应字段:

名称 类型 描述
access_token string 令牌
token_type string 令牌类型,目前仅支持 Bearer
expires_in int 过期时间,单位秒,令牌过期后需要重新获取
scope string 权限范围

响应示例:

json 复制代码
{
    "access_token": "eyJraWQiOiJyc2EtandrLWtpZCIsImFsZyI6IlJTMjU2In0.eyJzdWIiOiI1MjMxODcwODQ5OTMxMjgwNTExIiwiYXVkIjoiNTIzMTg3MDg0OTkzMTI4MDUxMSIsIm5iZiI6MTY0NjAyODk1OSwic2NvcGUiOlsiMS0wIiwiMi0wIiwiMy0wIl0sImlzcyI6Imh0dHA6XC9cL3ZvZG1hcmtldHNzby55ZnhuLmxpemhpLmZtIiwiZXhwIjoxNjQ2MDMwMTU5LCJpYXQiOjE2NDYwMjg5NTksImNpZCI6IjUyMzE4NzA4NDk5MzEyODA1MTEifQ.Wn9APM9l64J761MJDs2nh61lITme575UyCXvyL0UftYEOebpoo60PSN3kLVGOXC5LIEztmzWF4ZcEOlkoHToU-9op3XML3e-HikmcpPOIExjDNdbimrY_zoHvzuX0LkTRxDNEwCrHkl7kHueJlwwXcaKM6jOLxyBD6wRL43DvaF4__hiI_RvMVh069SOgQlVRr0wpKtjegEfoXiMOhGYuRt_ArKBv8SWYjGL2Zz0dPA6Kxy8NowgVEHtwRRPSklSKPzq6sWsU9XMq1uGHBcf1EAMFD-CQAcFsL_b7oS4rGgOgT7kYDHRaMKGILnCEY4VZDA3FNTy1vnllumzN6quEA",
    "token_type": "Bearer",
    "expires_in": 1800,
    "scope": "1-0 2-0 3-0"
}

获取资源

获取资源请求需要包含 Authorization 请求头,示例:

ini 复制代码
Authorization = Bearer eyJraWQiOiJyc2EtandrLWtpZCIsImFsZyI6IlJTMjU2In0.eyJzdWIiOiI1MjMxODcwODQ5OTMxMjgwNTExIiwiYXVkIjoiNTIzMTg3MDg0OTkzMTI4MDUxMSIsIm5iZiI6MTY0NjAyODk1OSwic2NvcGUiOlsiMS0wIiwiMi0wIiwiMy0wIl0sImlzcyI6Imh0dHA6XC9cL3ZvZG1hcmtldHNzby55ZnhuLmxpemhpLmZtIiwiZXhwIjoxNjQ2MDMwMTU5LCJpYXQiOjE2NDYwMjg5NTksImNpZCI6IjUyMzE4NzA4NDk5MzEyODA1MTEifQ.Wn9APM9l64J761MJDs2nh61lITme575UyCXvyL0UftYEOebpoo60PSN3kLVGOXC5LIEztmzWF4ZcEOlkoHToU-9op3XML3e-HikmcpPOIExjDNdbimrY_zoHvzuX0LkTRxDNEwCrHkl7kHueJlwwXcaKM6jOLxyBD6wRL43DvaF4__hiI_RvMVh069SOgQlVRr0wpKtjegEfoXiMOhGYuRt_ArKBv8SWYjGL2Zz0dPA6Kxy8NowgVEHtwRRPSklSKPzq6sWsU9XMq1uGHBcf1EAMFD-CQAcFsL_b7oS4rGgOgT7kYDHRaMKGILnCEY4VZDA3FNTy1vnllumzN6quEA

其中,

  • Bearer代表令牌类型,后面跟着访问令牌。

API 权限通配符配置示例

这里给一些 API 权限配置示例(只是建议)

URI 请求方式 描述 API 权限通配符配置(对应 oauth2_open_api 表 path 字段)
/api/demo_entities/{id} GET 根据id获取资源 GET_/api/demo_entities/{id:\d+}
/api/demo_entities POST 新建资源 POST_/api/demo_entities,POST_/api/demo_entities/
/api/demo_entities GET 查询资源 GET_/api/demo_entities,GET_/api/demo_entities/
/api/demo_entities PUT 更新资源 PUT_/api/demo_entities,PUT_/api/demo_entities/
/api/demo_entities/{id} DELETE 根据id删除资源 DELETE_/api/demo_entities/{id:\d+}

参考

相关推荐
MinBadGuy22 分钟前
【GeekBand】C++设计模式笔记5_Observer_观察者模式
c++·设计模式
刷帅耍帅36 分钟前
设计模式-生成器模式/建造者模式Builder
设计模式·建造者模式
蜡笔小新..1 天前
【设计模式】软件设计原则——开闭原则&里氏替换&单一职责
java·设计模式·开闭原则·单一职责原则
性感博主在线瞎搞1 天前
【面向对象】设计模式概念和分类
设计模式·面向对象·中级软件设计师·设计方法
lucifer3111 天前
JavaScript 中的组合模式(十)
javascript·设计模式
lucifer3111 天前
JavaScript 中的装饰器模式(十一)
javascript·设计模式
蜡笔小新..1 天前
【设计模式】软件设计原则——依赖倒置&合成复用
设计模式·依赖倒置原则·合成复用原则
刷帅耍帅1 天前
设计模式-代理模式
设计模式·代理模式
神的孩子都在歌唱1 天前
行为设计模式 -观察者模式- JAVA
java·观察者模式·设计模式
刷帅耍帅2 天前
设计模式-解释器模式
设计模式·解释器模式