1、场景描述

我们开发了一个钉钉应用,但是客户要求手机端要使用微信。这样的话,我们给客户的解决方案是后台管理功能监控功能使用的钉钉(主要是依托于钉钉的人员,部门,角色的管理,我们应用本身就没有做相关的维护页面),手机端使用公众号。

这样的话,就带来了一个问题,由于我们应用是依托于钉钉的,没有自己的账号体系。所以就必须使用钉钉的账号来登录。

2、开发环境

1、前后端分离。前端使用的vue

2、后端是springboot 工程

3、实际开发

(1)技术选型经过

1、首先我们是想用微信小程序来开发,但是发现小程序的web-view没法实现,尤其是我们还是用的钉钉,光是跳转域名的审核就没法通过,审核需要的验证文件我们根本没办法放到钉钉的域名下。所以就选择普通的H5工程。

2、找到钉钉官方文档,这里有两种方式,扫码和账号密码。

这里由于我们本就是为了手机端做的,扫码登录这个就不考虑了。选用账号密码。

(2)步骤

接下来是步骤,基本上是按照官方文档来的,不过有些地方我加上了截图

1、首先是登录开发者后台,选择应用开发 > 移动接入应用 > 登录,然后单击创建扫码登录应用授权,创建用于免登过程中验证身份的appId及appSecret,创建后即可看到appId和appSecret。

位置:

单击“创建扫码登录应用授权”按钮,弹出以下对话框

加完之后,能够得到AppId和appSecret。

注:所有的字段中,只有描述没有实际的用途,其他的字段都很重要

2、构造要跳转的链接

构造如下跳转链接,此链接处理成功后,会重定向跳转到指定的redirect_uri并向url追加临时授权码code及state两个参数

1

https://oapi.dingtalk.com/connect/oauth2/sns_authorize?appid=APPID&response_type=code&scope=snsapi_login&state=STATE&redirect_uri=REDIRECT_URI

根据我上面的参数,构造的url是

1

https://oapi.dingtalk.com/connect/oauth2/sns_authorize?appid=dingoaddugp123ueic122dbpxf6v2wq71yn81&response_type=code&scope=snsapi_login&state=STATE&&redirect_uri=http://192.168.0.16:8080/#/

其中需要注意的是:

redirect_uri 的参数值必须是申请扫码登录授权应用的回调url。如果一直但是还是有问题,看看是否是没有urlencode编码导致的。

在浏览器中查看构造好的url

如果错了的话,提示

如果正确的话,就能够跳转到第三方登录页面。图片因为用的百度的,是403 (Forbidden)了。这个换成可用的图片url就可以了。

单击登录账号,

输入手机号和密码,单击授权登录,就会跳转到我们指定的回调地址上并添加上临时授权码

我们的工程是vue,所以我的回调地址直接就是前段的地址。

这里前端从url中拿到临时授权码,用这个授权码请求我的后端,获取用户的信息,完成整个登录过程

后端代码

controller

@ApiOperation("第三方网站使用钉钉账号登录")@RequestMapping(value = "/third-party/login", method = RequestMethod.GET)public ResponseMessage<DingUserDto> thirdPartyLogin(@ApiParam("临时授权码") @RequestParam("code") @NotBlank(message = "授权Code 不能为空") String code) throws Exception {return ResponseMessage.ok(dingUserService.thirdPartyLogin(code));}

service

获取用户信息的步骤,首先是unionId。

这个unionId是用户在钉钉的唯一标识。我的理解是手机号的替代。因为手机号虽然也具有唯一性,但是信息太敏感,所以给用户添加了一个unionId来唯一区分各个用户。

我们在进行应用开发的时候还有一个概念叫userId。这个userId是针对组织而言的。也就是,同样一个用户,不同的组织当中userId是不一样的。

举例子

我用手机号(13512341234)申请了一个钉钉账号,我会获得一个unionId,比如dingunion1234

后来我加入了公司A,那么我的unionId依然还是dingunion1234,我在这个公司的urserId是dinguser987654

我同时又加入了公司B,那么我的unionId依然还是dingunion1234,但是我在公司B的urserId就变成了dinguser29387928

这样的话其实就可以看到,unionId + 企业corpId就可以唯一确定userId

后面也是这么获取用户信息的,只不过企业coprId要换成企业accessToken

1、通过临时授权码(一次性的,用过就失效)获取用户的unionId。

public OapiSnsGetuserinfoBycodeResponse getUserInfoByCode(String code) {DefaultDingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/sns/getuserinfo_bycode");OapiSnsGetuserinfoBycodeRequest reqBycodeRequest = new OapiSnsGetuserinfoBycodeRequest();// code临时授权码reqBycodeRequest.setTmpAuthCode(code);OapiSnsGetuserinfoBycodeResponse response;try {response = client.execute(reqBycodeRequest, dingSnsPropertiesConfig.getAppId(), dingSnsPropertiesConfig.getAppSecret());} catch (ApiException e) {log.info(e.toString(), e);return null;}if (response == null || !response.isSuccess()) {return null;}return response;}

2、获取企业accessToken

public static OapiServiceGetCorpTokenResponse getCorpTokenUtil(String corpId, String suiteTicket, String suiteKey, String suiteSecret) {long timestamp = System.currentTimeMillis();String signature = DingTalkSignatureUtil.computeSignature(suiteSecret, DingTalkSignatureUtil.getCanonicalStringForIsv(timestamp, suiteTicket));Map<String, String> params = new LinkedHashMap<>();params.put("timestamp", "" + timestamp);params.put("suiteTicket", suiteTicket);params.put("accessKey", suiteKey);params.put("signature", signature);String queryString = DingTalkSignatureUtil.paramToQueryString(params, "utf-8");DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/service/get_corp_token?" + queryString);OapiServiceGetCorpTokenRequest request = new OapiServiceGetCorpTokenRequest();request.setAuthCorpid(corpId);try {return client.execute(request, suiteKey, suiteSecret, suiteTicket);} catch (ApiException e) {e.printStackTrace();throw new DingApiException("获取企业 token 异常,详情:" + e.getErrCode() + "-" + e.getErrMsg() + ":" + e.getSubErrCode() + "-" + e.getSubErrMsg());} finally {log.info("GetCorpTokenUtil 耗时:{}", System.currentTimeMillis() - timestamp);}}

3、根据企业的accessToken和unionId获取用户信息

public OapiUserGetbyunionidResponse getByUnionId(String unionId, String accessToken) {DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/user/getbyunionid");OapiUserGetbyunionidRequest req = new OapiUserGetbyunionidRequest();req.setUnionid(unionId);OapiUserGetbyunionidResponse response;try {response = client.execute(req, accessToken);} catch (ApiException e) {log.info(e.toString(), e);return null;}if (response == null || !response.isSuccess()) {return null;}return response;}

到此为止,我们获取到了该用户的userid,名称,角色,corpId等信息。

剩下的根据自己的业务做处理就行了。

企业自建应用使用钉钉账号密码登录(钉钉第三方登录)相关推荐

  1. linux 本地账号密码无法登陆(shell可以登录),一直返回 登陆的login界面

    今天我在我虚拟机测试的时候遇到了一个问题.登陆centos一直是返回login,账号和密码没错,我也换了两个用户. 1.问题描述 我正常的输入用户名和密码 错误提示截图:返回登陆界面,我重新试了另外的 ...

  2. oracle shell 登录,linux 本地账号密码无法登陆(shell可以登录),一直返回 登陆的login界面...

    今天我在我虚拟机测试的时候遇到了一个问题.登陆centos一直是返回login,账号和密码没错,我也换了两个用户. 1.问题描述 我正常的输入用户名和密码 错误提示截图:返回登陆界面,我重新试了另外的 ...

  3. python账号密码一一对应_python模拟用户登录系统,如何两个用户输入各自的密码才能登入?...

    展开全部 #我可以把我自己2113的成果送你,你来研究5261研究 import json #用来存储数据4102的模块 import os #用来进行文件操作1653 import sys #获取脚 ...

  4. session模拟登录怎么传账号密码_三国群英传全系列登录Steam;合金装备V主题仿生手臂;了不起的修仙模拟器 推出首个DLC...

    点击蓝字[游戏风云]关注我们~ <三国群英传>全系列登录Steam 新闻来源:游戏风云 <三国群英传8>将于2021年1月13日发售,为了更好的让新老玩家重温经典,官方将系列1 ...

  5. 企业邮箱登录地址,邮箱登录入口,邮箱登录须知

    企业邮箱注册后,有很多登录方式选择,TOM企业邮箱可在官方网页端.独立定制登录页.微信端.手机APP.电脑邮箱客户端.接下来给大家一一介绍下~ 官方统一登录页 喜欢用网页端的用户,一般从统一登录页面登 ...

  6. 网站输入正确账号密码页面刷新一下_Folx的密码管理保存网站登陆信息

    Folx的密码管理保存网站登陆信息 大家下载某个文件时,需要登录文件所在的网站才能进行下载,否则哪怕有下载链接也无权限进行文件下载,那Folx遇到这种情况是否就无法使用了呢?Folx的密码管理也能保存 ...

  7. 使用Socket实现账号密码验证

    客户端: 1. 提示用户输入用户名和密码,将用户输入的用户名和密码发送给服务端 2. 接收服务端验证完用户名和密码的结果 服务端: 1. 服务端设置一组账号.密码作为合法账号 2. 接收客户端发送过来 ...

  8. iOS 手机记录登录账号密码列表

    当在开发的过程中,我们可能需要记录一下登陆过的账号密码,为了用户方便登录时再次操作. 举个例子:当我们退出登录的时候,换一个账号登录的时候我们就可以在记录的账号列表中选择想要的账号,直接就可以登录了. ...

  9. google 云开启 ssh 账号密码登录

    google 云开启 ssh 账号密码登录 1.新买的 google 服务器是不支持使用账号密码通过 ssh 登录的,这样就很不方便,要使用账号密码登录需要修改 ssh 配置文件. 先通过浏览器打开 ...

最新文章

  1. 2021年人工智能和机器学习的五大趋势
  2. Keepalived简介
  3. 2018.3,GC可控了
  4. 七十一、去重交换排序链表、 求链表的中间结点
  5. 电脑中病毒后被隐藏的文件的显示
  6. android UI进阶之实现listview的分页加载
  7. 快过年了,来,来,来!给七大姑八大姨好好解释解释【啥是DBA 】
  8. 在linux中建立一个vim的目录,Linux学习笔记一(目录结构、Vim编辑器、用户管理)...
  9. JS实现图片翻书效果
  10. 基于Sendmail、Dovecot和Ssl的电子邮件服务器搭建——从不安全通信到安全通信
  11. 2018.8.29牛客OI测试赛A-斐波那契题解(找规律)
  12. QuartusII13.1 操作
  13. SSL认证之相关证书的生成
  14. 计算方法(三)分段线性插值和Hermite插值
  15. 下一个冷链独角兽:C轮融资后,九曳供应链如何撬动生鲜市场?
  16. word文档无法编辑且点击后每次跳到首页
  17. 表格提示html内容消失,如何解决Word里面的表格插入题注后页面上内容消失、无法编辑的问题...
  18. [java] java语言基础
  19. Requests 和 Scrapy 添加动态IP代理
  20. CP-net第三部分解读

热门文章

  1. 服务端开发---云数据库mysql的常见问题
  2. 胡桃日记获取服务器版本信息,胡桃日记各渠道时装兑换领取方法
  3. centos系统关闭ntp服务器,CentOS 7配置NTP客户端
  4. 安徽省计算机2级考试试题,安徽省计算机二级VFP考试理论模拟试题2(附答案)!!!!!!!!...
  5. html页面判断是否相等,javascript怎么判断字符串是否相等?
  6. 免费好用的jpg转换成pdf转换器
  7. 银豹收银系统零费率怎么切
  8. Android OMX 01
  9. 合成地震记录的matlab程序,合成地震记录的matlab程序
  10. 全新数据增强方式KeepAugment,简单高效提升模型精度!