钉钉一键登录第三方网站

简介: 钉钉一键登录第三方网站,这里主要记录一键登录整个实现步骤。登录页面构造好钉钉一键登录链接后的页面效果。

企业内部系统已经做过了钉钉扫码登录,现在需要添加钉钉一键登录第三方网站功能,这里主要记录一键登录整个实现步骤。

钉钉开发者后台

想要实现钉钉一键登录,首先需要在钉钉开放平台管理平台配置H5微应用

H5微应用

实现钉钉一键登录第三方网站,官方文档地址:实现登录第三方网站根据官方文档的操作步骤来看的话需要先到钉钉开发者后台添加H5微应用,钉钉开发者后台地址:钉钉开发者后台进入钉钉开发者后台后,

image.png

选择【企业内部开发】进入

image.png


点击右上角【创建应用】

image.png

输入【应用名称】,【应用描述】,上传系统图标或者不上传都可以,点击【确认创建】

image.png

创建完成之后你就可以看到你创建的H5微应用的应用凭证,点击左侧菜单【权限管理】

image.png

这里需要申请【个人手机号信息】、【通讯录个人信息读权限】两个权限,权限申请完成之后点击菜单【登录与分享】

image.png

在输入框中输入回调的域名及对应的方法,点击【添加】完成回调URL的配置,这里因为是三套环境(开发、测试、线上),所以配置三套回调URL,三套环境用同一套应用凭证,当然你也可以选择创建三个H5微应用来支持三套环境。

应用代码开发

首先需要在登录页构造钉钉一键登录跳转链接,构造链接参考官方文档

image.png

登录页面login.html

登录页面构造好钉钉一键登录链接后的页面效果

image.png

页面代码,在原有的登录页面中添加如下代码

<divstyle="padding-left: 83px;"><buttontype="button"class="btn-dingding"onclick="toDingDing();">钉钉一键授权登录</button></div>


同时在页面增加跳转方法

//钉钉一键授权登录functiontoDingDing() {
varprojectUrl=$("#projectUrl").val();
varh5AppKey=$("#h5AppKey").val();
varredirect_uri=projectUrl+"dingdingOneClickLogin";
redirect_uri=encodeURIComponent(redirect_uri);
self.location="https://login.dingtalk.com/oauth2/auth?redirect_uri="+redirect_uri+"&response_type=code&client_id="+h5AppKey+"&scope=openid&state=&prompt=consent";
}


其中:projectUrl  就是获取的请求域名地址

          h5AppKey 就是配置的H5微应用的AppKey

至此,页面的内容添加完毕,下面开始来增加后台Java方法

登录实现LoginController.java

登录实现controller需要增加如下方法

/*** 登录系统* @param use* @return*/privateStringdoLoginSystem(SysUseruse) {
//已绑定账号则直接登录操作MyUsernamePasswordTokentoken=newMyUsernamePasswordToken(use.getUnionId(), use.getPassword(),false,true);
// 登陆主流程Subjectsubject=SecurityUtils.getSubject();
subject.login(token);
returnredirect("/index");
    }
publicstaticcom.aliyun.dingtalkoauth2_1_0.ClientauthClient() throwsException {
Configconfig=newConfig();
config.protocol="https";
config.regionId="central";
returnnewcom.aliyun.dingtalkoauth2_1_0.Client(config);
    }
/*** 获取用户token* @param authCode* @return* @throws Exception*///接口地址:注意/auth与钉钉登录与分享的回调域名地址一致@RequestMapping(value="/dingdingOneClickLogin", method=RequestMethod.GET)
publicStringgetAccessToken(@RequestParam(value="authCode")StringauthCode) throwsException {
com.aliyun.dingtalkoauth2_1_0.Clientclient=authClient();
GetUserTokenRequestgetUserTokenRequest=newGetUserTokenRequest()
//应用基础信息-应用信息的AppKey,请务必替换为开发的应用AppKey                .setClientId(dingDingProperties.getH5AppKey())
//应用基础信息-应用信息的AppSecret,,请务必替换为开发的应用AppSecret                .setClientSecret(dingDingProperties.getH5AppSecret())
                .setCode(authCode)
                .setGrantType("authorization_code");
GetUserTokenResponsegetUserTokenResponse=client.getUserToken(getUserTokenRequest);
//获取用户个人tokenStringaccessToken=getUserTokenResponse.getBody().getAccessToken();
GetUserResponseBodyuserinfo=getUserinfo(accessToken);
//根据unionId 获取用户信息StringunionId=userinfo.getUnionId();
SysUseruse=sysUserService.selectUserByUnionId(unionId);
Stringmsg="";
if (use!=null) {
returndoLoginSystem(use);
        }else {
//未绑定 则自动添加账号 根据unionid获取useridOapiUserGetbyunionidResponse.UserGetByUnionIdResponseuserIdByUnionIdV2=dingDingService.getUserIdByUnionIdV2(unionId);
if (userIdByUnionIdV2!=null&&StringUtils.isNotEmpty(userIdByUnionIdV2.getUserid())) {
//根据userid获取用户详细信息OapiV2UserGetResponse.UserGetResponseuser=dingDingService.getUserDetailByUserid(userIdByUnionIdV2.getUserid(), null);
if (user!=null) {
returnsaveSysUserAuto(user);
                }else {
msg="one";
                }
            }else {
msg="one";
            }
        }
returnredirect("/login?msg="+msg);
    }
publicstaticcom.aliyun.dingtalkcontact_1_0.ClientcontactClient() throwsException {
Configconfig=newConfig();
config.protocol="https";
config.regionId="central";
returnnewcom.aliyun.dingtalkcontact_1_0.Client(config);
    }
/*** 获取用户个人信息* @param accessToken* @return* @throws Exception*/publicGetUserResponseBodygetUserinfo(StringaccessToken) throwsException {
com.aliyun.dingtalkcontact_1_0.Clientclient=contactClient();
GetUserHeadersgetUserHeaders=newGetUserHeaders();
getUserHeaders.xAcsDingtalkAccessToken=accessToken;
//获取用户个人信息,如需获取当前授权人的信息,unionId参数必须传meGetUserResponseBodyres=client.getUserWithOptions("me", getUserHeaders, newRuntimeOptions()).getBody();
returnres;
    }
privateStringsaveSysUserAuto(OapiV2UserGetResponse.UserGetResponseuser) {
List<UserRole>userRoleList=newArrayList();
//整理需要插入数据库字段Stringuserid=user.getUserid();
//判断当前用户是否已经插入过了LonguserId=null;
SysUsersysUser=sysUserService.selectUserByDingDingUserid(userid);
if (sysUser!=null) {
userId=sysUser.getUserId();
        }else {
sysUser=newSysUser();
sysUser.setDingdingUserid(userid);
sysUser.setAvatar(user.getAvatar());
sysUser.setUnionId(user.getUnionid());
sysUser.setPhonenumber(user.getMobile());
sysUser.setEmail(user.getEmail());
sysUser.setTitle(user.getTitle());
StringuserName=user.getName();
sysUser.setUserName(userName);
//中文转拼音作为loginNameStringloginName=PinYinUtils.getPingYin(userName);
//根据当前公司人员重名情况,最大重名6人,故此处设置最大重名为10StringBuildersb=newStringBuilder(loginName).append(",");
for (inti=1; i<10; i++) {
sb.append(loginName+String.valueOf(i)).append(",");
            }
Stringloginnames=sb.toString();
//判断一下当前是否已经存在了loginnameSysUseruniqueuser=sysUserService.selectLastUserByLoginName(Convert.toStrArray(loginnames));
if (uniqueuser!=null) {
//获取当前重名用户的序号Stringnumber=uniqueuser.getLoginName().replace(loginName, "");
//序号增加1在放回去拼接好inti=0;
if (StringUtils.isNotEmpty(number)) {
i=Integer.parseInt(number) +1;
                }else {
//说明当前loginname还没有后续数字i=1;
                }
sysUser.setLoginName(loginName+i);
            }else {
sysUser.setLoginName(loginName);
            }
sysUser.randomSalt();
//初始未编码前password为123456sysUser.setPassword(passwordService.encryptPassword(sysUser.getLoginName(), "123456", sysUser.getSalt()));
sysUser.setCreateBy("扫码登录补充用户");
sysUser.setCreateTime(newDate());
sysUserService.insertSysUser(sysUser);
userId=sysUser.getUserId();
//插入用户的角色,初始用户都是普通角色UserRoleur=newUserRole();
ur.setUserId(userId);
if (Constants.ONE_KEY.equals(user.getUserid()) ||Constants.TWO_KEY.equals(user.getUserid())) {
ur.setRoleId(1L);
            }else {
ur.setRoleId(2L);
            }
userRoleList.add(ur);
        }
//插入用户的部门List<Long>deptIdList=user.getDeptIdList();
if (CollectionUtils.isNotEmpty(deptIdList)) {
//插入部门之前需要清除之前的人员部门关系,以防钉钉部门变动而系统未感知intdele=sysUserDeptService.deleteSysUserDeptByUserId(userId);
//插入人员部门关系表SysUserDeptuserDept=newSysUserDept();
userDept.setUserId(userId);
for (Longdeptid : deptIdList) {
userDept.setDeptId(deptid);
userDept.setCreateBy("扫码登录补充用户");
userDept.setCreateTime(newDate());
sysUserDeptService.insertSysUserDept(userDept);
            }
        }
//插入角色if (CollectionUtils.isNotEmpty(userRoleList)) {
userRoleMapper.batchUserRole(userRoleList);
        }
//登录系统returndoLoginSystem(sysUser);
    }


其中dingDingService.getUserIdByUnionIdV2(unionId)方法如下

/*** 根据unionId获取userId 2.0版本* @param unionId 当前钉钉用户在当前企业下的唯一识别码* @return*/@OverridepublicOapiUserGetbyunionidResponse.UserGetByUnionIdResponsegetUserIdByUnionIdV2(StringunionId) {
try {
StringaccessToken=getAccessToken();
//根据unionId获取userIdDingTalkClientclient=newDefaultDingTalkClient("https://oapi.dingtalk.com/topapi/user/getbyunionid");
OapiUserGetbyunionidRequestreq=newOapiUserGetbyunionidRequest();
req.setUnionid(unionId);
OapiUserGetbyunionidResponsersp=client.execute(req, accessToken);
OapiUserGetbyunionidResponse.UserGetByUnionIdResponseresult=rsp.getResult();
returnresult;
        } catch (ApiExceptione) {
e.printStackTrace();
        }
returnnull;
    }


dingDingService.getUserDetailByUserid(userIdByUnionIdV2.getUserid(), null)方法如下

/*** 查询用户详情* @param userid 钉钉userid* @param accessToken* @return*/@OverridepublicOapiV2UserGetResponse.UserGetResponsegetUserDetailByUserid(Stringuserid, StringaccessToken) {
try {
if (StringUtils.isEmpty(accessToken)) {
accessToken=getAccessToken();
            }
DingTalkClientclient=newDefaultDingTalkClient("https://oapi.dingtalk.com/topapi/v2/user/get");
OapiV2UserGetRequestreq=newOapiV2UserGetRequest();
req.setUserid(userid);
OapiV2UserGetResponsersp=client.execute(req, accessToken);
OapiV2UserGetResponse.UserGetResponseresult=rsp.getResult();
returnresult;
        } catch (ApiExceptione) {
e.printStackTrace();
returnnull;
        }
    }


PinYinUtils.java类如下

packagecom.dongao.project.utils;
importnet.sourceforge.pinyin4j.PinyinHelper;
importnet.sourceforge.pinyin4j.format.HanyuPinyinCaseType;
importnet.sourceforge.pinyin4j.format.HanyuPinyinOutputFormat;
importnet.sourceforge.pinyin4j.format.HanyuPinyinToneType;
importnet.sourceforge.pinyin4j.format.HanyuPinyinVCharType;
importnet.sourceforge.pinyin4j.format.exception.BadHanyuPinyinOutputFormatCombination;
/*** @ClassName:PinYinUtils* @author:dongao* @date 2022/2/10 14:05*/publicclassPinYinUtils {
/*** 中文转拼音* @param inputStr* @return*/publicstaticStringgetPingYin(StringinputStr) {
if (inputStr==null||"".equals(inputStr)) {
return"";
        }
HanyuPinyinOutputFormatformat=newHanyuPinyinOutputFormat();
//UPPERCASE 大写 LOWERCASE 小写format.setCaseType(HanyuPinyinCaseType.LOWERCASE);
//WITH_TONE_NUMBER 音标用数字 WITHOUT_TONE 无音标 WITH_TONE_MARK 直接用音标format.setToneType(HanyuPinyinToneType.WITHOUT_TONE);
//WITH_U_AND_COLON 用u表示ü WITH_V 用v表示ü WITH_U_UNICODE 用ü表示üformat.setVCharType(HanyuPinyinVCharType.WITH_V);
StringBuilderpYStr=newStringBuilder();
char[] input=inputStr.trim().toCharArray();
try {
for (inti=0; i<input.length; i++) {
if (Character.toString(input[i]).matches("[\\u4E00-\\u9FA5]+")) {
pYStr.append(PinyinHelper.toHanyuPinyinStringArray(input[i], format)[0]);
                } elseif (!(input[i] ==' ')) {
//过滤空格pYStr.append(input[i]);
                }
            }
        } catch (BadHanyuPinyinOutputFormatCombinatione) {
e.printStackTrace();
        }
returnpYStr.toString();
    }
}


pom.xml增加

pom.xml涉及到的jar包有

<dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.6</version></dependency><dependency><groupId>com.aliyun</groupId><artifactId>dingtalk</artifactId><version>1.1.86</version></dependency><dependency><groupId>com.aliyun</groupId><artifactId>alibaba-dingtalk-service-sdk</artifactId><version>2.0.0</version></dependency><dependency><groupId>com.belerweb</groupId><artifactId>pinyin4j</artifactId><version>2.5.0</version></dependency>


那么到这里整个关于钉钉一键授权登录的页面代码以及后台逻辑代码也就写完了,下面看一下一键登录的效果

一键登录效果展示

登录页面点击【钉钉一键授权登录】

image.png

跳转到钉钉授权页面

image.png

点击【立即登录】

image.png

跳转到系统首页,这里文中的图片打码主要是由于内容涉及不方便展示,希望可以谅解,整体的流程和代码是可以参考的,如果有问题欢迎大家评论区留言讨论。

相关文章
|
11月前
|
Java
钉钉第三方扫码登录提示 code: 403, 没有调用该接口的权限,接口权限申请参考
钉钉第三方扫码登录提示 code: 403, 没有调用该接口的权限,接口权限申请参考 ,但是我明明申请了Contact.User.Read 这个权限
347 1
|
移动开发 测试技术 开发工具
【钉钉免登录】(详解)钉钉接口,H5微应用,钉钉免登录及获取当前用户信息
【钉钉免登录】(详解)钉钉接口,H5微应用,钉钉免登录及获取当前用户信息
760 1
【钉钉免登录】(详解)钉钉接口,H5微应用,钉钉免登录及获取当前用户信息
|
2月前
|
人工智能 数据可视化 API
10 分钟构建 AI 客服并应用到网站、钉钉或微信中测试评
10 分钟构建 AI 客服并应用到网站、钉钉或微信中测试评
90 2
|
3月前
|
人工智能
10 分钟构建 AI 客服并应用到网站、钉钉或微信中简说
10 分钟构建 AI 客服并应用到网站、钉钉或微信
|
2月前
|
人工智能 运维 负载均衡
10 分钟构建 AI 客服并应用到网站、钉钉或微信中
《10分钟构建AI客服并应用到网站、钉钉或微信中》的解决方案通过详尽的文档和示例代码,使具有一定编程基础的用户能够快速上手,顺利完成AI客服集成。方案涵盖高可用性、负载均衡及定制化选项,满足生产环境需求。然而,若文档不清晰或存在信息缺失,则可能导致部署障碍。实际部署中可能遇到网络、权限等问题,需逐一排查。云产品的功能、性能及操作配置便捷性直接影响解决方案效果,详尽的产品手册有助于快速解决问题。总体而言,该方案在各方面表现出色,值得推荐。
|
4月前
|
存储 NoSQL 中间件
【Django+Vue3 线上教育平台项目实战】登录功能模块之短信登录与钉钉三方登录
在当今的数字化时代,用户认证是任何在线服务安全性的基石。本文将简明扼要地介绍登录注册流程中的核心概念:HTTP无状态性、Session、Token与JWT,并详细阐述两种实用登录方式—— 手机号登录验证(借助容联云/云通讯服务) 与钉钉第三方登录。我们将探讨这些概念的基本原理,并深入解析两种登录方式的实现流程,旨在帮助开发者提升用户认证的安全性与便捷性。
【Django+Vue3 线上教育平台项目实战】登录功能模块之短信登录与钉钉三方登录
|
12月前
|
存储 开发者
钉钉企业内部应用与第三方企业应用的主要区别
钉钉企业内部应用与第三方企业应用的主要区别
304 1
|
12月前
|
移动开发 算法 编译器
OAUTH之 钉钉第三方授权登录
OAUTH之 钉钉第三方授权登录
499 0
|
缓存 搜索推荐 网络安全
钉钉登录页面网页自动跳转,显示对不起,你无权限查看该页面,需要使用钉钉账号登录才可以进行授权
钉钉登录页面网页自动跳转,显示对不起,你无权限查看该页面,需要使用钉钉账号登录才可以进行授权
3796 1
|
存储 弹性计算 安全
成功案例-钉钉 | 学习笔记
快速学习 成功案例-钉钉
397 0

热门文章

最新文章