本次飞书网页应用代码示例采用uni-app框架,注重代码的思想,触类旁通
1.1 网页应用 JSSDK鉴权流程
1.1.1 获取tenant_access_token
- \src\manifest.json - H5端的跨域设置
"h5": {
"devServer": {
"proxy": {
"/api": {
"target": "https://open.feishu.cn/open-apis/auth/v3/",
"pathRewrite": {
"^/api": ""
}
},
}
}
}
- \src\pages\index\index.vue - 获取企业自建应用access_token
getTenantToken() {
uni.request({
url: '/prefix/tenant_access_token/internal',
method: 'POST',
data: {
app_id: 'cli_a0f79da3fef8d014',
app_secret: 'RoO3nYOhQu7gbtTjCXwlnyTMx0BepkVy',
},
success: (res) => {
// 存储tenant_access_token
uni.setStorage({
key: 'tenantToken',
data: 'Bearer ' + res.data.tenant_access_token,
success: (res) => {
console.log('tenantToken已存储至Storage');
},
});
},
fail: (err) => {
console.log(err);
},
});
}
获取到的 tenant_access_token是请求获取jsapi_ticket的前提
1.1.2 获取jsapi_ticket
- \src\manifest.json - H5端的跨域设置
"h5": {
"devServer": {
"proxy": {
"/api": {
"target": "https://open.feishu.cn",
"pathRewrite": {
"^/api": ""
}
},
}
}
}
- \src\pages\index\index.vue - 获取JSAPI临时凭证jsapi_ticket
getJsApiTicket() {
let tenantToken = '';
uni.getStorage({
key: 'tenantToken',
success: (res) => {
tenantToken = res.data;
},
});
// 获取jsapi_ticket
uni.request({
url: '/api/open-apis/jssdk/ticket/get',
method: 'POST',
header:{
'Authorization':tenantToken
},
success: (res) => {
uni.setStorage({
key:'ticketToken',
data:'Bearer ' + res.data.data.ticket
});
},
fail: (err) => {
console.log(err);
}
});
}
1.1.3 计算签名
- 计算签名需要获取以下参数
参数 | 数据类型 | 描述 |
---|---|---|
noncestr | string | 随机字符串 |
jsapi_ticket | string | 上一步骤获得的ticket |
timestamp | number | 当前时间戳,ms级 |
url | string | 当前网页的URL,不包含#及其后面部分 |
- \src\utils\authentication\noncestr.js - 生成noncestr参数方法
export default function nonceStr(e) { // e代表生成的字符个数
e = e || 32;
var t = "ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz0123456789",
a = t.length,
noncestr = "";
for (let i = 0; i < e; i++) noncestr += t.charAt(Math.floor(Math.random() * a));
return noncestr;
}
- 安装生成 signature的依赖包
npm install js-sha1
- \src\utils\authentication\getSignature.js - 生成signature参数方法
const sha1 = require('js-sha1');
/**
* 计算h5sdk.config的签名参数
*
* @param jsticket 之前获取的jsticket
* @param nonceStr 随机字符串
* @param timeStamp 当前时间戳
* @param url 调用h5sdk.config的当前页面URL
* @return
*/
export default function getSignature(jsticket, nonceStr, timeStamp, url) {
const verifyStr = `jsapi_ticket=${jsticket}&noncestr=${nonceStr}×tamp=${timeStamp}&url=${url}`;
return sha1(verifyStr);
}
- \src\pages\index\index.vue - 引用自定义方法
import nonceStr from '../../utils/authentication/noncestr.js';
import getSignature from '../../utils/authentication/getSignature.js';
- 配置飞书H5可信域名以及IP白名单,按照飞书开发文档进行配置即可:H5可信域名配置说明 和 IP白名单配置说明
飞书H5可信域名必须 和 飞书开放平台[我的后台] / 应用功能 / 网页 / 网页配置 的内容保持一致
- \src\pages\index\index.vue - 调用config接口鉴权
getJSSDK() {
let noncestr = nonceStr(16); // 随机字符串
let jsapi_ticket; // jsapi_ticket
let timestamp = Date.now();
let url = 'http://10.1.14.136:8080/';
uni.getStorage({ key : 'ticketToken', success:(res) => { jsapi_ticket = res.data; } });
let signature = getSignature(jsapi_ticket, noncestr, timestamp, url);
window.h5sdk.ready(function() {
window.h5sdk.config({
appId: 'cli_a0f79da3fef8d014', // 必填,应用ID
timestamp:timestamp , // 必填,生成签名的时间戳,ms级
nonceStr:noncestr, // 必填,生成签名的随机串
signature:signature, // 必填,签名
jsApiList : [
'biz.user.getUserInfo',
'device.health.getStepCount',
'biz.user.openDetail',
'biz.contact.open',
'device.base.getSystemInfo',
'biz.util.getClipboardInfo',
'biz.util.openDocument',
'biz.util.downloadFile',
'device.geolocation.get',
'device.geolocation.start',
'device.geolocation.stop',
'biz.user.getUserInfoEx',
'device.connection.getNetworkType'
], // 必填,需要使用的jsapi列表。
onSuccess: function(result) {
alert("JSSDK已获取权限");
},
onFail: function(err) {
alert("JSSDK权限获取失败",err);
}
});
});
}
飞书通过JSSDK鉴权获取的jsapi的运行效果只能在飞书内置浏览器中运行
- 按顺序依次点击获取权限按钮
- 获取JSSDK临时权限结果