釘釘JSAPI前端鑒權


釘釘二次開發分為如下表所示三種類型的開發,只有企業內部應用才需要對JSAPI鑒權。

類型

開發方式

JSAPI鑒權

應用場景

第三方企業應用

E應用開發

不需要

用於發布到釘釘應用市場,供廣大用戶下載,應用可選收費或免費,需要收取保證金,並進行應用審核

企業內部應用

H5開發,8月中旬也開始支持E應用開發

需要

只能企業內部應用,不能發布到釘釘市場

第三方個人應用

E應用開發

需要

應用與企業不掛鈎,服務於個人

先來看一下釘釘官網給出的JSAPI鑒權的流程,它分為四個步驟:

  1. 獲取token
  2. 獲取ticket
  3. 獲取數字簽名
  4. 設置權限

查看釘釘開發文檔,它給出了兩個JSAPI的鑒權demo,分別是java和php的,需要前后端配合,而本文講述的是純前端JSAPI鑒權,完全實現前后端分離。

下面的代碼將用到以下三個js依賴包:

import CryptoJS from 'crypto-js'; // 加密,用於生成數字簽名
import * as dd from "dingtalk-jsapi"; // 釘釘JSAPI
import axios from "axios"; // HTTP請求

 提示:下面的代碼,用了ES6和ES7的一些語法,沒接觸過的朋友,可自行百度

1、獲取token

首先根據corpid和corpsecret參數,從釘釘服務器獲取token。

/**
 * 獲取token信息
 * @param {Object} params {corpid, corpsecret}
 */
async function getToken(params) {
    return await axios.get('/proxy/gettoken', {
            params
        })
        .then(function(response) {
            return response.data.access_token;
        });
}

 

細心的朋友會發現,axios請求的URL並沒有直接指定 https://oapi.dingtalk.com/gettoken,這是因為直接寫這個URL,會存在跨域問題,因此,這里我們用了代理。

代理可以采用nginx代理或者node代理,這里推薦用node代理。

因為需要代理的請求是https請求,本人也沒跑通nginx代理https請求,如果有哪位朋友跑通了nginx代理的,麻煩告知一聲,也學習以下。

2、設置代理

如果采用vue-cli創建的項目,可以直接在proxyTable中配置,如下:

 proxyTable: {
     '/proxy': {
        target: 'https://oapi.dingtalk.com',
        secure: false,
        // 設置跨域
        changeOrigin: true,
        pathRewrite: {
          '^/proxy': ''
        }

     }
  }

 

不過上面的配置只能在dev開發環境中使用,如果需要在生產環境中使用,還是需要自己寫nodejs代碼實現,如下:

var express = require('express');
var proxy = require('http-proxy-middleware');

var app = express();

app.use('/proxy', proxy({
    target: 'https://oapi.dingtalk.com',
    changeOrigin: true,
    pathRewrite: {
        '^/proxy': ''
      }
    }));
app.listen(3000);

 

 這代碼量是不是很少,隨便百度下都搞定。

3、獲取ticket

根據上面獲取的access_token,從釘釘服務器獲取ticket。

/**
 * 獲取ticket信息
 * @param {Object} params {access_token}
 */
async function getJsticket(params) {
    return await axios.get('/proxy/get_jsapi_ticket', {
            params
        })
        .then(function(response) {
            return response.data.ticket;
        });
}

 

4、獲取數字簽名

釘釘官網的demo是后台實現生成數字簽名,通過crypto-js前端加密庫就可以將這個功能移植到前端來。

ticket是上面生成的;

nonce可以是任何字符串;

timeStamp是當前時間戳;

url是當前訪問的URL地址,不包括#及后面的部分,特別注意這個參數,別搞錯了。如果設置錯了,可以通過下面的dd.error輸出查看釘釘服務器獲取的URL地址

/**
 * 獲取簽名信息
 * @param {*} ticket
 * @param {*} nonce
 * @param {*} timeStamp
 * @param {*} url
 */
function getJsApiSingnature(ticket, nonce, timeStamp, url) {
    let plainTex = "jsapi_ticket=" + ticket + "&noncestr=" + nonce + "&timestamp=" + timeStamp + "&url=" + url;
    let signature = CryptoJS.SHA1(plainTex).toString();
    return signature;
}

 

 

5、設置權限

通過dd.config設置需要的權限

// 步驟4:設置權限
    dd.config({
        agentId: agentId,
        corpId: corpid, //必填,企業ID
        timeStamp: timeStamp, // 必填,生成簽名的時間戳
        nonceStr: nonce, // 必填,生成簽名的隨機串
        signature: signature, // 必填,簽名
        jsApiList: jsApiList // 必填,需要使用的jsapi列表,注意:不要帶dd。
    });

 

jsApiList是權限列表,如:

var jsApiList = [
    'biz.user.get',
    'device.geolocation.get',
    'biz.util.uploadImage'
];

 

6、驗證

上面配置成功之后,就能調用JSAPI中需要鑒權的功能了,下面以獲取當前地理位置為例說明:

/**
 * 測試代碼,通過調用位置服務,測試鑒權是否正確
 */
function testJsApi() {
    // 獲取位置
    dd.ready(() => {
        dd.device.geolocation.get({
            targetAccuracy: 200,
            coordinate: 1,
            withReGeocode: false,
            useCache: true, //默認是true,如果需要頻繁獲取地理位置,請設置false,
            onSuccess: result => {
                /* 高德坐標 result 結構
                    {
                        longitude : Number,
                        latitude : Number,
                        accuracy : Number,
                        address : String,
                        province : String,
                        city : String,
                        district : String,
                        road : String,
                        netType : String,
                        operatorType : String,
                        errorMessage : String,
                        errorCode : Number,
                        isWifiEnabled : Boolean,
                        isGpsEnabled : Boolean,
                        isFromMock : Boolean,
                        provider : wifi|lbs|gps,
                        accuracy : Number,
                        isMobileEnabled : Boolean
                    }
                    */
                console.log(result)
                alert("success: " + JSON.stringify(result))
            },
            onFail: err => {
                console.log(err)
                alert("error: " + JSON.stringify(err))
            }
        });
    });

    // 查看鑒權錯誤信息
    dd.error(function(err) {
        alert('dd error: ' + JSON.stringify(err));
    });
}

 

如果鑒權失敗,則dd.error將輸出釘釘服務器采用的數字簽名參數,可以與自己采用的參數做比較

 

附:串起來的代碼

async function getAccessToken() {
    // 步驟1:獲取token
    let access_token = await getToken({
        corpid,
        corpsecret
    });

    // 步驟2:獲取ticket
    let ticket = await getJsticket({
        access_token
    });

    // 步驟3:獲取數字簽名
    let signature = getJsApiSingnature(ticket, nonce, timeStamp, url);

    // 步驟4:設置權限
    dd.config({
        agentId: agentId,
        corpId: corpid, //必填,企業ID
        timeStamp: timeStamp, // 必填,生成簽名的時間戳
        nonceStr: nonce, // 必填,生成簽名的隨機串
        signature: signature, // 必填,簽名
        jsApiList: jsApiList // 必填,需要使用的jsapi列表,注意:不要帶dd。
    });

    // 測試定位功能
    testJsApi();
}

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM