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

您所在的位置:网站首页 钉钉如何登录已有账号 企业自建应用使用钉钉账号密码登录(钉钉第三方登录)

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

2024-07-04 13:34| 来源: 网络整理| 查看: 265

1、场景描述

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

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

2、开发环境

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

2、后端是springboot 工程

3、实际开发

(1)技术选型经过

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

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

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

(2)步骤

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

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

位置:

image.png

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

加完之后,能够得到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 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 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等信息。

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



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3