3.1.11 • Published 3 months ago

@geega-components/geega-guc-js-next-sdk v3.1.11

Weekly downloads
-
License
ISC
Repository
-
Last release
3 months ago

geegaguc-JavaScript-Next-SDK

(新一代)基于 Geega GUC 登陆 API 开发的前端 JavaScript SDK

更多版本信息

请升级/更新前阅读:JS-SDK修改记录

GUC-JS-SDK-2.0(长期维护-不再添加新功能)

后端SDK接入指南

快速导航

概述

GeegaGuc-JavaScript-SDK (下文简称为 JS-SDK)适用于 :IE10、Edge、Chrome、Firefox、Safari 等浏览器,基于 GeegaGuc 登陆 API 构建。开发者基于 JS-SDK 方便一键接入登陆。

使用前须知

1、sdk 3.0 向下兼容 2.0 token 存储方式都支持 cookie,2.0 只支持 cookie 方式,3.0 支持 localStroage 和 cookie 两种方式。

2、初始化配置参数 env 必填

3、SDK 2.0 会向共享区域(这里称为 hub) 发送 token,并存储在共享区域。

4、父子应用的场景下,假设父应用使用的是 2.0cookie 方式存储 token,子应用使用 3.0 localStroage 方式存储 token,子应用可以通过 getToken 拿到,共享区域的 token

5、父子应用只能初始化一次 init 方法 (guc.init 只能执行一次,多次执行会出现不可预知的问题) 父子应用场景下,建议把 GUC 实例挂载到 window 对象上,父子应用共享一个 guc 实例对象

3.0 sdk 工作流程图

avatar

功能简介

  • 登陆
  • 注销
  • 刷新 token
  • 检查 token 是否有效
  • 检查是否登录
  • 获取用户信息
  • 获取应用菜单列表(仅 B 端体系有效)
  • 获取应用按钮列表(仅 B 端体系有效)

准备

  • JS-SDK 依赖服务端颁发布 API
  • 需要依赖 axios jwt-decode

引入

支持以下两种安装方式

  • 使用 NPM 安装

    NPM 的全称是 Node Package Manager,

    更多信息

    Note:

    • 依赖 axios jwt-decode
    • @geega-components/geega-guc-js-next-sdk 源地址为:http://npm.geega.com/
     yarn add @geega-components/geega-guc-js-next-sdk
    const Guc = require('@geega-components/geega-guc-js-next-sdk')
    // or
    import Guc from '@geega-components/geega-guc-js-next-sdk'

参数说明

env/server 属性说明

env(必传)与server(选填)是初始化sdk实例的两个重要属性,env内部内置了四个枚举 [dev,test,demo,prod],每个会映射一个GUC服务地址,映射的GUC服务地址的优先级低server属性设置服务地址。也许大家有个疑问那直接设置server就行了,为什么 env 是必填写,主要有原因如下: 临时凭证信息采用的cookie主域方式共享【js-sdk-3.01已不再使用cookie共享,为了兼容其他使用sdk2.0场景,建议配置env】,但由于外部环境及不可控的原因,测试(https),演示,线上都是一样主域名,导致共享无法区分,所以需要使用env用来创建不同环境不同的 cookie key,登陆多环境多端的情况下会容易导致凭证cookie超大的问题【用户层面一般不会出现,因为它最多两端(B端与C端)一环境(线上环境)】。预留后期不同环境的其他逻辑隔离需要

//如果不存在不同环境使用同一主域的情况下,不希望埋不同env的值,可自定义env,
new Guc({
    // 可以给你的凭证key 加上你喜欢的标识 sdk按一定规则结合设置env值生成key。备注:如果env不是[dev,test,demo,prod]之一 注意此时必须通过server来设置不同环境服务。
    //例如 : geely  ====生成===》 c-geely-guc3-token
    env: 'geely',//自定义集团env
    appId: '1',
    server: 'https://guc-gateway.test.geely.com', //集团GUC地址
});

对应关系如下:

envserver备注
devhttp://guc3-api.cloud-dev.geega.comGUC团队使用,无法保障稳定,推荐使用联调环境
testhttps://guc3-api-test.geega.com联调环境
demohttps://guc3-api-demo.geega.com演示环境
prodhttps://guc3-api.geega.com生产环境

Props

属性类型默认值说明
serverurl string-GUC登陆服务地址,优先级高于通过配置 env 获取的GUC登陆服务地址(非必传)。注意:当 env 不是 【env,test,demo,prod】 之一时,server 必传
envstring'prod'运行环境 env/test/demo/prod 注意:server 优先级高于 env 的默认配置 ,如果你设置了 server,env也是必填写,因为SDK还是需要知道你运行的环境,方便我们做一些处理。(必传)
appIdstring-应用 ID,需要能力平台提供 (必传)
isClientBooleanfalse【2.0.x 以上版本】 C 端体系登陆 (非必传)
detectionFrequencynumber60 * 1000【2.0.5 以上版本】用户是否活跃检测频率 默认 60s 单位:(毫秒)(非必传) 强烈建议使用默认值
viewPageFrequencynumber2 60 1000【2.0.5 以上版本】页面活跃间隔检测频率 默认 120s 单位:(毫秒)(非必传) 强烈建议使用默认值
liveTimeOutnumber60 1000 6【2.0.5 以上版本】活跃存活时长 默认 存活 6min 单位:(毫秒)(非必传) 强烈建议使用默认值
remainingExpirationBoundarynumber1000 60 20【2.0.5 以上版本】 刷新时间边界 默认 20min 单位:(毫秒)(非必传) 强烈建议使用默认值
logoutExpirationBoundarynumber1000 60 10【2.0.5 以上版本】 退出时间边界 默认 10min 单位:(毫秒)(非必传) 强烈建议使用默认值
minTimenumber1000 60 2【2.0.5 以上版本】 最小激活时间 默认 2min 单位:(毫秒)(非必传) 强烈建议使用默认值
isAutoRefsTokenBooleantrue是否开启自动刷新 token (非必传) 默认开启 建议使用默认值
isStoreCookieBooleanfalse是否在当前域通过 cookie 方式 存储 token 凭证,默认不存储
enableCookieModeBooleanfalse是否开启 cookie 模式存储凭证 ,默认不启用 不支持 cross-storage 情况下强制开启.默认关闭
isAutoClearCodeBooleantrue是否自动清理url上的code,默认清理
GUCAPISUCEESSCODEstring"0000"依赖服务成功状态

Methods

属性参数返回值说明
refreshTokenrefreshToken:string ,isAutoLogout=truePromise.resolve(refreshInfo)刷新 token 参数:refreshToken 默认从本地获取,
getUserInfoisUseCache:BooleanPromise.resolve(userInfo)获取用户信息 参数: isUseCache:true / false 从缓存获取,默认 false
verifyTokenstring = null , isAutoLogout=truebooleanPromise.resolve(Boolean)检查 token 是否有效 ()=>Promise.resolve(Boolean) eg:guc.verifyToken(‘Your token’,false)); // 验证token,无效情况下不自动退出
init(isAutoLogin,callback )Promise.resolve(Boolean)初始化时否自动登录 参数: isAutoLogin:true/false(非必传:默认为 true) callback:登录后执行回调
getCookiecookieName:stringstring通过 cookie key 获取 cookie value
getToken-Promise.resolve(token)获取当前登录 token
decodeJwt-string解析 token
decodeExp-string解析 token 【不建议使用,后续会计划,3.0 后续计划移除】建议使用 decodeJwt
DelCookie--删除当前域下 cookie 【不建议使用,3.0 后续计划移除】替代方案建议你使用 clearGUCBrowserCertificate
clearGUCBrowserCertificate--是 Promise 函数仅清除浏览器端 GUC 一些凭证与定时任务,并清除服务器端凭证 ,浏览器端的清理不代表服务端凭证失效,退出使用 logout
login(redirectUri)=>void-登录方法 redirectUri 自定义登录回调地址(非必传),默认当前地址
logout(redirectUri,isNeedLogin)=>void-退出方法 redirectUri 自定义登录回调地址(非必传),默认当前地址,退出后是否需要再次登陆 isNeedLogin 默认:false
getMenusTree(appId,code?)Promise.resolve(tree)isClient:true下无效,获取应用菜单树。 appId 必传 , code(选填):应用菜单唯一标识,如果设置将优先获取该标识下所有菜单
getButtonsList(appId)Promise.resolve(buttons)isClient:true下无效 获取应用按钮列表 appId 必传
storeCredentialsToHub(token,refreshToken,tokenTimeOut,tokenExpiresTime)Promise存储凭证。tokenExpiresTime计算规则:tokenExpiresTime:decodeExp(token)?.exp * 1000
pushHubServerToSDKV2CredentialsPromisehub 凭证 同步 cookie 存储
pushSDKV2CredentialsToHubServerPromisecookie 凭证 同步 hup 存储
getValuesByKeyFromHubServerOrCookiekey?: string string[],options = {model:"cookie/storage",domain:""}Promise获取已存储凭证及记录信息tokenInfo:{token,refreshToken tokenTimeOut,tokenExpiresTime,userActive,userMoveMouseLastTime}
getValuesByKeyFromHubServerkey?: string string[]Promise获取已存储凭证及记录信息 token,refsToken,tokenTimeout,tokenExpires,userActive,userMoveLastTime
getConfigInfo()=> Promise.resolve(configInfo)Promise.resolve(configInfo)获取SDK基础配置与版本等信息

使用 DEMO

ES6+ 环境使用

// ES6+ 使用方式

import Guc from '@geega-components/geega-guc-js-next-sdk';

const init = async ()=>{
  //初始化
  const guc = new Guc({
    env: 'test',
    appId: '1691562535',
    // autoRefsTokenTime: 5, //刷新token时长秒默认60秒 isAutoRefs 为 true有效
    // isAutoRefsToken: true, //是否刷新token
    server: 'https://guc3-api-test.geega.com',
    // isClient:true
    // 多语言配置 en-US  zh-CN
    axiosRequestConfig: {
      headers: {
        'Accept-Language': 'en-US',
      },
    }
  });
  
  let isLogin = await guc.init(true, () =>{}, (data) =>{
    // 初始化验证异常,执行退出逻辑
    if (data?.code == '0401') {
      guc.logout();
    }
  });

  if(isLogin){
    //dome something
  }

  const token = await guc.getToken();

  //获取配置的菜单路由
  //const menus = await guc.getMenusTree('1')

  guc.getMenusTree('1','geega_guc_role').then((menus)=>{
    console.log(menus)
  })

  //获取配置的菜单路由
  //const btns = await guc.getButtonsList('1')
  guc.getButtonsList('1').then((btns)=>{
    console.log(btns)
  })

}

init()

ES5 环境使用

  <button id="login">登录</button>
  <button id="logout">退出</button>
  <button id="istoken">token是否有效</button>
  <button id="getuser">获取用户信息</button>
  <button id="pushsdktohup">推送cookie到hup</button>
  <button id="pushhuptosdk">推送hup到cookie</button>
  <button id="refstoken">刷新token</button>
  <button id="getmenu">获取菜单</button>
  <button id="getbtn">获取按钮</button>
  <button id="getcookie">获取并解析Token</button>
  <button id="storeCredentialsToHub">更新凭证</button>
  <button id="getValuesByKeyFromHubServerOrCookie">获取凭证</button>
  <button id="decodeexp">解析code过期时长</button>
  <button id="getbcookie">从浏览器获取cookie</button>
  <button id="delbcookie">删除浏览器cookie</button>
  <button id="clearbrowsercertificate">清理GUC所有浏览器凭证</button>
  <button id="configinfo">获取SDK配置信息</button>

<script>

var login = document.getElementById('login');
var logout = document.getElementById('logout');

var pushsdktohup = document.getElementById('pushsdktohup');

var pushhuptosdk = document.getElementById('pushhuptosdk');

var storeCredentialsToHub = document.getElementById('storeCredentialsToHub');

var getValuesByKeyFromHubServerOrCookie = document.getElementById('getValuesByKeyFromHubServerOrCookie');

var refstoken = document.getElementById('refstoken');
var istoken = document.getElementById('istoken');
var getuser = document.getElementById('getuser');
var getmenu = document.getElementById('getmenu');
var getbtn = document.getElementById('getbtn');
var getcookie = document.getElementById('getcookie');
var decodeExp = document.getElementById('decodeexp');
var getbcookie = document.getElementById('getbcookie');
var delbcookie = document.getElementById('delbcookie');
var clearbrowsercertificate = document.getElementById('clearbrowsercertificate');
var configInfo = document.getElementById('configinfo');

(async () => {
  // 初始化登陆对象
  const guc = new Guc({
    env: 'test',
    appId: '1',
    // enableCookieMode:true,
    // server:'http://guc3-api-geega-dev.cloud-dev.geega.com', //自定GUC
    // isClient: false,
    // en-US / zh-CN
    axiosRequestConfig: {
      headers: {
        'Accept-Language': 'en-US',
      },
    }
  });

  let isLogin = await guc.init(false);

  if (isLogin) {
    login.style.display = 'none';
  } else {
    login.style.display = 'block';
  }

  decodeExp.onclick = async function () {
    console.log(guc.decodeJwt(await guc.getToken()).exp);
  };

  login.onclick = function () {
    if (!isLogin) {
      guc.login();
    }
  };

  pushsdktohup.onclick = async function () {
     await guc.pushSDKV2CredentialsToHubServer()
  };

  pushhuptosdk.onclick = async function () {
    await guc.pushHubServerToSDKV2Credentials()
  };

  logout.onclick = function () {
    guc.logout();
  };
  getuser.onclick = async function () {
    // console.log(await guc.getUserInfo());
    guc.getUserInfo().then((userInfo) => {
      console.log(userInfo);
    });
  };

  refstoken.onclick = function () {
    guc.refreshToken().then(
      (res) => {
        console.log(res);
      },
      () => {
        throw new Error('refreshToken error');
      }
    );
  };
  istoken.onclick = async function () {
    const verifyRes = await guc.verifyToken(null,false)
    console.log('verifyRes',verifyRes);
  };
  getmenu.onclick = async function () {
    // console.log(await guc.getMenusTree('1'));
    guc.getMenusTree('1','geega_guc_role').then((menus) => {
      console.log(menus);
    });
  };
  getbtn.onclick = async function () {
    guc.getButtonsList('1').then((btns) => {
      console.log(btns);
    });
  };
  getcookie.onclick = async function () {
    const token =await guc.getToken()
    console.log(token);
  };

  storeCredentialsToHub.onclick = async function () {
    const v = await guc.getValuesByKeyFromHubServerOrCookie(
      guc.config.enableCookieMode ? guc.REFRESH_TOKENV2 : guc.REFRESH_TOKEN
    );
    guc.refreshToken().then(
     async (res) => {
      if(res.code === guc.config.GUCAPISUCEESSCODE)
        await guc.storeCredentialsToHub(
          res.data.token,
          res.data.refreshToken,
          res.data.tokenTimeOut,
          res.data.tokenExpiresTime
        );
      },
      () => {
        throw new Error('refreshToken error');
      }
    );
  };

  getValuesByKeyFromHubServerOrCookie.onclick = async function () {

    const v = await guc.getValuesByKeyFromHubServerOrCookie(
      guc.config.enableCookieMode ? guc.TOKEN_TIMEOUTV2 : guc.TOKEN_TIMEOUT
    );
    const tokenTimeOut = v.tokenTimeOut;

    console.log('tokenTimeOut',tokenTimeOut);

    const v2 = await guc.getValuesByKeyFromHubServerOrCookie("",{
      model:"storage",
      domain: "",
    })
    console.log('getValuesByKeyFromHubServerOrCookie',v2);
  };

  getbcookie.onclick = function () {
    //const token =await guc.getToken()
    console.log(guc.getCookie('b-test-guc3-token'));
  };

  delbcookie.onclick = function () {
    guc.DelCookie(window.location.hostname, '/');
  };

  clearbrowsercertificate.onclick = function () {
    guc.clearGUCBrowserCertificate();
  };

  configInfo.onclick = function () {
    guc.getConfigInfo().then((config) => {
      alert(JSON.stringify(config));
    });
  };
})();
      </script>
    </body>

F&Q


1、cross-storage无法订阅成功,导致降级使用Cookie存储

环境信息

GUC-SDK:@geega-components/geega-guc-js-next-sdk v3.0.88

浏览器:chrome/108.0.5359.124

问题描述:

cross-storage会嵌入iframe来加载hub并且使用postmessage来传输信息,在使用iframe加载hub的过程中,可能会因为http协议中请求hub的请求头与响应头之间的编码差异导致hub无法加载成功,从而使得cross-storage.onConnect报错,最终造成降级使用Cookie。

可参考官方文档

问题详情:

请求:/api/guc/view/token/hub

Http Request Header中设置了:Accept-Encoding: gzip, deflate

Http Response未进行gzip压缩

最终导致请求内容在chrome浏览器端无法解析,使得降级为Cookie存储。

体验影响:

  • 由于数据均使用Cookie存储,导致Cookie内容超长,所有业务请求400
  • hub无法注册成功可能导致b-token-expires-time-key和b-guc3-is-active无法共享,导致业务系统偶发性退出到登录界面。此问题可结合GUC SDK中的_keepUseViewPageHandler方法分析

解决方案:

  • GUC-Service对于/api/guc/view/token/hub进行gzip压缩后返回
  • 使用nginx代理/api/guc/view/token/hub请求并且开启gzip压缩