如果你正在规划一个社区型产品、论坛、博客、或其他开放性Web站点,需要在登录用户之间形成互动性;或者正在对接政府机构、酒店大堂、药房门店等,需要访客先登记后进入;抑或正在设计企业内部系统,不想对接繁琐的iDaaS,但又需要记录和识别访问者的身份,那么,钉钉账号免登或许是你想要的东西,这篇文章应该正好也可以帮到你;本文尽量从初级开发者的角度来讲讲,钉钉账号免登体系的接入方法。
副标题:为你的Web站点接入钉钉账号免登体系(钉内免登也适用)。
预期效果
进入站点/打开页面,直接进入钉钉账号授权登录流程,用户同意后直接获取到登录者身份信息。
适用对象
PC站点 :通过桌面端浏览器访问的网站。
H5站点 :通过手机端扫码、或点击链接访问的网站。
适用场景
场景一:社区型产品、论坛、博客、或其他开放性Web站点,需要在登录用户之间形成互动性。
Before:传统的做法是做一套账号系统,提供注册流程,然后再登录使用。
After:接入钉钉账号授权体系,可不用繁琐注册、直接免登(可账密、可扫码)。
场景二:政府机构、酒店大堂、药房门店等,需要访客先登记后进入。
Before:纸笔登记,然后酌情录入访客系统。
After:钉钉扫码,手机上一键快速登记(接入钉钉账号授权体系即可)。
场景三:企业内部系统,不想对接繁琐的iDaaS,但又需要记录和识别访问者的身份。
Before:建设简单的账号管理体系,提供内部账号注册流程,登录可用。
After:对接钉钉账号授权体系,一键免登快速进入(可账密、可扫码)。
所需接口
获得钉钉授权免登的链接请参见钉钉授权免登录。
根据临时授权码,获取用户授权的AccessToken。
根据用户AccessToken,获取用户信息。
接入流程
本文尝试从初级/小白开发者的角度来写,尽可能细、尽可能直白。
准备工作
准备好本地开发环境,Java、PHP、Node.js、Python、C#均可;只要是标准的Web应用开发环境即可,没什么特殊的(这里都不需要管SDK的事儿,开发过程中遇到了再引入,一点都不晚)。
创建应用
登录钉钉开发者后台 (请确保前面的准备工作已经完成)。
顶部导航栏选择应用开发>企业内部开发,页面右上角按钮选择创建应用。
在应用创建的弹层中,填写关键信息,最后确定创建。
应用类型:选择H5微应用。
开发方式:选择企业自主开发。
应用名称:酌情自定义即可,假定这里起名为扫码免登。
创建好应用以后,就可以获取到应用的AppKey 和AppSecret 了,可以说,这俩东西组合起来就是钉钉开放接口的访问凭证了。
申请接口
进入应用的开发配置界面,左侧菜单中找到权限管理。
右侧权限配置界面中,权限范围默认选择全部员工,下方接口列表内切换到个人权限,右侧勾选如下两个权限点:
通讯录个人信息读权限。
个人手机号信息。
如果还想通过授权获得更多个人信息,酌情申请其他权限点即可。
配置回调
在钉钉授权登录页面,用户点击同意后,页面会跳转回到用户自己的系统,并且此时会携带一个authCode 即临时授权码,此处需要配置的,就是这个回调的地址
进入应用的开发配置界面,左侧菜单中找到登录与分享。
在右侧回调域名处填写你未来需要接收临时授权码的Web URL,此处假定为本地服务:
http://127.0.0.1:3000/callback-for-dingtalk
。
这里的回调域名可以添加多个,可以分别用于本地开发、预发环境、线上生成环境,甚至供多个Web站点使用(酌情设定)。
开始开发
开发语言不限,目前钉钉的SDK也支持多种语言覆盖,包括Java、PHP、C#、Python、Node.js、Go,酌情选择自己最熟悉的即可。
不过个人感觉,开放平台的本质都是OpenAPI的访问,就是往一个开放接口传参提交数据并获得结果,没啥特别的,所以用不用SDK问题都不是太大。
创建项目:以下以Node.js项目为例,用Express框架快速初始化一个Web项目。
// 在命令行通过下面几行代码初始化你的Web项目
// 创建项目
mkdir dingtalk-login && cd dingtalk-login
// 初始化,持续回车键即可
npm init
// 安装express:快捷创建web项目很酸爽
npm install --save express express-generator
// 通过express命令行在当前目录下初始化项目
./node_modules/express-generator/bin/express-cli.js -ef .
// ps:在启动服务之前,可能有些nodejs依赖包还需要安装一下,不妨再install一次
npm install
// 启动服务,然后就可以去浏览器输入地址访问了:http://127.0.0.1:3000
./bin/www
在文件routes/index.js中开始写主程序代码(意思就是未来通过 https://127.0.0.1:3000/* 进行访问);核心代码就两部分,一个入口,一个回调:
入口部分,假定命名为 /entry-for-dingtalk ,即未来通过 http://127.0.0.1:3000/entry-for-dingtalk 访问
// 改写这个首页的内容,加一个测试的链接
router.get('/', function(req, res, next) {
// 页面默认显示一个钉钉免登的链接,点击以后会跳转到下面的router中
res.send('<a href="/entry-for-dingtalk" target="_blank">点击这里测试钉钉免登</a>');
});
// 扫码免登Demo入口页,完整的访问路径:http://127.0.0.1:3000/entry-for-dingtalk
router.get('/entry-for-dingtalk', function(req, res, next) {
let clientId = '<这里替换成你自己应用的App Key>';
let site = 'http://127.0.0.1:3000';
// 重定向到授权页
let redirect_uri = encodeURIComponent(`${site}/demo/scan-login-demo`);
let base_url = 'https://login.dingtalk.com/oauth2/auth';
// 直接跳转到钉钉授权界面
res.redirect(base_url + "?redirect_uri=" + redirect_uri + "&client_id=" + clientId
+ "&response_type=code&scope=openid&prompt=consent");
});
App Key 从什么地方获取,在前面5.2章节中已经有介绍,自行查看,点击复制即可。
ii. 回调部分,必须与5.4中配置的回调地址保持一致,/callback-for-dingtalk,即未来通过http://127.0.0.1:3000/callback-for-dingtalk 访问
// 扫码免登Demo回调,完整的访问路径:http://127.0.0.1:3000/callback-for-dingtalk
router.get('/callback-for-dingtalk', function(req, res, next) {
// Step 1:参考如下文档,获取当前登录用户的授权Token
// 文档:https://open.dingtalk.com/document/orgapp-server/obtain-user-token
DingtalkClient.request({
path:'/v1.0/oauth2/userAccessToken',
method:'POST',
body:{
clientId:'<这里替换成你自己应用的App Key>',
clientSecret: '<这里替换成你自己应用的App Secret>',
code:req.query.authCode,
grantType:'authorization_code'
}
}).then(data => {
// Step 2:参考如下文档,获取当前登录用户的个人信息
// 文档:https://open.dingtalk.com/document/orgapp-server/dingtalk-retrieve-user-information
return DingtalkClient.request({
path:'/v1.0/contact/users/me',
headers: {
'x-acs-dingtalk-access-token': data.accessToken
}
});
}).then(data => {
// Step 3:根据获取到的用户授权信息,做相关业务操作
res.setHeader("Content-Type", "application/json;charset=utf-8");
res.end(JSON.stringify({
message:'下面这些内容就是通过免登获取到的个人详细信息了,如果当前已经有账号登录了,可以直接获取到数据',
data:data // 这里就是拿到的结果了!!
},null,4));
});
});
你可能注意到了上门示例代码中的DingtalkClient.request ,不知道这是什么,这实际上是钉钉OpenApi的简单访问工具,工具定义如下:
// 钉钉OpenApi的访问工具
// github: https://github.com/zxlie/dingtalk-client
let DingtalkClient = {
/**
* 钉钉OpenAPI的统一调用入口
* @param {object} configs 请求配置
* @p-config {boolean} isOldApi 是否老版本接口,默认 false
* @p-config {string} method 请求方式,GET或者POST
* @p-config {string} path 接口地址,如:/v1.0/sso/getToken
* @p-config {object} params 需要在接口地址上进行URL拼接的参数
* @p-config {object} body 请求方式为POST时,指定提交的内容
* @p-config {object} headers 请求头
* @p-config {function} callback 请求结果的处理回调:function(error,data)
* @returns {promise} 返回一个Promise对象
**/
request : function(configs) {
var url = ((isOldApi, path, params) => {
let _hostConfig = {
topHost: 'https://oapi.dingtalk.com', // 老版API
popHost: 'https://api.dingtalk.com' // 新版API
};
let oUrl = new URL((isOldApi ? _hostConfig.topHost : _hostConfig.popHost) + path);
if (Object.keys(params || {}).length > 0) {
Object.keys(params, key => oUrl.searchParams.append(key,params[key]));
}
return oUrl.toString();
})(configs.isOldApi, configs.path, configs.params);
var obj = {
method: (configs.method || 'GET').toUpperCase(),
url: url,
json: true
};
if(obj.method === 'POST' && configs.body) {
obj.body = configs.body;
}
if(configs.headers) {
obj.headers = configs.headers;
}
return new Promise((resolve,reject) => {
request(obj, (err, response, body) => {
resolve(body);
});
});
}
};
routes/demo.js的完整代码就不重复贴了,点击这里直接下载。
上面示例代码中用到了request 包,所以记得在命令行安装一下依赖:
// 安装依赖包:request
npm install --save request
至此,所有的开发工作都结束了,可以去测试了
开始体验
通过命令行工具,重新进入到项目dingtalk-login的目录下,操作如下命令重新启动服务:
// 启动服务,然后就可以去浏览器输入地址访问了:http://127.0.0.1:3000
./bin/www
如果之前你的服务已经启动,记得退出(Win:Ctrl+C,Mac:control+C)。
浏览器访问http://127.0.0.1:3000
试一下,是不是跑起来了,按步操作扫码,也拿到了当前用户在钉钉上的个人信息。
如果当前电脑上已经登录过钉钉账号,钉钉也是可以帮你自动识别出来的,一键登录即可:
体验升级
上面的链接http://127.0.0.1:3000
在PC端浏览器上访问,是没有问题的,但是如果要在手机端测试这个流程,就不能直接用了(大家应该都懂的,因为127.0.0.1表示的本机)。解决方案有两种:
手机和PC保持在同一局域网内(原理:局域网内可互联)。
获取PC端在局域网下被分配的IP,如 192.168.3.4,Web站点在PC上的服务即可通过链接
http://192.168.3.4:3000
进行访问。在开发者后台,新增登录与分享的回调地址,设置为:
http://192.168.3.4:3000/callback-for-dingtalk
。routes/index.js
中的/ 路由里,也对应将127.0.0.1替换成新IP。重启Web服务,在PC或者手机上直接访问
http://192.168.3.4:3000
即可体验最新效果。BTW:也可以在PC上将连接生成个二维码,用钉钉扫码直接打开,体验更顺滑。
通过钉钉提供的内网穿透工具来实现(原理:将本地Web服务映射到公网)。
打开命令行工具,执行以下命令,下载并启动内网穿透工具(附工具文档)。
# 从Git上下载内网穿透工具
git clone https://github.com/open-dingtalk/pierced.git
# 如果是Windows平台,执行下面的命令
cd cd windows_64 && ding -config=ding.cfg -subdomain=abc 3000
# 如果是Mac平台,执行下面的命令
cd mac_64 && chmod 777 ./ding && ./ding -config=./ding.cfg -subdomain=abc 3000
上面-subdomain=abc 里的abc是需要替换成你自己的域名标识的,你希望它叫啥就叫啥(请酌情起名字)。
ii. 在开发者后台,新增【登录与分享】的回调地址,设置为:http://abc.vaiwan.com/callback-for-dingtalk
。
iii. routes/index.js中的/ 路由里,也对应将127.0.0.1替换成新的公网域名abc.vaiwan.com
。
iv. 重启Web服务,在PC或者手机上直接访问 http://abc.vaiwan.com
即可体验最新效果。
v. BTW-1:也可以在PC上将连接生成个二维码,用钉钉扫码直接打开,体验更顺滑。
vi. BTW-2:现在把 http://abc.vaiwan.com
发给你的其他同事或朋友,他们也可以访问了(内网穿透的surprise~)。
下载Sample
从Github下载示例代码
# 下载代码
git clone https://github.com/zxlie/dingtalk-client.git
# 进入Sample目录
cd dingtalk-client/sample/dingtalk-login
# 安装npm包依赖
npm install
替换入口文件routes/index.js里的App Key 和App Secret (这里不要忘记了前面接入流程中提到的准备工作)。
步骤一:创建应用,获得AppKey和AppSecret(参考接入流程中的创建应用)。
步骤二:申请接口权限(参考接入流程中的申请接口)。
步骤三:配置回调地址(参考接入流程中的配置回调)。
启动服务,开始体验。
# 启动服务,然后就可以到浏览器里去访问了,http://127.0.0.1:3000
./bin/www