参考资料
飞书开发者平台网页应用鉴权
飞书网页鉴权流程
问题描述
飞书嵌套网页应用,网页应用里需要用到飞书的api,但是大部分的飞书的jsapi是需要进行鉴权后才能使用的。
解决方案
根据飞书开发者平台的文档一步一步来进行鉴权。第一步和第二步是服务端做的工作,服务端可以写个接口,返给我们获取到的jsapi_ticket
步骤一:获取 access_token
步骤二:获取 jsapi_ticket
步骤三:计算签名
签名生成规则如下:
参与签名的字段包括 noncestr(随机字符串),有效的 jsapi_ticket,timestamp(时间戳), url(当前网页的URL,不包含 # 及其后面部分)。
对所有待签名参数按照字段名的 ASCII 码从小到大排序(字典序)后,使用 URL 键值对的格式(即key1=value1&key2=value2…)拼接成字符串。这里需要注意的是所有参数名均为小写字符。对拼成的字符串做sha1 加密。
字段名和字段值都采用原始值,不进行 URL 转义。
示例:
noncestr=Y7a8KkqX041bsSwTjsapi_ticket=617bf955832a4d4d80d9d8d85917a427timestamp=1510045655000url=https://m.haiwainet.cn/ttc/3541093/2018/0509/content_31312407_1.html
根据 jsapi_ticket、noncestr、timestamp、url 的顺序,使用 URL 键值对的格式(即key1=value1&key2=value2…)拼接成字符串 verifyStr:
jsapi_ticket=617bf955832a4d4d80d9d8d85917a427&noncestr=Y7a8KkqX041bsSwT×tamp=1510045655000&url=https://m.haiwainet.cn/ttc/3541093/2018/0509/conte
计算签名
拿到后端返回的jsapi_ticket后
获取url
let url = window.location.href.split('#')[0]
获取时间戳
let timestamp = new Date().getTime()
生成16位随机字符串
const randomString = (e) => {
e = e || 32
let t = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678',
a = t.length,
n = ''
for (let i = 0; i < e; i++) n += t.charAt(Math.floor(Math.random() * a))
return n
}
let nonceStr = randomString(16)
拼接签名
//jsapi_ticket 是第一二步服务端拿到的jsapi_ticket
const verifyStr = `jsapi_ticket=${
jsapi_ticket}&noncestr=${
nonceStr}×tamp=${
timestamp}&url=${
url}`
进行sha1加密
npm i sha1
let signature = sha1(verifyStr)
进行鉴权
window.h5sdk.config({
timestamp: timestamp,
nonceStr: nonceStr,
signature: signature,
appId: Enums.APPID,//这里是自创应用的appid
jsApiList: ['biz.navigation.close', 'biz.util.share'],
onSuccess: () => {
},
onFail: (res) => {
alert(JSON.stringify(res))
},
})
完整代码
import sha1 from 'sha1'
const randomString = (e) => {
e = e || 32
let t = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678',
a = t.length,
n = ''
for (let i = 0; i < e; i++) n += t.charAt(Math.floor(Math.random() * a))
return n
}
let url = window.location.href.split('#')[0]
let timestamp = new Date().getTime()
// 生成16位随机字符串
let nonceStr = randomString(16)
const verifyStr = `jsapi_ticket=${
jsapi_ticket}&noncestr=${
nonceStr}×tamp=${
timestamp}&url=${
url}`
window.h5sdk.config({
timestamp: timestamp,
nonceStr: nonceStr,
signature: sha1(verifyStr),
appId: Enums.APPID,//自建网页应用的appId
jsApiList: ['biz.navigation.close', 'biz.util.share'],
onSuccess: () => {
},
onFail: (res) => {
alert(JSON.stringify(res))
},
})
}