钉钉微应用的免登录流程

摘要:
最近,我们在美甲企业内部做了一个微应用项目。首先,根据官方文件,了解登录豁免流程。0表示微应用程序的jsapi,1表示服务窗口的jsapi;如果未填写,则默认值为0。某些固定的api在调用之前必须经过身份验证,而其他api则没有。收到代码后,将代码发送回后台并添加access_Token访问无钉api,并在验证成功后返回用户信息,包括用户的唯一ID,然后使用用户ID和access_Token来访问另一个api。代码如下。

  最近做了个钉钉企业内部微应用的项目。记录下自己的心得。

  首先根据官方文档明白免登流程

钉钉微应用的免登录流程第1张

  免登录的流程如上。首先我们需要拿到自己企业的corpId,和corpSecret,访问企业后台https://oa.dingtalk.com/index.htm#/microApp/microAppList登录后就可以拿到(当然你得有管理员权限),拿到这两个参数后,通过调用钉钉的接口,我们就可以拿到令牌了,也就是access_Token。根据官方文档的的说明,申请一个access_Token的有效时间是两个小时,同时该接口对每分钟的访问量有限制,所以最好请求到缓存在本地。代码如下。

  

function getToken(){
		if(Session::has('dingToken')){
			$accessToken = Session::get('dingToken');
		}else{
			$corpId = config('ding.CorpId');
			$corpSecret = config('ding.CorpSecret');
			$urlToken = "https://oapi.dingtalk.com/gettoken?corpid=$corpId&corpsecret=$corpSecret";
			$resToken = apiGet($urlToken);
			$resToken = json_decode($resToken,true);
			$accessToken = $resToken['access_token'];
			Session::set('dingToken',$accessToken);
		}
		return $accessToken;
	}

  在登录前,首先要在前端引入钉钉的js文件,以前钉钉的js是要分pc端与移动端的,引入的js也不一样,pc端为前缀为dingTalkPc,移动端前缀为dd。但是钉钉前不久有重新更新了开发文档,将两种js合并在了一起,通过传入type参数区分设备,如下图代码所示。

dd.config({
        agentId: "{$data['agentId']}", // 必填,微应用ID
        corpId: "{$data['corpId']}",//必填,企业ID
        timeStamp: "{$data['timeStamp']}", // 必填,生成签名的时间戳
        nonceStr: "{$data['nonceStr']}", // 必填,生成签名的随机串
        signature: "{$data['signature']}", // 必填,签名
        type:0/1,   //选填。0表示微应用的jsapi,1表示服务窗的jsapi;不填默认为0。该参数从dingtalk.js的0.8.3版本开始支持
        jsApiList : [
            'runtime.info',
            '​runtime.permission.requestAuthCode',
            'device.notification.confirm',
            'device.notification.alert',
            'device.notification.prompt',
            'biz.ding.post',
            'biz.util.uploadImage',
        ] // 必填,需要使用的jsapi列表,注意:不要带dd。
    });

  js的地址我就不写了,开发文档中有。上面的代码在钉钉开发文档中称之为鉴权。在钉钉的api中有部分api必须是要先进行鉴权才能调用的,而有部分则不需要。为什么要说这个呢。因为有两种免登的方式,一种比较简单,一种比较复杂。相信你也猜到了,简单的不需要鉴权,而复杂的需要鉴权。这两种方式也互有利弊。

  我们先来说简单的。当我们拿到access_Token后就可以进行免登了。在页面中引入钉钉的js文件后,调用js中的api,如下

dd.ready(function() {
    dd.runtime.permission.requestAuthCode({
        corpId: "corpid",
        onSuccess: function(result) {
        {
            code: 'hYLK98jkf0m' //string authCode
        }
        },
        onFail : function(err) {}
  
    });
});

  这个api是不用鉴权的,需要你把corpId传到前台来,当页面加载完成后自动执行,执行成功后会返回code码,值得一提的是钉钉做了限制,它的jsapi只能在钉钉应用中访问,所以如果直接在浏览器中查看时没有效果的,所以如果你要在电脑上调试,就需要下载一个RC版的钉钉,打开钉钉后,在浏览器中输入http://localhost:16888/就可以在浏览器中看到控制台了,手机上的话同样也有开发版的钉钉app,在app设置中打开调试模式,开启手机usb调试权限,通过下图中google浏览器的工具来捕捉输出。钉钉微应用的免登录流程第2张

  回归正题,通过钉钉的jsapi拿到code,code也是有过期时间的,为5分钟有效时间。拿到code后将code传回后台加上access_Token访问钉钉的免登api,验证成功后返回用户信息,其中就有用户的唯一标识Id,再使用拿到de用户Id加上access_Token访问另外一个api,代码如下。

public function getUserInfo(){
        //code
        $data = input();
        $code = $data['code'];

        //Access_Token
        $accessToken = getToken();

        //userId
        $urlId = "https://oapi.dingtalk.com/user/getuserinfo?access_token=$accessToken&code=$code";
        $resId = apiGet($urlId);
        $resId = json_decode($resId,true);
        $userId = $resId['userid'];

        //登录用户信息
        $urlInfo = "https://oapi.dingtalk.com/user/get?access_token=$accessToken&userid=$userId";
        $resInfo = apiGet($urlInfo);
        $resInfo = json_decode($resInfo);
        $resInfo = get_object_vars($resInfo); 
}

  就此,免登录完成了。当然这种方法也有缺陷,那就是返回的用户信息比较少,不是那么全面。只能拿到如下参数

钉钉微应用的免登录流程第3张

  如果需要更多的用户信息,那我们就需要进行比较复杂的免登方式了。也就是说我们在请求用户信息前必须进行一次鉴权,才能拿到更多的用户信息。回到拿到access_Token的开头,我们从后端开始,从一开始的流程图来看,鉴权需求ticket,nonceStr,timeStamp,signature,agentId,corpId这六个参数agentId和corpId是直接可以拿到的,不再赘述,ticket带上accessToken参数通过接口获得,noceStr用于生成密钥的参数,我是直接给的随机数。timeStamp当前时间戳,而

signature则是上述几个参数通过一定算法得到。

function ddconfig(){
    //Access_Token
    $accessToken = getToken();
    // $accessToken = "08bbf680be4f3a028aa652e75a0ad754";

    //ticket
    $urlTicket = "https://oapi.dingtalk.com/get_jsapi_ticket?access_token=$accessToken";
    $resTicket = apiGet($urlTicket,false);
    $resTicket = json_decode($resTicket,true);
    $ticket = $resTicket['ticket'];

    //signature
    $nonceStr = md5(rand(10000000,99999999));
    $agentId = 181397144;
    $timeStamp = time();
    $url = get_current_url();

    $plain = 'jsapi_ticket=' . $ticket .
        '&noncestr=' . $nonceStr .
        '&timestamp=' . $timeStamp .
        '&url=' . $url;
    $signature = sha1($plain);

    $corpId = config('ding.CorpId');

    $data['nonceStr'] = $nonceStr;
    $data['agentId'] = $agentId;
    $data['timeStamp'] = $timeStamp;
    $data['url'] = $url;
    $data['signature'] = $signature;
    $data['corpId'] = $corpId;

    return $data;
}

  拿到这几个参数后将其返回到前端页面。首先进行钉钉鉴权,代码前面已经贴过,值得注意的是鉴权过程中需要初始化jsapi,只有初始化了的jsapi在后面才能被调用,鉴权后的过程就跟第一种方法一样,拿着返回的code码,请求userId和用户信息。最终可以拿到用户的完整信息。再通过与自己数据库的数据作对比就完成了免登。

免责声明:文章转载自《钉钉微应用的免登录流程》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇Jquery 父、子、兄弟节点查询方法WebStorm设置左侧菜单栏背景和字体设置下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

GBT28181中的RTP

国标中说h264数据按照RFC3984打包,但是国标的测试工具——SPVMN,却不支持RFC3984的打包方式。无奈之下直接用RFC3550的方式打包,其实就是分包,然后加上RTP头,对于一帧的结束,在RTP头中把MARK置1,并且在一帧的开始把时间戳增加而已。这种打包方式其实和RFC有冲突,打包处理的RTP数据用VLC播放解码不正常,但用SPVMN是可以...

ecshop 二次开发 函数列表大全

最近进行ecshop的二次开发,整理了一部分的函数,另外在ecshop论坛上面也发现了很多函数说明,整理汇总如下,供大家参考。 所有函数功能说明: lib_time.phpgmtime() P: 获得当前格林威治时间的时间戳 /$0server_timezone() P: 获得服务器的时区 /$0local_mktime($hour = NULL , $mi...

TCP全连接队列和半连接队列已满之后的连接建立过程抓包分析[转]

最近项目需要做单机100万长连接与高并发的服务器,我们开发完服务器以后,通过自己搭的高速压测框架压测服务端的时候,发生了奇怪的现象,就是服务端莫名其妙的少接收了连接,造成了数据包的丢失,通过网上查资料,和自己的实践,下面是我做实验,抓包分析的过程如下: 总共5个连接 其中全连接队列somaxconn参数为1表示监听队列的总长度(实际可以完成somaxcon...

微信公众号--JS-SDK

JS-SDK 微信JS-SDK是微信公众平台 面向网页开发者提供的基于微信内的网页开发工具包。 通过使用微信JS-SDK,网页开发者可借助微信高效地使用拍照、选图、语音、位置等手机系统的能力,同时可以直接使用微信分享、扫一扫、卡券、支付等微信特有的能力,为微信用户提供更优质的网页体验。 JS-SDK使用步骤 l  步骤一:绑定域名 先登录微信公众平台进...

java微信二次第三方开发,token认证,消息事件接收,图文素材库,自定义菜单等功能

基于之前的文章SSM配置的项目:http://www.cnblogs.com/mangyang/p/5168291.html 来进行微信第三方开发, 微信二次开发,官方还是网上有很多介绍了,这里就不在进行讲述了 直接上干货。 首先 与微信对接,服务器配置,需要80端口和443端口开放的服务器,这里推荐 使用 python 的pagekite,一款反向代理...

Windows访问令牌模拟窃取以及利用(T1134)

Token简介 Windows下有两种类型的Token Delegation token(授权令牌):用于交互会话登录(例如本地用户直接登录、远程桌面登录) Impersonation token(模拟令牌):用于非交互登录(利用net use访问共享文件夹 两种token只在系统重启后清除,具有Delegation token的用户在注销后,该Toke...