本篇博客主要作為本人的日記,如果各位博友對以下內容有所疑問歡迎留言探討。
一、准備工作
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。轉載請說明出處