IconCreated with Sketch.

YAPI 接口文档

YApi
  • 路由网关
    • 登录权限鉴定
    • 角色权限鉴定
    • 访问权限鉴定(单)
    • 访问权限鉴定(多)
  • 业务应用
    • 访问权限鉴定(单)
    • 访问权限鉴定(多)

CAS

权限验证接口

公共信息

Edge测试插件地址

插件安装: https://microsoftedge.microsoft.com/addons/detail/crossrequest/bephiepmhphdlafkfonngafenjhfehlb

鉴权域名

当前应用的域,在应用部署后, 应用如果使用的是FMES内容应用, 其IAM系统会分享一下接口给部署的应用

接口 备注
/api/iam/v1/a/odic/login 应用登录接口
/api/iam/v1/a/odic/callback IAM系统回调接口
/api/iam/v1/a/odic/logout 应用登出接口
/api/iam/v1/odic/authc 应用鉴权接口

对于第三方应用, 可以使用账户中心域名:

测试环境:http://account.dev.k8s.local
正式环境:http://account.con.plscn.com

通用性错误

名称 类型 默认值 是否必须 说明 备注
success boolean 必须 请求状态
data object 非必须 请求内容
errorCode string 非必须 异常编码
errorMessage string 非必须 异常内容
showType integer 非必须 前端动作
traceId string 必须 追踪ID
{
  "success": false,
  "data": "string",
  "errorCode": "S_SERVE_FORBIDDEN",
  "errorMessage": "用户未得到授权,访问是被禁止的",
  "showType": 1,
  "traceId": "e59e6f078389d36c2bb06d29297b5b86"
}

前端动作类型, 页面的内容应该有前端拦截器统一处理

名称 类型 值 动作 备注
ShowNone 0 静音
ShowWarn 1 消息警告
ShowError 2 消息错误
ShowNotify 4 通知
ShowPage 9 页面跳转

路由网关

登录权限鉴定

基本信息

Path: /authx

Method: GET

接口描述:

该内容为网关层调用,与具体业务应用无关,请求路由到业务接口前已经通过平台IAM网关处理,网关会在转发的请求上增加下面的Serve, Sessionid, Authorize, Signature内容。子应用只需要处理请求头上的内容完成授权即可。

Kratos框架:

框架中的Kratos.getUser方法可以直接得到用户的登陆信息,无需单独处理请求头上的内容

用户认证处理过程:

  1. 用户通过IAM系统登陆, 获取访问令牌
  2. 用户通过访问令牌访问业务应用, 被IAM系统拦截, 确认身份后, 将身份信息附加到请求头上, 向业务应用转发
  3. 业务应用通过请求头获取用户身份, 完成请求处理后,将结果返回给用户
返回结果

请求头

参数 类型 描述 说明
X-Request-Sky-Serve Header 验证服务器
X-Request-Sky-Sessionid Header 账户SessionId
X-Request-Sky-Authorize Header 用户信息载体
X-Request-Sky-Signature Header 用户信息签名 用户验证载体信息的正确性
处理说明

X-Request-Sky-Authorize: 内容为Base64加密的JSON内容, 通过Base64解密即可得到用户详细信息。以下是用户载体中的内容:推荐使用fasterjson解析内容, 如果使用非fasterjson解析, 需要替换注解内容。

 String authorize = request.getHeader("X-Request-Sky-Authorize"):
 byte[] bts = Base64.getDecoder().decode(authorize);
 UserCtx ctx2 = JSON.parseObject(bts, UserCtx.class);

用户上下文内容:

/**
 * 用户上下文
 *
 * @author <a href="mailto:suisrc@outlook.com">Y13</a>
 */
@Data
public class UserCtx implements UserI {
// 上下文ID

@JSONField(serialize = false)
private String contextId;
@JSONField(serialize = false)
private String requestId;
@JSONField(serialize = false)
private String clientIp;

// UserClaims

@JSONField(name = "jti")
private String id;
@JSONField(name = "aud")
private String audience;
@JSONField(name = "exp")
private String expiredAt;
@JSONField(name = "iat")
private String issuedAt;
@JSONField(name = "iss")
private String issuer;
@JSONField(name = "nbf")
private String notBefore;
@JSONField(name = "sub")
private String subject;

@JSONField(name = "nam")
private String name;
@JSONField(name = "rol")
private String role; // 请看tenant_role_code

@JSONField(name = "flw")
private String flow;
@JSONField(name = "akd")
private String accountKind;
@JSONField(name = "atc")
private String userTmpCode;
@JSONField(name = "nonce")
private String nonce;

// IdInfo
@JSONField(name = "ids")
private String ids;
@JSONField(serialize = false)
private Integer accountId;
@JSONField(serialize = false)
private Integer userId;
@JSONField(serialize = false)
private Integer appId;
@JSONField(serialize = false)
private Integer tenantId;
@JSONField(serialize = false)
private Integer tenantUserId;
@JSONField(serialize = false)
private Integer tenantRoleId;
@JSONField(serialize = false)
private Integer tenantDirId;
@JSONField(serialize = false)
private Integer tenantAppId;
@JSONField(name = "id2")
private Integer[] id2;

// UserInfo

@JSONField(name = "uco")
private String userCode;
@JSONField(name = "una")
private String userName;

@JSONField(name = "three")
private String three;
@JSONField(name = "agent")
private String agent;
@JSONField(name = "scope")
private String scope;

// TenantInfo
@JSONField(name = "tkd")
private String tenantKind;
@JSONField(name = "tco")
private String tenantCode;
@JSONField(name = "tna")
private String tenantName;

@JSONField(name = "tuc")
private String tenantUserCode;
@JSONField(name = "tcc")
private String tenantUserCcde;
@JSONField(name = "tun")
private String tenantUserName;

@JSONField(name = "app")
private String tenantAppCode;
@JSONField(name = "apn")
private String tenantAppName;
@JSONField(name = "trc")
private String tenantRoleCode;
@JSONField(name = "trn")
private String tenantRoleName;

@JSONField(name = "tpg")
private String tenantPrivilege;
@JSONField(name = "tup")
private String tenantUserPhone;

/**
 * 异常
 */
private ErrorCodeException error;

// ======================================================
// ======================================================
// ======================================================

public String getAccountCode() {
    return subject;
}
public String getAccountName() {
    return name;
}

@Override
public boolean verify() {
    if (error != null) {
        throw error;
    } else if (accountId == null) {
        // throw Errors.Err401Unauthorized // 业务代理中不能使用401异常
        // 否则会导致平台在IAM和业务系统间无限跳转异常
        throw Errors.Err403Unauthorized;
    }
    return true;
}

}

X-Request-Sky-Signature: 用户载体签名, 防止用户内容被篡改。publicKey为平台IAM系统颁发给子应用的验签公钥。Sign通过request.getHeader("X-Request-Sky-Authorize")方式取得。

    /**
     * @param content:验证参数的内容
     * @param sign:签名
     * @param publicKey:公钥
     * @return
     */
    public boolean verifySign(String authorize, String sign, String publicKey) {
        try {
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            byte[] encodedKey = Base64.getDecoder().decode(publicKey);
            PublicKey pubKey = keyFactory.generatePublic(new X509EncodedKeySpec(encodedKey));
        Signature signature = Signature.getInstance("SHA256withRSA");
        signature.initVerify(pubKey);
        signature.update(content.getBytes());

        return signature.verify(Base64.getUrlDecoder().decode(sign));
    } catch (Exception e) {
        // throw new RuntimeException(e)
        return false;
    }
}

平台业务应用无需访问平台IAM鉴权系统。请求通过平台网关后, 会将请求优先转发到IAM系统完成权限认证。如果认证失败,IAM系统直接通知平台网关将结果返回给客户端。如果鉴权成功,鉴权的结果, 包含用户信息载体和用户信息签名附件到请求上,继续向上游业务系统路由。
业务系统,需要内部调用其他业务应用资源,使用以上4个header内容附加到请求上。即到达其他应用资源权限校验。

请求参数

Headers

参数名称 参数值 是否必须 示例 备注
Content-Type application/json 是 application/json 编码方式
Authorization 是 Bearer XXXX 访问令牌
X-Request-Origin-Host 是 127.0.0.1 访问的客户端IP
X-Request-Origin-Path 是 /api/v1 访问的路径
X-Request-Origin-Method 是 GET 访问的方法,ET, POST, DELETE, PUT

返回数据

名称类型是否必须默认值备注其他信息
successboolean必须请求状态
datastring非必须请求结果
errorCodestring非必须异常编码
errorMessagestring非必须异常内容
showTypenumber非必须前端动作
traceIdstring必须追踪ID

角色权限鉴定

基本信息

Path: /authz

Method: GET

接口描述:

该内容为网关层调用,与具体业务应用无关,请求路由到业务接口前已经通过平台IAM网关处理,网关会在转发的请求上增加下面的Serve, Sessionid, Authorize, Signature内容。子应用只需要处理请求头上的内容完成授权即可。

Kratos框架:

框架中的Kratos.getUser方法可以直接得到用户的登陆信息,无需单独处理请求头上的内容

用户认证处理过程:

  1. 用户通过IAM系统登陆, 获取访问令牌
  2. 用户通过访问令牌访问业务应用, 被IAM系统拦截, 确认身份后, 将身份信息附加到请求头上, 向业务应用转发
  3. 业务应用通过请求头获取用户身份, 完成请求处理后,将结果返回给用户
返回结果

请求头

参数 类型 描述 说明
X-Request-Sky-Serve Header 验证服务器
X-Request-Sky-Sessionid Header 账户SessionId
X-Request-Sky-Authorize Header 用户信息载体
X-Request-Sky-Signature Header 用户信息签名 用户验证载体信息的正确性
处理说明

X-Request-Sky-Authorize: 内容为Base64加密的JSON内容, 通过Base64解密即可得到用户详细信息。以下是用户载体中的内容:推荐使用fasterjson解析内容, 如果使用非fasterjson解析, 需要替换注解内容。

 String authorize = request.getHeader("X-Request-Sky-Authorize"):
 byte[] bts = Base64.getDecoder().decode(authorize);
 UserCtx ctx2 = JSON.parseObject(bts, UserCtx.class);

用户上下文内容:

/**
 * 用户上下文
 *
 * @author <a href="mailto:suisrc@outlook.com">Y13</a>
 */
@Data
public class UserCtx implements UserI {
// 上下文ID

@JSONField(serialize = false)
private String contextId;
@JSONField(serialize = false)
private String requestId;
@JSONField(serialize = false)
private String clientIp;

// UserClaims

@JSONField(name = "jti")
private String id;
@JSONField(name = "aud")
private String audience;
@JSONField(name = "exp")
private String expiredAt;
@JSONField(name = "iat")
private String issuedAt;
@JSONField(name = "iss")
private String issuer;
@JSONField(name = "nbf")
private String notBefore;
@JSONField(name = "sub")
private String subject;

@JSONField(name = "nam")
private String name;
@JSONField(name = "rol")
private String role; // 请看tenant_role_code

@JSONField(name = "flw")
private String flow;
@JSONField(name = "akd")
private String accountKind;
@JSONField(name = "atc")
private String userTmpCode;
@JSONField(name = "nonce")
private String nonce;

// IdInfo
@JSONField(name = "ids")
private String ids;
@JSONField(serialize = false)
private Integer accountId;
@JSONField(serialize = false)
private Integer userId;
@JSONField(serialize = false)
private Integer appId;
@JSONField(serialize = false)
private Integer tenantId;
@JSONField(serialize = false)
private Integer tenantUserId;
@JSONField(serialize = false)
private Integer tenantRoleId;
@JSONField(serialize = false)
private Integer tenantDirId;
@JSONField(serialize = false)
private Integer tenantAppId;
@JSONField(name = "id2")
private Integer[] id2;

// UserInfo

@JSONField(name = "uco")
private String userCode;
@JSONField(name = "una")
private String userName;

@JSONField(name = "three")
private String three;
@JSONField(name = "agent")
private String agent;
@JSONField(name = "scope")
private String scope;

// TenantInfo
@JSONField(name = "tkd")
private String tenantKind;
@JSONField(name = "tco")
private String tenantCode;
@JSONField(name = "tna")
private String tenantName;

@JSONField(name = "tuc")
private String tenantUserCode;
@JSONField(name = "tcc")
private String tenantUserCcde;
@JSONField(name = "tun")
private String tenantUserName;

@JSONField(name = "app")
private String tenantAppCode;
@JSONField(name = "apn")
private String tenantAppName;
@JSONField(name = "trc")
private String tenantRoleCode;
@JSONField(name = "trn")
private String tenantRoleName;

@JSONField(name = "tpg")
private String tenantPrivilege;
@JSONField(name = "tup")
private String tenantUserPhone;

/**
 * 异常
 */
private ErrorCodeException error;

// ======================================================
// ======================================================
// ======================================================

public String getAccountCode() {
    return subject;
}
public String getAccountName() {
    return name;
}

@Override
public boolean verify() {
    if (error != null) {
        throw error;
    } else if (accountId == null) {
        // throw Errors.Err401Unauthorized // 业务代理中不能使用401异常
        // 否则会导致平台在IAM和业务系统间无限跳转异常
        throw Errors.Err403Unauthorized;
    }
    return true;
}

}

X-Request-Sky-Signature: 用户载体签名, 防止用户内容被篡改。publicKey为平台IAM系统颁发给子应用的验签公钥。Sign通过request.getHeader("X-Request-Sky-Authorize")方式取得。

    /**
     * @param content:验证参数的内容
     * @param sign:签名
     * @param publicKey:公钥
     * @return
     */
    public boolean verifySign(String authorize, String sign, String publicKey) {
        try {
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            byte[] encodedKey = Base64.getDecoder().decode(publicKey);
            PublicKey pubKey = keyFactory.generatePublic(new X509EncodedKeySpec(encodedKey));
        Signature signature = Signature.getInstance("SHA256withRSA");
        signature.initVerify(pubKey);
        signature.update(content.getBytes());

        return signature.verify(Base64.getUrlDecoder().decode(sign));
    } catch (Exception e) {
        // throw new RuntimeException(e)
        return false;
    }
}

平台业务应用无需访问平台IAM鉴权系统。请求通过平台网关后, 会将请求优先转发到IAM系统完成权限认证。如果认证失败,IAM系统直接通知平台网关将结果返回给客户端。如果鉴权成功,鉴权的结果, 包含用户信息载体和用户信息签名附件到请求上,继续向上游业务系统路由。
业务系统,需要内部调用其他业务应用资源,使用以上4个header内容附加到请求上。即到达其他应用资源权限校验。

请求参数

Headers

参数名称 参数值 是否必须 示例 备注
Content-Type application/json 是 application/json 编码方式
Authorization 是 Bearer XXXX 访问令牌
X-Request-Origin-Host 是 127.0.0.1 访问的客户端IP
X-Request-Origin-Path 是 /api/v1 访问的路径
X-Request-Origin-Method 是 GET 访问的方法,ET, POST, DELETE, PUT

返回数据

名称类型是否必须默认值备注其他信息
successboolean必须请求状态
datastring非必须请求结果
errorCodestring非必须异常编码
errorMessagestring非必须异常内容
showTypenumber非必须前端动作
traceIdstring必须追踪ID

访问权限鉴定(单)

基本信息

Path: /authc

Method: GET

接口描述:

访问权限鉴定(单)

用户用户访问鉴权

用户没有有效令牌

{
  "success": false,
  "errorCode": "S_UNAUTHORIZED_INVALID-TOKEN",
  "errorMessage": "用户没有权限(请求令牌无效)",
  "showType": 1,
  "traceId": "ccff7913a6a4e746f4c19a559d746fa0"
}

用户没有访问权限

{
  "success": false,
  "errorCode": "S_SERVE_FORBIDDEN",
  "errorMessage": "用户未得到授权,访问是被禁止的",
  "showType": 1,
  "traceId": "e59e6f078389d36c2bb06d29297b5b86"
}

用户获取访问权限

{
  "success": true,
  "data": "ok",
  "traceId": "ced0b4187066b2a7d52a2f34ce8b5c65"
}

请求参数

Headers

参数名称 参数值 是否必须 示例 备注
Content-Type application/json 是 application/json
Authorization Bearer XXXX 是 Bearer XXXX 访问令牌, cookie中如果存在kat, 该参数可以为空

Query

参数名称 是否必须 示例 备注
method 是 GET 请求方法,GET , POST, PUT, DELETE
path 是 /api/v1 清理路径

返回数据

名称类型是否必须默认值备注其他信息
successboolean必须是否成功
datastring非必须结果,发生异常,该值不存在
errorCodestring非必须异常编码,成功后,该值不存在
errorMessagestring非必须异常内容
showTypenumber非必须前端反应
traceIdstring必须追踪编码,用于追踪集

访问权限鉴定(多)

基本信息

Path: /authc

Method: POST

接口描述:

访问权限鉴定(单)
用户用户访问鉴权

用户没有有效令牌

{
  "success": false,
  "errorCode": "S_UNAUTHORIZED_INVALID-TOKEN",
  "errorMessage": "用户没有权限(请求令牌无效)",
  "showType": 1,
  "traceId": "ccff7913a6a4e746f4c19a559d746fa0"
}

用户访问权限

{
  "success": true,
  "data": {
    "KEY1": false,
    "KEY2": true
  },
  "traceId": "993f452303a796ab44447ac5f84ceb87"
}

请求参数

Headers

参数名称 参数值 是否必须 示例 备注
Content-Type application/json 是 application/json
Authorization Bearer XXXX 是 Bearer XXXX 访问令牌, cookie中如果存在kat, 该参数可以为空

Body

名称类型是否必须默认值备注其他信息
KEY1object必须鉴权资源编码
├─ methodstring必须鉴权内容的方法
├─ pathstring必须鉴权内容的路径
KEY2object必须鉴权资源编码
├─ methodstring必须鉴权资源的方法
├─ pathstring必须鉴权资源的路径

返回数据

名称类型是否必须默认值备注其他信息
successboolean必须请求状态
dataobject必须结果
├─ KEY1boolean必须鉴权资源的结果
├─ KEY2boolean必须鉴权资源的结果
errorCodestring非必须异常编码
errorMessagestring非必须异常内容
showTypenumber非必须前端动作
traceIdstring必须追踪ID

业务应用

访问权限鉴定(单)

基本信息

Path: /api/iam/v1/a/odic/authc

Method: GET

接口描述:

访问权限鉴定(单)

用户用户访问鉴权

用户没有有效令牌

{
  "success": false,
  "errorCode": "S_UNAUTHORIZED_INVALID-TOKEN",
  "errorMessage": "用户没有权限(请求令牌无效)",
  "showType": 1,
  "traceId": "ccff7913a6a4e746f4c19a559d746fa0"
}

用户没有访问权限

{
  "success": false,
  "errorCode": "S_SERVE_FORBIDDEN",
  "errorMessage": "用户未得到授权,访问是被禁止的",
  "showType": 1,
  "traceId": "e59e6f078389d36c2bb06d29297b5b86"
}

用户获取访问权限

{
  "success": true,
  "data": "ok",
  "traceId": "ced0b4187066b2a7d52a2f34ce8b5c65"
}

请求参数

Headers

参数名称 参数值 是否必须 示例 备注
Content-Type application/json 是 application/json
Authorization Bearer XXXX 是 Bearer XXXX 访问令牌, cookie中如果存在kat, 该参数可以为空

Query

参数名称 是否必须 示例 备注
method 是 GET 请求方法,GET , POST, PUT, DELETE
path 是 /api/v1 清理路径

返回数据

名称类型是否必须默认值备注其他信息
successboolean必须是否成功
datastring非必须结果,发生异常,该值不存在
errorCodestring非必须异常编码,成功后,该值不存在
errorMessagestring非必须异常内容
showTypenumber非必须前端反应
traceIdstring必须追踪编码,用于追踪集

访问权限鉴定(多)

基本信息

Path: /api/iam/v1/a/odic/authc

Method: POST

接口描述:

访问权限鉴定(单)
用户用户访问鉴权

用户没有有效令牌

{
  "success": false,
  "errorCode": "S_UNAUTHORIZED_INVALID-TOKEN",
  "errorMessage": "用户没有权限(请求令牌无效)",
  "showType": 1,
  "traceId": "ccff7913a6a4e746f4c19a559d746fa0"
}

用户没有访问权限

{
  "success": true,
  "data": {
    "KEY1": false,
    "KEY2": true
  },
  "traceId": "993f452303a796ab44447ac5f84ceb87"
}

请求参数

Headers

参数名称 参数值 是否必须 示例 备注
Content-Type application/json 是 application/json
Authorization Bearer XXXX 是 Bearer XXXX 访问令牌, cookie中如果存在kat, 该参数可以为空

Body

名称类型是否必须默认值备注其他信息
KEY1object必须鉴权资源编码
├─ methodstring必须鉴权内容的方法
├─ pathstring必须鉴权内容的路径
KEY2object必须鉴权资源编码
├─ methodstring必须鉴权资源的方法
├─ pathstring必须鉴权资源的路径

返回数据

名称类型是否必须默认值备注其他信息
successboolean必须请求状态
dataobject必须结果
├─ KEY1boolean必须鉴权资源的结果
├─ KEY2boolean必须鉴权资源的结果
errorCodestring非必须异常编码
errorMessagestring非必须异常内容
showTypenumber非必须前端动作
traceIdstring必须追踪ID

Build by YMFE.