全部产品

JWT应用接入

更新时间:2020-08-06 15:47:19

在PDS控制台上,开发者可以创建出一个域(Domain)。

域:拥有独立的访问入口、资源空间、用户体系等。

PDS为每个域提供一套独立的用户体系。

  • 支持OAuth2.0应用接入: 目前支持基于钉钉和RAM子用户的OAuth登录接入。
  • 支持JWT应用接入:支持已有的用户体系的接入,比如已有的web服务想要增加云盘的功能等。

JWT应用介绍

此类应用可以通过私钥计算出一个JWT(JSON Web Token),该JWT具有访问已经配置了公钥的服务端的API的能力(权限)。

1

JWT应用,适合服务端应用访问PDS的数据,比如企业通过自建应用访问企业的数据(数据所有权属于企业)的场景,这个场景不需要最终用户参与授权。

适用场景

适用场景1: 企业A已有独立的账号体系和登录入口,想要使用已有的登录入口结合PDS搭建一套已有独立账号的云存储系统。

适合场景2: 企业A开发一个运维统计应用,用来定期统计一些数据指标。

JWT 应用原理

  • 需要生成一对公私钥。
  • 应用服务端配置私钥,PDS API端配置公钥。
  • 应用服务端可以使用私钥计算出一个JWT Token,这个JWT具有一定的权限,可以直接调用PDS API相应的接口。

目前使用最广泛的场景,就是调用PDS API的GetToken接口,获取任意用户的AccessToken。非常适合已有用户体系接入。

2

下面介绍详细的接入步骤。

接入步骤概览

  • 租户在PDS控制台创建一个JWT应用。
  • 然后生成一对公私钥。公钥保存到PDS服务端,私钥自己复制保存。
  • 使用我们提供的SDK可以通过私钥生成一个有特定权限的并且有时效的JWT。
  • 使用该JWT调用getToken接口换取一个代表用户身份的AccessToken。

详细步骤

(1) 创建域

a1

(2) 创建应用

进入域详情,在应用列表界面,创建一个应用:

a2

(3) 设置公钥

应用创建好后,点击”设置公钥”:

a3

生成公私钥:a4

生成公私钥后,记得复制私钥,自己保存。然后点确定即可。

a5

(4) 服务端计算JWT

需要开发代码。

逻辑在用户登录成功之后,通过私钥计算出JWT。 具体的计算方法:

node.js 参考代码:

  1. const JWT = require('jsonwebtoken');
  2. const privateKeyPEM = '';
  3. var current_time_sec = Math.floor(Date.now()/1000);
  4. var opt = {
  5. iss:'',
  6. sub:'',
  7. sub_type:'',
  8. aud:'',
  9. jti: '',
  10. exp: current_time_sec + 60,
  11. iat: current_time_sec ,
  12. //nbf: '',
  13. auto_create: true,
  14. };
  15. var token = JWT.sign(opt, privateKeyPEM, {
  16. algorithm: 'RS256'
  17. });

opt 参数说明:

字段名 是否必选 类型 描述
iss 必选 String App ID
sub 必选 String User ID、Domain ID
sub_type(扩展字段) 必选 String 账号类型,目前支持填 user、service,此处填user,则sub为userID,签发普通用户accessToken。 此处填service,则sub为domainID,签发domain服务账号accessToken(超级管理员权限)
aud 必选 String Domain ID
jti 必选 String 应用生成JWT的唯一标识,长度16-128位,推荐使用uuid即可
exp 必选 Integer JWT过期时间, Unix Time,单位秒,最多在当前时间基础上加60秒
iat 可选 Integer 签发时间,Unix Time,单位秒,在此时间之前无法使用,如:1577682075
nbf 可选 Integer 生效时间,Unix Time,单位秒,不指定则默认生效
auto_create(扩展字段) 可选 Boolean 如果用户不存在,则自动创建,默认不创建用户。

(5) 通过JWT换取任意用户的AccessToken

调用PDS API换取。

  1. POST /v2/oauth/token
  2. Content-Type: application/x-www-form-urlencoded
  3. grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer&client_id=${APP_ID}&assertion=xxxxxxxxxx

请求参数说明:

字段名 是否必选 类型 描述
grant_type 必选 String 申请授权的类型,此处应为字符串常量: urn:ietf:params:oauth:grant-type:jwt-bearer
client_id 必选 String 应用ID
assertion 必选 String 上一步骤计算出来的JWT

返回 token json 样例

  1. {
  2. access_token: 'eyJh****eQdnUTsEk4',
  3. refresh_token: 'kL***Lt',
  4. expires_in: 7200,
  5. token_type: 'Bearer'
  6. }

浏览器端拿到用户的AccessToken后,就可以直接调用PDS API了。

(6) 使用 Basic UI (可选)

如果您不想自己开发UI,而我们官方提供的Basic UI可以满足您的要求,可以直接使用Basic UI。

原理: 使用window.open 打开 basic ui,postMessage传递AccessToken过去即可。

示例代码:

  1. const ENDPOINT = `https://${domain_id}.apps.alicloudpds.com`
  2. window.addEventListener('message', onMessage, false)
  3. var win = window.open(ENDPOINT + '/accesstoken')
  4. async function onMessage(e) {
  5. if (e.data.code == 'token' && e.data.message == 'ready') {
  6. var result = await getToken();// 从服务端获取 AccessToken
  7. //result = {"access_token": ...}
  8. win.postMessage({
  9. code: 'token',
  10. message: result
  11. }, '*')
  12. window.removeEventListener('message', onMess)
  13. }
  14. }

附录:

服务端获取AccessToken 的 Node.js 代码实现:

  1. const fs = require('fs')
  2. const JWT = require('jsonwebtoken');
  3. const axios = require('axios')
  4. init()
  5. async function init() {
  6. try {
  7. //这几个变量需要根据实际情况填写
  8. var params = {
  9. domain_id: '${DOMAIN_ID}',
  10. client_id: '${APP_ID}',
  11. user_id: '${USER_ID}',
  12. privateKeyPEM: "${PRIVATE_KEY_PEM}"
  13. };
  14. var obj = await JWTGetUserToken(params)
  15. var tokenInfo = obj.data
  16. console.log(tokenInfo)
  17. } catch (e) {
  18. if (e.response) {
  19. console.log(e.response.status)
  20. console.log(e.response.headers)
  21. console.log(e.response.data)
  22. } else {
  23. console.log(e)
  24. }
  25. }
  26. }
  27. async function JWTGetUserToken({ domain_id, client_id, user_id, privateKeyPEM }) {
  28. var now_sec = parseInt(Date.now()/1000)
  29. var opt = {
  30. iss: client_id,
  31. sub: user_id,
  32. sub_type: 'user',
  33. aud: domain_id,
  34. jti: Math.random().toString(36).substring(2),
  35. exp: now_sec + 60,
  36. // iat: now_sec,
  37. // nbf: '',
  38. auto_create: true,
  39. };
  40. var token = JWT.sign(opt, privateKeyPEM, {
  41. algorithm: 'RS256'
  42. });
  43. const PRE = `https://${domain_id}.api.alicloudpds.com`
  44. return await axios({
  45. method: 'post',
  46. url: PRE + '/v2/oauth/token',
  47. headers: {
  48. 'Content-Type': 'application/x-www-form-urlencoded'
  49. },
  50. data: params({
  51. grant_type: 'urn:ietf:params:oauth:grant-type:jwt-bearer',
  52. client_id: client_id,
  53. assertion: token
  54. })
  55. })
  56. }
  57. function params(m){
  58. const params = new URLSearchParams();
  59. for(var k in m){
  60. params.append(k, m[k]);
  61. }
  62. return params;
  63. }