springboot實現第三方釘釘掃碼登錄


 本篇博客主要作為本人的日記,如果各位博友對以下內容有所疑問歡迎留言探討。

一、准備工作

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。轉載請說明出處


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM