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。转载请说明出处

posted @ 2022-01-27 22:35  陈远波  阅读(2716)  评论(0编辑  收藏  举报