zoukankan      html  css  js  c++  java
  • 钉钉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();
    }

     

  • 相关阅读:
    2017-4-6校内训练
    [BZOJ]1023: [SHOI2008]cactus仙人掌图
    [BZOJ]1086: [SCOI2005]王室联邦
    [BZOJ]1055: [HAOI2008]玩具取名
    [BZOJ]3527: [Zjoi2014]力
    [BZOJ]2820: YY的GCD
    【BZOJ3233】【tyvj1729】文艺平衡树
    【数据结构】【平衡树】无旋转treap
    【BZOJ2733】【HNOI2012】永无乡
    【BZOJ3224】【tyvj1728】普通平衡树
  • 原文地址:https://www.cnblogs.com/zhang90030/p/9569515.html
Copyright © 2011-2022 走看看