SpingBoot-Vue 前后端分离—实现钉钉免登功能(2025)

news/2025/2/21 5:44:35/

一、需求分析

        要实现钉钉免登功能,需要按照钉钉开放平台所提供步骤,进一步可以细分成以下操作:

    A [用户访问应用] --> B [获取临时授权码(code)]
    B --> C [应用服务器请求access_token]
    C --> D [钉钉服务器返回access_token]
    D --> E [应用服务器请求用户信息]
    E --> F [钉钉服务器返回用户信息]
    F --> G [应用服务器处理用户信息]
    G --> H [用户登录成功]   

总结过后,具体免登流程如下:

  1. 调用本接口获取免登授权码。
  2. 调用获取应用的 Access Token接口,获取应用访问凭证。
  3. 调用通过免登码获取用户信息接口,获取用户userid。
  4. 调用查询用户详情接口,获取用户信息。

二、具体实现

①、前端实现

 以某信息确认系统首页为例,若是钉钉环境下,直接实现免登操作,若不是钉钉环境,则实现账号和密码的方式进行登录:

<template><div><div class="login"><p>XXX信息确认系统</p><div class="loginContent"><div class="fromuseruser"><input type="text" v-model="user_name" placeholder="请输入账号" /></div><div class="frompassword"><inputtype="password"v-model="user_password"placeholder="请输入密码"/></div></div><div class="submit"><van-buttontype="primary":round="true"loading-text="加载中..."size="normal"style="width:4.6rem"text="登 录"@click="submit"></van-button></div></div></div>
</template><script>
import * as dd from 'dingtalk-jsapi'
import { Notify } from 'vant'
import {UserLogin} from "@/api/request.js";
export default {data() {return {user_name:"",user_password: "",code: null,};},mounted(){// this.ddFun();window.addEventListener('keydown',this.keyDown)},methods:{ddFun(){let _this = this// corpId 在后台 -基本信息-开发信息-企业自用账户信息 下查看let corpId = ''dd.ready(()=> {// dd.ready参数为回调函数,在环境准备就绪时触发,jsapi的调用需要保证在该回调函数触发后调用,否则无效。dd.runtime.permission.requestAuthCode({corpId:corpId,onSuccess: result => {_this.code = result.code;let param = {code: _this.code,};_this.login(param);},onFail: err => {alert("dd error: " + JSON.stringify(err));},});});},submit(){if(this.user_name == '' || this.user_password == ''){Notify({type: "danger",message: `账号或密码不能为空`,});return;}let u_pass = this.$encruption(this.user_password) //对密码进行签名加密let param = {'uN':this.user_name,'pW':u_pass// 'pW':this.user_password};// this.login(param)UserLogin(param).then((res) => {console.log('登录Res',res);if (res.result == 1) {sessionStorage.setItem('tel',JSON.stringify(res.data.tel))sessionStorage.setItem('token',JSON.stringify(res.data.token))if(res.data.auth == 2){this.$router.push("/sensorjxpro/web/jxensure");}else if(res.data.auth == 1){this.$router.push("/sensorjxpro/web/staff/mobileweb");}} else {Notify({type: "danger",message: `${res.data.msg}`+ ','+`${res.data.data}`,});}})},// 回车登录keyDown(e){if(e.keyCode === 13){this.submit()}}},deactivated() {this.user_name = "";this.user_password = "";this.code = null;},destroyed(){window.removeEventListener('keydown',this.keyDown,false)}
}
</script><style lang="scss" scoped>
@import '@/style/login/login.scss'
</style>

关键钉钉免登的实现步骤主要是,通过 dd.runtime.permission.requestAuthCode 将code 传递给后端,后端进行解析,至此第一步,调用本接口获取免登授权码完成(前端也主要负责这一部分)

javascript">ddFun(){let _this = this// corpId 在后台 -基本信息-开发信息-企业自用账户信息 下查看let corpId = ''dd.ready(()=> {// dd.ready参数为回调函数,在环境准备就绪时触发,jsapi的调用需要保证在该回调函数触发后调用,否则无效。dd.runtime.permission.requestAuthCode({corpId:corpId,onSuccess: result => {_this.code = result.code;let param = {code: _this.code,};_this.login(param);},onFail: err => {alert("dd error: " + JSON.stringify(err));},});});},

②、后端实现

        将前端传来的code,调用获取应用的 Access Token接口,获取应用访问凭证。调用通过免登码获取用户信息接口,获取用户userid。调用查询用户详情接口,获取用户信息。并最终在数据库中根据name查询,二次确认,并将得到的name信息返回给前端。至此完成钉钉免登的全部流程。

subgraph 钉钉服务器
        D[返回access_token]
        F[返回用户信息]
    end

    subgraph 应用服务器
        C[请求access_token]
        E[请求用户信息]
        G[处理用户信息]
    end

/*** 用户登陆* http://localhost:8080/user/login* 0、判断是否包含code,包含进行钉钉免登陆方法;** 1、依据姓名密码查找user;* 2、使用jwtUtils生成token,token载体内容为 name、tel* 3、将LoginVo 赋值作为响应实体类的响应数据(data)** @return RespondDto*/@Overridepublic RespondDto userLogin(InParam inParam) {User user;if(inParam.getCode() == null){log.info("userLogin方法成功调用 userName:{}", inParam.getUN());inParam.setPW(rsaUtils.priKeyDecode(inParam.getPW()));user = loginMapper.selectUser(inParam.getUN(), inParam.getPW());log.info("userLogin查找方法调用完成,user:{}", user);}else{user = ddLogin(inParam);}if (user != null) {LoginVo loginVo = new LoginVo();loginVo.setName(user.getUserName());loginVo.setTel(user.getTel());loginVo.setToken(jwtUtils.tokenMaker(user));loginVo.setAuth(user.getAuth());return new RespondDto(ResultCode.OK,"登录成功",loginVo);} else {return new RespondDto(ResultCode.USER_NONE, "登陆失败");}}/**钉钉免登陆* 1、获取 accessToken;* 2、获取用户信息,截取到name;* 3、用name查找 user;*/private User ddLogin(InParam inParam) {String code = inParam.getCode();// 获取access_tokenString accessToken = HttpHelper.getAccess_Token(appkey, appsecret);//不要获取userid,  不可与以下代码同用;DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/v2/user/getuserinfo");OapiV2UserGetuserinfoRequest req = new OapiV2UserGetuserinfoRequest();req.setCode(code);OapiV2UserGetuserinfoResponse rsp = null;try {rsp = client.execute(req, accessToken);} catch (ApiException e) {e.printStackTrace();}System.out.println(rsp.getBody());String body = rsp.getBody();String name = body.substring(body.indexOf("name\":\""),body.indexOf("\",\"sys")).substring(7);System.out.println(name);User user = loginMapper.selectUserByName(name);return user;}


http://www.ppmy.cn/news/1573529.html

相关文章

机器学习数理基础:从概率到梯度下降的全面解析

一、引言&#xff1a;为什么需要数理基础&#xff1f; 机器学习是数据与算法的艺术&#xff0c;而数学是其背后的语言。无论是理解模型原理、优化算法&#xff0c;还是解决实际问题&#xff0c;扎实的数理基础都是必不可少的。本文将从概率论、线性代数、微积分三大核心领域出发…

商城源码产品的品类

商城源码产品的品类繁多&#xff0c;哪个品类最实用取决于具体的业务需求和目标用户群体。以下是一些常见且实用的商城源码产品品类&#xff1a; 多用户商城系统 功能特点&#xff1a;支持多个商家入驻开店&#xff0c;每个商家可以有自己的店铺和独立运营管理权限&#xff0…

网络安全不分家 网络安全不涉及什么

何为网络安全 信息安全是指系统的硬件、软件及其信息受到保护&#xff0c;并持续正常运行和服务。信息安全的实质是保护信息系统和信息资源免受各种威胁、干扰和破坏&#xff0c;即保证信息的安全性。 网络安全是指利用网络技术、管理和控制等措施&#xff0c;保证网络系统和…

Ubuntu18.04/20.04开机自启运行脚本

首先&#xff0c;编写一个.sh文件。 #任意目录创建文件 touch start.sh#授予权限 sudo chmod x start.sh#编辑文件 gedit start.sh start.sh #! /bin/bash gnome-terminal -- bash -c "roslaunch wpr_simulation wpb_stage_robocup.launch; exec bash" echo “wp…

(LLaMa Factory)大模型训练方法--预训练(Qwen2-0.5B)

❗由于大模型的预训练需要数千个GPU并持续数月的时间&#xff0c;所以一般情况下实际工作中并不会涉及到预训练&#xff0c;本篇文章我们只做的简单流程体验。 1、准备训练数据 说明&#xff1a;LLaMa-Factory的Github上有训练数据格式的详细说明&#xff0c;请见README_zh。 …

STL介绍1:vector、pair、string、queue、map

一、vector&#xff1a;变长数组、倍增思想 1.常用函数 size()&#xff1a;返回元素个数 empty()&#xff1a;返回是否为空 clear()&#xff1a;清空 front() / bcak() push_back() / pop_back()&#xff1a;尾部插入和删除 2.存储方式 #include<iostream> #incl…

vite让每个scss文件自动导入某段内容

写了如下一个scss函数&#xff0c;希望自动导入到每个scss文件里面 vite.config.ts里面如下配置 import fs from fsconst filePath resolve(__dirname, ./src/assets/css/index.scss);const Minxcss fs.readFileSync(filePath, utf8); css: {preprocessorOptions: {scss: {…

Grafana——如何迁移Grafana到一台新服务器

背景 有时候由于服务器更新之类的&#xff0c;我们需要迁移一整套Grafana&#xff0c;这时候该怎么操作呢&#xff1f; 下面让我一步步说明下 安装Grafana 在新的服务器上安装Grafana 这个不再赘述&#xff0c;可以看一下我之前的文章 备份及迁移 迁移配置文件 配置文件即…