References
Feishu Developer Platform webpage application authentication
Feishu webpage authentication process
Problem Description
Feishu nests web applications. The web application needs to use Feishu's api, but most of Feishu's jsapi needs to be authenticated before it can be used.
solution
Perform authentication step by step according to the documentation on the Feishu Developer Platform. The first and second steps are the work done by the server. The server can write an interface and return the jsapi_ticket we obtained.
Step 1: Get access_token
Step 2: Get jsapi_ticket
Step 3: Calculate the signature
The signature generation rules are as follows:
The fields involved in the signature include noncestr (random string), valid jsapi_ticket, timestamp (timestamp), url (the URL of the current web page, excluding # and its following parts).
After sorting all the parameters to be signed according to the ASCII code of the field name from small to large (lexicographical order), use the URL key-value pair format (ie key1=value1&key2=value2…) to concatenate into a string. It should be noted here that all parameter names are in lowercase characters. Do sha1 encryption on the spelled string.
Field names and field values are taken as raw values without URL escaping.
Example:
noncestr=Y7a8KkqX041bsSwTjsapi_ticket=617bf955832a4d4d80d9d8d85917a427timestamp=1510045655000url=https://m.haiwainet.cn/ttc/3541093/2018/0509/content_31312407_1.html
According to the order of jsapi_ticket, noncestr, timestamp, url, use the URL key-value pair format (ie key1=value1&key2=value2...) to concatenate the string verifyStr:
jsapi_ticket=617bf955832a4d4d80d9d8d85917a427&noncestr=Y7a8KkqX041bsSwT×tamp=1510045655000&url=https://m.haiwainet.cn/ttc/3541093/2018/0509/conte
Calculate signature
After getting the jsapi_ticket returned by the backend
get url
let url = window.location.href.split('#')[0]
get timestamp
let timestamp = new Date().getTime()
Generate a 16-bit random string
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)
splice signature
//jsapi_ticket 是第一二步服务端拿到的jsapi_ticket
const verifyStr = `jsapi_ticket=${
jsapi_ticket}&noncestr=${
nonceStr}×tamp=${
timestamp}&url=${
url}`
Perform sha1 encryption
npm i sha1
let signature = sha1(verifyStr)
Authenticate
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))
},
})
full code
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))
},
})
}