news 2026/3/4 6:45:23

实战案例:Spring Boot 快实现钉钉扫码登录(不需要企业认证)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
实战案例:Spring Boot 快实现钉钉扫码登录(不需要企业认证)

前置条件,准备clientid、clientsecrect密钥、回调地址即可(本地需要自备公网映射)。

实战案例:Spring Boot 快实现钉钉扫码登录

在企业级 OA 系统或内部工具开发中,“钉钉扫码登录”是最高频的需求之一。它能利用钉钉的身份认证体系,免去用户记忆账号密码的烦恼,同时实现企业架构的安全管控。

本文基于Spring Boot 2.x阿里新版 Tea SDK (2.0),还原从配置到代码落地的完整流程,重点解决403权限报错SDK参数类型不匹配等痛点。



一、 核心准备工作 (不做必错)

在写代码之前,必须先在 钉钉开发者后台 完成以下配置。****

1. 权限开通 (关键!)

痛点:代码跑通了,但最后一步获取用户信息时报错 403 Forbidden。

原因:未开通通讯录读取权限。

解决:

进入【应用开发】->【权限管理】,搜索并申请以下权限:

  • 通讯录个人信息读权限(核心:用于获取UnionIdNick,不申请会报 403)
  • 成员信息读权限(建议一并申请)

2. 配置回调域名

规则:前端代码里的redirect_uri必须与后台配置字符级完全一致

  • 开发配置->回调域名
    • 示例:http://domain.com:28088/login/callback# 回调你本地或公网的
    • 注意:请确保包含http://协议头和端口号。

二、 项目依赖配置 (Maven)

<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>com.aliyun</groupId> <artifactId>dingtalk</artifactId> <version>2.2.40</version> </dependency> <dependency> <groupId>com.aliyun</groupId> <artifactId>tea-openapi</artifactId> <version>0.3.1</version> </dependency> <dependency> <groupId>com.aliyun</groupId> <artifactId>tea-util</artifactId> <version>0.2.16</version> </dependency> </dependencies>

三、 前端实现 (内嵌二维码)

使用钉钉官方提供的ddlogin.js,可以在页面内通过div容器直接渲染二维码,无需跳转页面,体验更佳。

文件index.html

HTML

<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title>OA系统钉钉扫码登录</title> <script src="https://g.alicdn.com/dingding/h5-dingtalk-login/0.21.0/ddlogin.js"></script> <style> body { display: flex; justify-content: center; align-items: center; height: 100vh; background: #f0f2f5; } #login_box { background: #fff; padding: 20px; border-radius: 8px; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); } </style> </head> <body> <div id="login_box"></div> <script> // 必须与钉钉后台配置的一模一样 const REDIRECT_URI = "http://domain.com:28088/login/callback"; const CLIENT_ID = "dingw6c***sfqjrr"; // 您的ClientId window.DTFrameLogin( { id: 'login_box', width: 300, height: 300, }, { redirect_uri: REDIRECT_URI, client_id: CLIENT_ID, scope: 'openid', // 固定值 response_type: 'code', // 固定值 state: 'my_oa_security_token', // 防止CSRF,生产环境建议随机生成 prompt: 'consent', }, (loginResult) => { // 扫码成功后,钉钉返回 redirectUrl,其中包含了 authCode window.location.href = loginResult.redirectUrl; }, (errorMsg) => { alert("二维码加载失败: " + JSON.stringify(errorMsg)); } ); </script> </body> </html>

四、 后端实现 (核心逻辑)

后端逻辑遵循“Code 换 Token -> Token 换 UserInfo”的标准流程。

package org.example.dingdingscan; import com.aliyun.teaopenapi.models.Config; import com.aliyun.dingtalkoauth2_1_0.Client; import com.aliyun.dingtalkoauth2_1_0.models.*; import com.aliyun.dingtalkcontact_1_0.models.*; import com.aliyun.teautil.models.RuntimeOptions; // 必须引入 import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping("/login") public class DingLoginController { // 替换为您的真实配置 private static final String CLIENT_ID = "dingw6cv1****fqjrr"; private static final String CLIENT_SECRET = "uiGdvr7xztEU****uLgmSv0O1nOiPoe0-vmkfYWHxMDAeiDIv42QEFY"; @GetMapping("/callback") public String callback(@RequestParam("authCode") String authCode) { try { // --- 步骤 1:初始化基础配置 --- Config config = new Config(); config.protocol = "https"; config.regionId = "central"; // --- 步骤 2:使用 OAuth2 Client 获取 AccessToken --- Client oauthClient = new Client(config); GetUserTokenRequest tokenRequest = new GetUserTokenRequest() .setClientId(CLIENT_ID) .setClientSecret(CLIENT_SECRET) .setCode(authCode) .setGrantType("authorization_code"); GetUserTokenResponse tokenResponse = oauthClient.getUserToken(tokenRequest); String userAccessToken = tokenResponse.getBody().getAccessToken(); // --- 步骤 3:使用 Contact Client 获取用户信息 --- com.aliyun.dingtalkcontact_1_0.Client contactClient = new com.aliyun.dingtalkcontact_1_0.Client(config); GetUserHeaders headers = new GetUserHeaders(); headers.setXAcsDingtalkAccessToken(userAccessToken); // 【核心修正点】使用 WithOptions 避免参数类型报错 GetUserResponseBody userBody = contactClient.getUserWithOptions( "me", // "me" 代表查询当前用户 headers, new RuntimeOptions() // 运行时参数,不可为 null ).getBody(); // --- 步骤 4:提取核心数据 --- String dingUserId = userBody.getUnionId(); // 全局唯一ID String nick = userBody.getNick(); String avatar = userBody.getAvatarUrl(); // 在此处对接您的 OA 数据库: // select * from sys_user where union_id = dingUserId return "<div style='text-align:center; padding:50px;'>" + "<h2>🎉 登录成功</h2>" + "<img src='" + avatar + "' style='width:64px;border-radius:50%;'><br/>" + "<b>欢迎回来:</b> " + nick + "<br/>" + "<b>UnionId:</b> " + dingUserId + "</div>"; } catch (Exception e) { e.printStackTrace(); return "❌ 登录失败: " + e.getMessage(); // 常见错误如 403 会在这里捕获 } } }

五、 总结与排查速查表

在整个实施过程中,请对照以下表格自查:

错误现象可能原因解决方案
二维码加载不出来前端client_idredirect_uri配置错误检查代码与钉钉后台【回调域名】是否完全一致。
Code: 403 Forbidden接口权限未开通钉钉后台 -> 权限管理 -> 申请“通讯录个人信息读权限”
Maven 找不到包依赖版本过旧或模块拆分错误使用dingtalk聚合包,版本推荐2.2.40
Required String…SDK 方法签名不匹配改用getUserWithOptions替代getUser
手机号为空企业未认证未认证企业通常无法通过 API 获取手机号,建议使用UnionId做账号绑定。

通过以上步骤,成功实现从扫码到获取用户身份**的完整闭环。该方案代码结构清晰,且规避了常见的版本兼容性问题。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/2/23 14:00:25

7步构建企业级自动化部署:从触发到监控的完整指南

7步构建企业级自动化部署&#xff1a;从触发到监控的完整指南 【免费下载链接】webhook webhook is a lightweight incoming webhook server to run shell commands 项目地址: https://gitcode.com/gh_mirrors/we/webhook 在当今快速迭代的软件开发环境中&#xff0c;We…

作者头像 李华
网站建设 2026/3/3 12:44:23

Auto.js微信跳一跳智能辅助完全指南

Auto.js微信跳一跳智能辅助完全指南 【免费下载链接】Auto.js微信跳一跳辅助说明分享 Auto.js微信跳一跳辅助说明 项目地址: https://gitcode.com/Open-source-documentation-tutorial/747cc 项目概述 还在为微信跳一跳的分数而烦恼吗&#xff1f;Auto.js微信跳一跳智能…

作者头像 李华
网站建设 2026/3/1 13:50:01

ESP32引脚控制门锁系统:从零实现家庭安全方案

用ESP32引脚控制电磁锁&#xff1a;手把手打造低成本智能门禁系统你有没有过这样的经历&#xff1f;出门忘带钥匙&#xff0c;站在门口干着急&#xff1b;或者朋友临时来访&#xff0c;却没法远程开门。传统机械锁虽然可靠&#xff0c;但使用体验早已跟不上现代生活的节奏。而市…

作者头像 李华
网站建设 2026/2/20 15:46:25

KAT-Dev-FP8:企业级AI编程部署的量化技术突破与60%成本优化方案

在AI编程工具快速发展的当前阶段&#xff0c;企业面临着"高性能必然高成本"的行业困境。Kwaipilot团队推出的KAT-Dev-FP8开源编程模型&#xff0c;通过创新的FP8量化技术&#xff0c;在保持62.4% SWE-bench Verified解决率的同时&#xff0c;将企业部署成本降低60%&a…

作者头像 李华
网站建设 2026/2/28 9:05:05

ckeditor网页编辑器IE下word图片粘贴转存优化

山东某国企项目需求实现记录&#xff1a;基于CKEditor4的Word/微信内容集成方案 一、需求分析与技术选型 核心需求&#xff1a; 编辑器插件需支持&#xff1a; Word粘贴&#xff08;保留格式图片自动上传&#xff09;Word/Excel/PPT/PDF导入&#xff08;保留格式图片&#xff…

作者头像 李华
网站建设 2026/3/1 10:55:52

ckeditor html编辑器IE下word图片粘贴转存实践

军工级富文本内容迁移解决方案技术评估日志 2023年X月X日 于长沙研发中心 一、需求拆解与技术调研 1.1 核心需求矩阵 需求类型技术指标信创要求Word粘贴保留形状/表格/公式等复杂样式&#xff0c;图片自动转存OSS支持银河麒麟V10飞腾FT-2000环境文档导入支持Office/PDF格式解…

作者头像 李华