为了给您提供更优质的服务,请您先完善以下信息:
确认提交

扫码关注

爱数技术支持中心公众号

请选择:

请选择咨询类型

AnyShare
AnyBackUp
AnyRobot

扫码关注

爱数技术支持中心公众号

contact us

提交成功!

我们将在 24 小时之内联系你。

性能爆表
AnyShare
如何购买
我已是Anyshare 客户
AnyRobot
如何购买
购买 AnyRobot 订阅服务
我已是 AnyRobot 客户
一对一在线咨询
我是 AnyRobot 新客户
一对一在线咨询

爱数博客

全部 AnyBackup AnyShare AnyRobot AnyDATA AnyFabric

AnyShare 7 使用 sso 方法获取业务系统访问令牌

2022-09-26 3294 0

背景

业务系统和 AnyShare 7 对接,调用 OpenDoc API 时需要在请求头中加入访问令牌才能得到正确的响应,所以需要提供一份认证指南。该指南以生成业务系统使用的访问令牌为目的。

术语

  • Access_token: 访问令牌,调用 OpenDoc API 需要加入 "Authorization: Bearer Access_token" Header

  • Client_id: 客户端 id,用于识别业务系统,建议每个业务系统使用一个单独的 Client_id

  • Client_secret: 客户端密钥,和 Client_id 一一对应,统一生成

  • JWT: 即 JSON Web Token,网络应用环境间传递声明而执行的一种基于json的开放标准

  • Plugin_id: 插件 id,AnyShare 第三方认证插件 id

  • Plugin_secret: 插件密钥,用于 JWT 签名

  • As_code: 用于换取 Access_token 的临时密钥

前置条件

  • AnyShare 7.0.1以上版本

  • 已通过爱数集成开发工程师定制第三方认证插件

定制的认证插件主要完成验证 JWT 的过程,对于有能力的服务商,可以自行开发插件

Access_token 获取步骤

一、获取 Plugin_id 和 Plugin_secret

这一步应由管理员操作

登录 AnyShare 8000 控制台,可以在第三方配置插件界面获取 Plugin_id 和 Plugin_secret:

二、生成业务系统客户端

这一步可以由管理员(推荐)或业务系统操作,生成的client_id和redirect_uris可以保存在配置文件中,多次使用。

可以使用 http 请求按以下方式生成业务系统客户端:

URL: https://{{host}}/oauth2/clients

Method: POST

请求 Body:

{
    "client_name": "测试业务系统",
    "grant_types": [
        "authorization_code",
        "implicit",
        "refresh_token"
    ],
    "response_types": [
        "token id_token",
        "code",
        "token"
    ],
    "scope": "offline openid all",
    "redirect_uris": [
        "https://localhost/callback"
    ],
    "post_logout_redirect_uris": [
        "https://localhost/logout"
    ],
    "metadata": {
        "device": {
            "name": "测试业务系统",
            "client_type": "web",
            "description": "web"
        }
    }
}

请求说明:

参数名 说明
client_name 业务系统名称,按需填写
grant_types 授权类型,不需要修改
response_types 响应类型,不需要修改
scope 适用范围,不需要修改
redirect_uris 重定向地址列表,无实际用处,可以使用虚构地址,但是调用后续接口时需要保持一致,需要记录
post_logout_redirect_uris 登出地址列表,无实际用处,可以使用虚构地址
metadata 元数据,无实际用处,name 字段和 client_name 一致即可

响应 body:

{
    "client_id": "9d33abd5-204b-4a08-8bf2-5dc6a7f08b9f",
    "client_secret": "EBxXDrytts~Z"
}

响应说明:

参数名 说明
client_id 客户端 id,需要记录,后续接口需要适用
client_secret 客户端密钥,需要记录

这一步需要记录 client_id、client_secret、redirect_uris 三个字段。如果遗失,没有办法恢复

Postman 截图:

管理员应提供 Client_id 、Redirect_uri、Plugin_id 、 Plugin_secret 和 username 给业务系统

三、使用 JWT 生成临时密钥

这一步应由业务系统操作

一份完整的 JWT 数据包含三部分:

  • Header: 头部

  • Payload: 负载

  • Signature: 签名

对于该认证过程,Header 固定如下:

{
    "alg": "HS256",
    "typ": "JWT"
}

Header 请求说明:

参数名 说明
alg 签名算法,不需要修改
typ JWT 类型,不需要修改

Payload 如下:

{
    "username": "test10",
    "exp": 1618467914
}

Payload 请求说明:

参数名 说明
username 需要登录的 AnyShare 用户名
exp 临时密钥的过期时间戳,注意不是访问令牌的过期时间,一般设置为1到2分钟即可

Signature: 签名使用 AnyShare 提供的 Plugin_secret 使用 HS256 算法计算。

实际使用过程中,可以使用各类 JWT 库来生成临时密钥,Python 和 Java 的实现如下。 Python 版本:

import time
​
import jwt
​
​
def get_token(username, secret):
    payload = {
        "username": username,
        "exp": int(time.time()) + 60
    }
    encoded = jwt.encode(payload, secret, algorithm="HS256")
    return encoded
​
​
if __name__ == '__main__':
    print(get_token("xxx", "xxxx"))

其中 username 为要登录的用户名,secret 为 Plugin_secret。

Java 版本:

package com.example.jwtTest;
​
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;
​
import java.io.UnsupportedEncodingException;
import java.util.Date;
import java.util.Map;
​
public class demo {
    public String createJwt(String username, String secret, long expire) throws UnsupportedEncodingException {
        Date now = new Date();
        Date expireDate = new Date(now.getTime() + 1000 * expire);
        Algorithm algorithm = Algorithm.HMAC256(secret);
        String token = JWT.create()
                .withClaim("username", username) // 增加Payload数据
                .withExpiresAt(expireDate)  // 过期时间
                .sign(algorithm);
        return token;
    }
​
    public static void main(String[] args) throws UnsupportedEncodingException {
        demo Demo = new demo();
        //过期时间  60 秒后
        long expire = 60;
        // 秘钥
        String username = "用户名";
        String secret = "xxx";
        System.out.println(Demo.createJwt(username, secret, expire));
    }
}

其中 username 为要登录的用户名,secret 为 Plugin_secret。

C# 版本:

using System;
using System.Collections.Generic;
using JWT;
using JWT.Algorithms;
using JWT.Serializers;
​
namespace ConsoleApp
{
    class Program
    {
        public static string CreateJwtToken(IDictionary payload, string secret, IDictionary extraHeaders = null)
        {
            IJwtAlgorithm algorithm = new HMACSHA256Algorithm();
            IJsonSerializer serializer = new JsonNetSerializer();
            IBase64UrlEncoder urlEncoder = new JwtBase64UrlEncoder();
            IJwtEncoder encoder = new JwtEncoder(algorithm, serializer, urlEncoder);
            var token = encoder.Encode(payload, secret);
            return token;
        }
​
        static void Main(string[] args)
        {
            // 配置项(用户名和plugin_secret)
            var username = "用户名";
            var secret = "xxx";
​
            var extraHeaders = new Dictionary { };
            //过期时间(可以不设置,下面表示签名后 60 秒过期)
            double exp = (DateTime.UtcNow.AddSeconds(60) - new DateTime(1970, 1, 1)).TotalSeconds;
            var payload = new Dictionary{
                { "username", username },
                { "exp", exp },
            };
            var token = CreateJwtToken(payload, secret, extraHeaders);
            Console.WriteLine(token);
            Console.ReadKey();
        }
    }
}

其中 username 为要登录的用户名,secret 为 Plugin_secret。

这一步需要记录生成的 As_code,用于换取访问令牌

Python 版截图: 

四、使用临时密钥换取访问令牌

这一步应由业务系统操作

可以使用 http 请求按以下方式生成业务系统客户端:

URL: https://{{host}}/api/authentication/v1/sso

Method: POST

请求 Body:

{
    "client_id": "xxx",
    "redirect_uri": "xxx",
    "response_type": "token id_token",
    "scope": "offline openid all",
    "udids": [
        ""
    ],
    "credential": {
        "id": "xxx",
        "params": {
            "as_code": "xxx"
        }
    }
}

请求说明:

参数名 说明
client_id 第一步生成的 client_id
redirect_uri 第一步使用的 redirect_uris 中的一个 uri
response_type 响应类型,不需要修改
scope 适用范围,不需要修改
udids 唯一标识符,可以留空
credential.id 插件id,即爱数提供的 Plugin_id
credential.params.as_code 第二部生成的 As_code

响应 body:

{
    "access_token": "TU6Vpwz-RMw71SuhsUHNPV5B5-eruDY6CxFo3vMaucc.Jm0TWZ9cp1zvoD4CEzqefjNjCDCKXEih94MUwgO6cMs",
    "expirses_in": 3599,
    "id_token": "eyJhbGciOiJSUzI1NiIsImtpZCI6InB1YmxpYzpmZmY4NTM2NS00YTZmLTQ5OWMtYjljNi1hMzMxNmQ0NzJjMWQiLCJ0eXAiOiJKV1QifQ.eyJhdF9oYXNoIjoiR21IZmR2UWU3dVU4OVA3V2wya015USIsImF1ZCI6WyIxMzJlYzc4Ny0zYjI2LTQ2N2UtODMzNS1lNDExNDBlNjZjNzYiXSwiYXV0aF90aW1lIjoxNjE4NDY3OTA2LCJleHAiOjE2MTg0NzE1MDYsImlhdCI6MTYxODQ2NzkwNiwiaXNzIjoiaHR0cHM6Ly8xMjEuMzYuMTkuOTI6NDQzLyIsImp0aSI6Ijc5Mzk4NmZmLTI4MmUtNDA3NS05YjFmLWY3MjI1NGJhOWE1YSIsIm5vbmNlIjoiM2ZhNGI0MGYtYThiMC00MTg4LTg2YTAtMmVmOGRiYjkwYzk1IiwicmF0IjoxNjE4NDY3OTA2LCJzaWQiOiI4ZDY5ODg5OC02ZWZkLTQ3NTMtYWI0NS1jNGI4MTdjMDQyYTUiLCJzdWIiOiI4NzU2MmM3MC05ZDkxLTExZWItOWM4MS1mYTE2M2VmOGUzYzgifQ.rzj_0vQLkzX4OHOAZysbRwcuticqzvLcwHZJnxH6pTbV3-tmgjLM_h4K3mMrT8mqbLGeMc8M4i0mzHchQ6RRWwQbaHnS911voW6o1fYbUi6iafMtgyPcDpjCUiyaSGq0tl2kSjbmJa7kwdmIbDD48nYPjIGhmkflNlPArujiRrSCklxKsAGMIEqoREGuYflGPO3_NvqaRvKBkxo9QuJF3xullM8rf3JJN6TOeYH-tAxALtM2rlDClTHPXCJAkoM0ZjDRDCd3A6l0NYvIkzFGsAtz4wnbOEcwmPqn1Yj1vNWwP4uH0f_x9MLpGIJ1vJAtEyhMcw4OG3qryjEzyq3F-jTAwirnUrqNNznHtGBI1QKl-bavZwuanDkkZW7mYMOFxVR_ZzzReQUFlhaANmGiQVpHQUpzDJJ5rVlxSv9atTWiYaUKgCsQ88o5T4gp6zcu4MUKGvog6I5OH3aruwEB4UTH-0F16NF3_ZPFRhv2frxTt4Jx2lgXBX3dQhKWYEoMvxUwy8jJWnDyPqRKYJI6u8X8KhtvbcefbwwUTnojBEOStcw89OID1Hcqo-C5PyLxFG5FpTYo7N3524AjgXPmEadczSuh76TMQckUSalBtxuK4igOFT8C7mFm1FE6OPjViLse9gWiQUwNWA5aIIJQy0Yivaw0Lgt8ZKYl8EomEgU",
    "scope": "offline openid all",
    "token_type": "bearer"
}

响应说明:

参数名 说明
access_token 访问令牌,可以用于调用其他 OpenDoc API
expirses_in 访问令牌过期时间戳
id_token 注销用户使用的令牌,不需要使用
scope 使用范围
token_type 访问令牌类型,固定为 bearer

至此,已经获取到调用 OpenDoc API 使用的 Access_token。

Postman 截图: 

关于获取 Access_token,需要注意以下事项:

  • /sso 接口不支持并发调用,代码调用时需要加锁

  • Access_token 会在一定时间后过期(一般为1小时),需要业务系统缓存使用并定时(如50分钟)刷新

  • Access_token 建议添加在请求头中使用,格式为 Authorization: Bearer Access_token

  • 使用临时令牌换取 Access_token 不是 AnyShare 自带功能,需要集成开发工程师开发定制版的第三方认证插件后才能使用

请就本文对您的益处进行评级:

相关文章

热门标签

版本发布 在线教学
ai-assistant
chat
support
trial
需求助手 (内容由 AI 大模型生成,请仔细甄别)