springboot集成钉钉扫码登录

最近项目要做一个登录页面进行钉钉扫码登录的功能,再这里做一下笔记和心得吧

前端登录页面代码,这里前端是用的vue:
第一步,在全局的public下的index.html添加所需要的js文件


image.png
<script src="https://g.alicdn.com/dingding/dinglogin/0.0.5/ddLogin.js"></script>

第二步,把之前的登录页面修改成下面这样,样式自己调成自己喜欢的,这里的登录页面是login.vue,这里面的回调地址和你的应用中回调地址是一致的

image.png
<template>
  <div class="login">
    <el-form ref="loginForm" :model="loginForm" class="login-form">
      <h3 class="title">登录</h3>
      <div id="login_container"></div>
    </el-form>
    <!--  底部  -->
    <div class="el-login-footer">
      <span>登录页面</span>
    </div>
  </div>
</template>

<script>
import { loginCode } from "@/api/login";
export default {
  name: "Login",
  data() {
    return {
   
    };
  },
  watch: {
    $route: {
      handler: function (route) {
        this.redirect = route.query && route.query.redirect;
      },
      immediate: true,
    },
  },
  mounted() {
    let str = this.$route.query.redirect;
    if (str) {
      let index = str.indexOf("=");
      let code = str.substr(index + 1, str.length);
      this.handleCodeLogin(code);
    } else {
      this.ddLoginInit();
    }
  },
  methods: {
    // 钉钉扫码登录初始化函数
    ddLoginInit() {
      console.log(200);
      let url = encodeURIComponent(`http://localhost:80`); //此处url写钉钉回调地址
      let appid = ""; //填写自己在钉钉开发者平台配的appid
      let goto = encodeURIComponent(
        `https://oapi.dingtalk.com/connect/oauth2/sns_authorize?appid=${appid}&response_type=code&scope=snsapi_login&state=STATE&redirect_uri=${url}`
      );

      let obj = DDLogin({
        id: "login_container", //对应刚刚的div盒子id
        goto: goto,
        style: "border:none;background-color:#FFFFFF;",
        width: 365,
        height: 350,
      });
      let handleMessage = (event) => {
        let origin = event.origin;
        if (origin == "https://login.dingtalk.com") {
          let loginTmpCode = event.data;
          window.location.href = `https://oapi.dingtalk.com/connect/oauth2/sns_authorize?appid=${appid}&response_type=code&scope=snsapi_login&state=STATE&redirect_uri=${url}&loginTmpCode=${loginTmpCode}`;
        }
      };
      if (typeof window.addEventListener != "undefined") {
        window.addEventListener("message", handleMessage, false);
      } else if (typeof window.attachEvent != "undefined") {
        window.attachEvent("onmessage", handleMessage);
      }
    },

    // 钉钉登录函数
    async handleCodeLogin(code) {
      //此处根据自己需求使用code
      let res = await loginCode(code);
      if (res) {
        //根据需要的返回需要的用户信息进行权限验证
      }
    },

第三步,login.js里面写上自己的登录函数中需要的请求方法

// 钉钉扫码登录接口
export function loginCode(code) {
  return request({
    url: '/DingLogin?code='+code,
    method: 'get',
  })
}

前端到这里就结束了,接下来就是后端代码,我这里后端用的springboot

第一步,在pom文件中添加sdk,在主pom文件中添加,然后需要引用的地方引用,我这边是在网关服务和主pom中添加的


image.png
//这里是主pom.xml添加的
<dingtalk.version>1.0.1</dingtalk.version>
<dependency>
                <groupId>com.aliyun</groupId>
                <artifactId>alibaba-dingtalk-service-sdk</artifactId>
                <version>${dingtalk.version}</version>
            </dependency>
//这里是auth中的pom.xnl中添加的
 <dependency>
            <groupId>com.aliyun</groupId>
            <artifactId>alibaba-dingtalk-service-sdk</artifactId>
        </dependency>

第二步,创建一个登录的controller,把钉钉教程文档中的代码复制过来
钉钉第三方扫码登录文档地址:https://developers.dingtalk.com/document/tutorial/scan-qr-code-to-log-on-to-third-party-websites?spm=ding_open_doc.21783679.J_8506627640.1.3db24ce9awRO4R
然后就报错了,有两个方法找不到,这边可能jar包更新了,文档没有更新,我直接给我修改过的代码

package com.dualshare.auth.controller;
import com.alibaba.fastjson.JSONObject;
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.request.OapiUserGetUseridByUnionidRequest;
import com.dingtalk.api.request.OapiV2UserGetRequest;
import com.dingtalk.api.response.OapiGettokenResponse;
import com.dingtalk.api.response.OapiSnsGetuserinfoBycodeResponse;
import com.dingtalk.api.response.OapiUserGetUseridByUnionidResponse;
import com.dingtalk.api.response.OapiV2UserGetResponse;
import com.dualshare.auth.service.SysLoginService;
import com.dualshare.common.core.domain.R;
import com.dualshare.common.security.service.TokenService;
import com.dualshare.system.api.model.LoginUser;
import com.taobao.api.ApiException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import java.util.Map;

/**
 * 钉钉扫码登录
 */
@RestController
public class LoginController {

    @Autowired
    private TokenService tokenService;

    @Autowired
    private SysLoginService sysLoginService;


    @Value("${Ding.appId}")
    private String appId;

    @Value("${Ding.appSecret}")
    private String appSecret;

    @Value("${Ding.getTokenUrl}")
    private String getTokenUrl;

    @Value("${Ding.getUserInfoUrl}")
    private String getUserInfoUrl;

    @Value("${Ding.getUnionIdUrl}")
    private String getUnionIdUrl;

    @Value("${Ding.getUserByUserIdUrl}")
    private String getUserByUserIdUrl;

    @RequestMapping(value = "/DingLogin")
    public R<?> DingLogin(@RequestParam("code") String code) {
        try {
            // 获取access_token,注意正式代码要有异常流处理
            String access_token = getToken();
            // 通过临时授权码获取授权用户的个人信息
            DefaultDingTalkClient client2 = new DefaultDingTalkClient(getUserInfoUrl);
            OapiSnsGetuserinfoBycodeRequest reqBycodeRequest = new OapiSnsGetuserinfoBycodeRequest();
            // 通过扫描二维码,跳转指定的redirect_uri后,向url中追加的code临时授权码
            reqBycodeRequest.setTmpAuthCode(code);
            // 修改appid和appSecret为步骤三创建扫码登录时创建的appid和appSecret
            OapiSnsGetuserinfoBycodeResponse bycodeResponse = client2.execute(reqBycodeRequest, appId, appSecret);
            // 根据unionid获取userid
            String unionid = bycodeResponse.getUserInfo().getUnionid();
            DingTalkClient clientDingTalkClient = new DefaultDingTalkClient(getUnionIdUrl);
            OapiUserGetUseridByUnionidRequest reqGetbyunionidRequest = new OapiUserGetUseridByUnionidRequest();
            reqGetbyunionidRequest.setUnionid(unionid);
            OapiUserGetUseridByUnionidResponse oapiUserGetbyunionidResponse = clientDingTalkClient.execute(reqGetbyunionidRequest, access_token);
            if (oapiUserGetbyunionidResponse.getErrcode() == 60121L) {
                return R.fail();
            }
            // 根据userId获取用户信息
            String rBody = oapiUserGetbyunionidResponse.getBody();
            String userid=null;
            if (rBody!=null){
                if (JSONObject.parseObject(rBody).get("result")!=null){
                    Map map =JSONObject.parseObject(JSONObject.parseObject(rBody).get("result").toString());
                    if (map.get("userid")!=null){
                        userid =map.get("userid").toString();
                    }
                }
            }
            if (userid==null){
                System.out.println(oapiUserGetbyunionidResponse.getErrmsg());
                return R.fail(oapiUserGetbyunionidResponse.getErrmsg());
            }
            DingTalkClient clientDingTalkClient2 = new DefaultDingTalkClient(getUserByUserIdUrl);
            OapiV2UserGetRequest reqGetRequest = new OapiV2UserGetRequest();
            reqGetRequest.setUserid(userid);
            reqGetRequest.setLang("zh_CN");
            OapiV2UserGetResponse rspGetResponse = clientDingTalkClient2.execute(reqGetRequest, access_token);
            System.out.println(rspGetResponse.getBody());
            String body = rspGetResponse.getBody();
            Map map =JSONObject.parseObject(JSONObject.parseObject(body).get("result").toString());
            //根据自己的需求,获取对应的所需要的东西返回给前端
            return R.ok();
        } catch (ApiException e) {
            e.printStackTrace();
            return R.fail(e);
        }
    }

    public String getToken() {
        try {
            DefaultDingTalkClient client = new DefaultDingTalkClient(getTokenUrl);
            OapiGettokenRequest request = new OapiGettokenRequest();
            // 填写步骤一创建应用的Appkey
            request.setAppkey(appId);
            // 填写步骤一创建应用的Appsecret
            request.setAppsecret(appSecret);
            request.setHttpMethod("GET");
            OapiGettokenResponse response = client.execute(request);
            String accessToken = response.getAccessToken();
            return accessToken;
        } catch (ApiException e) {
            throw new RuntimeException();
        }
    }
}

yml里面的配置

#Dingding扫码配置
Ding:
  appId: "你的appkey"
  appSecret: "你的appSecret"
  getTokenUrl: "https://oapi.dingtalk.com/gettoken"
  getUserInfoUrl: "https://oapi.dingtalk.com/sns/getuserinfo_bycode"
  getUnionIdUrl: "https://oapi.dingtalk.com/topapi/user/getbyunionid"
  getUserByUserIdUrl: "https://oapi.dingtalk.com/topapi/v2/user/get"

到这里启动前后端,然后访问登录页面就结束了


image.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容