本篇博客主要作为本人的日记,如果各位博友对以下内容有所疑问欢迎留言探讨。
一、准备工作
1、钉钉开放平台注册登录:
登录地址:https://open.dingtalk.com/
2、注册登录成功后选择你加入的组织
3、创建应用
4、相关权限开通(权限开通都是免费)
5、设置扫描成功后的回调域名
如果开发者没有域名可以随便写一个域名,在本地host中配置对应的域名即可
6、本地host文件配置域名
host文件路径为:C:\Windows\System32\drivers\etc\host,打开host文件添加以上输入的回调域名,本人写的回调地址为“www.chenyuanbo.com”,配置如下所示:
7、开发环境下配置好内网穿透
(1)登录natApp官网注册;https://natapp.cn/,在右上角点击“客户端下载”,下载对应的natApp客户端,登录成功后的界面如下,authToken用于启动natApp
(2)启动内网穿透
打开下载好的natApp,运行natapp.exe,输入命令:natapp -authtoken="NatApp的隧道authtoken",出现以下界面说明内网穿透启动已成功
二、功能实现思路:
1、获取钉钉二维码界面(即下方:dingdingLogin方法)
2、扫二维码成功后进入回调方法,获取code。
3、请求获取accessToken
4、根据code和accessToken获取用户信息(含用户openId)
5、根据用户openId去自己系统的用户表中查询是否存在对应的用户,如果存在则登录成功,跳转至系统首页
三、功能开发
1、maven坐标:
<dependency> <groupId>com.aliyun</groupId> <artifactId>dingtalk</artifactId> <version>1.2.43</version> </dependency> <dependency> <groupId>com.aliyun</groupId> <artifactId>alibaba-dingtalk-service-sdk</artifactId> <version>2.0.0</version> </dependency>
2、具体代码实现
package com.cyb.sso.server.controller; import com.dingtalk.api.DefaultDingTalkClient; import com.dingtalk.api.DingTalkClient; import com.dingtalk.api.request.OapiGettokenRequest; import com.dingtalk.api.request.OapiSnsGetuserinfoBycodeRequest; import com.dingtalk.api.response.OapiGettokenResponse; import com.dingtalk.api.response.OapiSnsGetuserinfoBycodeResponse; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; /** *@ClassName UnionLoginController *@Description 联合登录控制层 *@Author cyb *@Date 2022/1/25 23:06 */ @Controller @RequestMapping("/unionLogin") @Slf4j public class UnionLoginController { /*** * 钉钉APPKey或SuiteKey */ private static final String DING_TALK_APP_ID="dingrd9jvv0i2z0eu62q"; /*** * 钉钉SuiteSecret或appSecret */ private static final String DING_TALK_SECRET ="HkOsehRYCwhJBg-nChBGdxAg2eoLA9A3T1ykbR1kR4HU5XzrO_D79s8Y6BJ-Pjzy"; /*** * 钉钉扫码后回调地址 * http://www.chenyuanbo.com:8080/xxl-sso-server/unionLogin/dingdingCallback */ private static final String DING_TALK_CALL_BACK_URL = "http%3A%2F%2Fwww.chenyuanbo.com%3A8080%2Fxxl-sso-server%2FunionLogin%2FdingdingCallback"; /*** * 获取accessToken请求URL */ private static final String getTokenUrl ="https://oapi.dingtalk.com/gettoken"; /*** * 获取用户详情URL */ private static final String getUserInfoUrl= ":https://oapi.dingtalk.com/sns/getuserinfo_bycode"; /*** * 获取钉钉联合登录二维码 * @return 钉钉二维码 */ @ResponseBody @RequestMapping("/dingdingLogin") public Object dingdingLogin() { String time = String.valueOf(System.currentTimeMillis());//产生一个当前的毫秒 StringBuilder stringBuilder = new StringBuilder(); String result=""; stringBuilder .append("https://oapi.dingtalk.com/connect/qrconnect?appid=") .append(DING_TALK_APP_ID)//APP_ID .append("&response_type=") .append("code")//code .append("&scope=") .append("snsapi_login")//snsapi_login .append("&state=") .append(time) .append("&redirect_uri=") .append(DING_TALK_CALL_BACK_URL);//回调地址 try { result = stringBuilder.toString(); } catch (Exception e) { System.out.println(e.getMessage()); } return result; } /*** * 扫码后的回调方法 * @param code 钉钉扫码返回的code * @return */ @RequestMapping(value="/dingdingCallback", produces="text/html; charset=utf-8") public Object getUserInfo(String code) { log.info("进入回调"); //1、获取accesstoken String accessToken = getAccessToken(); if(StringUtils.isEmpty(accessToken)){ return "未获取到accessToken,跳转到登录页"; } //2、根据accessToken和code获取用户OpenId String openId = getPersistentCode(accessToken, code); if(StringUtils.isEmpty(openId)){ return "未获取到用户OpenId,跳转到登录页使用账户密码登录"; } //3、根据openId查询数据库用户表,如果查询到用户则登录成功,未查询到则返回到登录首页使用账号密码登录并进行绑定钉钉openId return null; } /** * @method 获取accesstoken * @description 获取accesstoken * @date: 2022/1/26 22:00 * @author: cyb * @return 钉钉accessToken */ public String getAccessToken() { try { DingTalkClient clientDingTalkClient = new DefaultDingTalkClient(getTokenUrl); OapiGettokenRequest request = new OapiGettokenRequest(); // 填写步骤一创建应用的Appkey request.setAppkey(DING_TALK_APP_ID); // 填写步骤一创建应用的Appsecret request.setAppsecret(DING_TALK_SECRET); request.setHttpMethod("GET"); OapiGettokenResponse response =clientDingTalkClient.execute(request); if(response.getErrcode() == 0){ return response.getAccessToken(); } log.info("获取accessToken失败:{}",response.getMsg()); }catch (Exception e){ log.error("获取accessToken失败:",e); } return null; } /** * @method getPersistentCode * @description 获取用户openId * @date: 2022/1/26 22:08 * @author: cyb * @param accessToken 用户的accessToken * @param code 扫码返回的code * @return openId */ public String getPersistentCode(String accessToken,String code) { try { DefaultDingTalkClient client = new DefaultDingTalkClient(getUserInfoUrl); OapiSnsGetuserinfoBycodeRequest req = new OapiSnsGetuserinfoBycodeRequest(); req.setTmpAuthCode(code); OapiSnsGetuserinfoBycodeResponse response = client.execute(req,DING_TALK_APP_ID,DING_TALK_SECRET); if(0 != response.getErrcode()){ return null; } OapiSnsGetuserinfoBycodeResponse.UserInfo userInfo = response.getUserInfo(); if(null != userInfo){ return userInfo.getOpenid(); } }catch (Exception e){ log.error("获取用户信息失败:",e); } return null; } }
以上则为钉钉扫码登录的主要流程,如有其他功能需求,可以查阅官网的文档说明,以扫码登录为例,访问网站:https://open.dingtalk.com/document/orgapp-server/obtain-the-user-information-based-on-the-sns-temporary-authorization。转载请说明出处