钉钉第三方登录(网页免登 / OAuth2 授权)实战指南
说明:下面的步骤以 “企业内部 H5/管理后台接入钉钉扫码登录” 为例,流程和钉钉开放平台文档基本一致,核心就是:用户在钉钉里或扫码 → 拿到临时授权码 → 后端用临时代码换取用户身份 → 建立自己系统的登录态。你可以按需要替换成自己语言,这里给出一份常见的 Java(Spring Boot)示例。
记得点赞加收藏哦😁😁😁
1. 整体流程长啥样?
- 你的前端发起“去钉钉登录”的请求(两种常见方式):
- A. 在 PC 浏览器上展示一个 钉钉扫码登录二维码;
- B. 在钉钉内置浏览器里访问你的 H5 页面,这时可以走 免登。
- 用户扫码 / 点授权后,钉钉会把一个 临时授权码(code) 回给你(有的方式是前端拿到再传给你,有的是钉钉直接回调到你配置的 redirect_uri)。
- 你的后端拿着这个 code + 应用的 appKey/appSecret 去钉钉服务器换 用户身份信息(userId / unionId / openId 等)。
- 拿到钉钉用户身份后,你的系统做一层 本系统用户绑定:
- 已经绑定过:直接把这个系统用户登录;
- 没绑定过:走一次绑定页面,让他选或绑定账号。
- 系统生成自己的 JWT / Session / Token,后面都走你自己的鉴权。
2. 需要准备的东西
- 钉钉开发者账号(https://open-dev.dingtalk.com/ )
- 创建应用:
- 如果是企业内部用,选「企业内部应用」;
- 也可以用「自建应用」。
- 在应用里拿到:
AppKeyAppSecret
- 配置 回调域名 / 白名单,比如:
- 授权回调地址:
https://your-domain.com/api/dingtalk/callback - 前端域名:
https://your-domain.com
- 授权回调地址:
- 服务器要能访问钉钉的开放平台接口(外网)
3. 钉钉登录的几种常见方式
钉钉的登录有几个名字,别被绕晕了,本质都差不多:
- 扫码登录(适合 PC 网页)
- 页面上嵌入钉钉官方提供的二维码 JS
- 用户用手机钉钉扫 → 钉钉把 code 回给你
- H5 免登 / 微应用免登(适合钉钉内打开的页面)
- 在钉钉里打开你页面时,前端先调用钉钉 JSAPI
dd.runtime.permission.requestAuthCode - 得到
code后丢给你后端
- 在钉钉里打开你页面时,前端先调用钉钉 JSAPI
- OAuth2 静态回调方式
- 通过钉钉的授权链接跳转,授权完成后回到你的 redirect_uri,带上 code
后端处理这几个方式其实是一样的:拿 code → 换用户信息。
下面给你说一个比较通用、实战里最好落地的两段式方案:前端拿 code → 后端换用户。
4. 前端:在钉钉内置浏览器里拿临时授权码
如果你的页面就是在钉钉里打开的(最常见情况),可以这样:
- 页面引入钉钉 JS SDK(在钉钉开放平台能看到示例)
- 调用:
dd.ready(function() {
dd.runtime.permission.requestAuthCode({
corpId: "你的企业corpId",
onSuccess: function(info) {
// info.code 就是临时授权码
const code = info.code;
// 把 code 发给你后台
fetch('/api/dingtalk/login', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({ code })
}).then(r => r.json()).then(res => {
// 收到你系统自己的token,保存起来
});
},
onFail: function(err) {
console.error(err);
}
})
});
注意点:
- 这个
corpId在钉钉后台就能看到; - 这个临时码是一次性的,有时效的;
- 这个方式适合“钉钉里打开的 H5/微应用”。
5. 前端:PC 网页扫码登录
如果你是做 PC 管理后台,要让用户拿手机钉钉扫一扫登录,可以用官方的扫码组件。
HTML 里准备一个容器:
<div id="dingtalk_qr"></div>
<script src="https://g.alicdn.com/dingding/dinglogin/0.0.5/ddLogin.js"></script>
<script>
var redirectUri = encodeURIComponent('https://your-domain.com/api/dingtalk/callback');
var appId = '你的AppId'; // 在钉钉后台应用详情里
var gotoUrl = 'https://oapi.dingtalk.com/connect/qrconnect?appid=' + appId
+ '&response_type=code&scope=snsapi_login&state=STATE&redirect_uri=' + redirectUri;
var obj = DDLogin({
id: "dingtalk_qr",
goto: gotoUrl,
style: "border:none;background-color:#FFFFFF;",
width : "365",
height: "400"
});
</script>
扫码后,钉钉会跳转到你配置的 redirect_uri,并带上 code,比如:
GET https://your-domain.com/api/dingtalk/callback?code=xxxx&state=STATE
后台这个接口就能拿到 code 继续干活。
6. 后端:用 code 换取用户信息
下面给一个 Java / Spring Boot 的示例思路,方便你直接嵌到项目里。你实际要看你用的是 企业内部应用登录 还是 扫码登录,调用的 URL 会略有差别,整体都遵循:先换 access_token → 再查用户 这套逻辑。
⚠️ 下面的接口地址可能会有版本升级,实际以钉钉开放平台最新文档为准;示例主要看结构。
6.1 先拿企业 access_token
public String getAccessToken() {
String appKey = "你的appKey";
String appSecret = "你的appSecret";
String url = "https://oapi.dingtalk.com/gettoken?appkey=" + appKey + "&appsecret=" + appSecret;
// 发起HTTP GET请求,拿到access_token
// 返回结果示例:{"errcode":0,"access_token":"xxx","expires_in":7200}
}
6.2 用前端传来的 code 换 userid
如果你是走的 免登,一般是这样的接口:
POST https://oapi.dingtalk.com/topapi/v2/user/getuserinfo
参数里带code和access_token
示例(伪代码):
@PostMapping("/api/dingtalk/login")
public ResponseEntity<?> dingtalkLogin(@RequestBody Map<String, String> body) {
String code = body.get("code");
String accessToken = getAccessToken();
// 1. 用 code 换 user info
String url = "https://oapi.dingtalk.com/topapi/v2/user/getuserinfo";
// 这个接口需要POST和特定body,这里用伪代码表示
// 请求体里通常要传 { "code": code }
// 带上 access_token
// 假设你拿到了 dingUserId
String dingUserId = "解析返回里的userid";
// 2. 再查这个用户的详细信息(如名字、手机号等)
// https://oapi.dingtalk.com/topapi/v2/user/get?access_token=xxx
// 请求里传 corpId + userid
// 3. 根据 dingUserId 去你自己库里找有没有对应的系统用户
// 比如 user表里有个 dingtalk_userid 字段
// 没有的话要么创建,要么让前端走绑定
String systemToken = createSystemTokenByDingUserId(dingUserId);
return ResponseEntity.ok(Map.of(
"token", systemToken,
"dingUserId", dingUserId
));
}
要点:
- 第一次拿到的通常只是钉钉侧的标识,不是你系统的;
- 你要自己维护一张“钉钉ID → 系统用户ID”的映射表;
- 最后返回给前端的一定是你系统自己的 token,别直接把钉钉的返回给前端。
7. 你的系统需要做的表结构(推荐)
搞个简单表:user_third_bind:
| 字段名 | 类型 | 说明 |
|---|---|---|
| id | bigint | 主键 |
| user_id | bigint | 你系统里的用户ID |
| third_type | varchar | 比如 dingtalk |
| third_user_id | varchar | 钉钉返回的userid/unionid |
| extra | json | 其他信息(名字、头像) |
| create_time | datetime | |
| update_time | datetime |
登录时的逻辑:
- 后端拿到钉钉userid
- 在
user_third_bind找有没有这条 - 有 → 查出 user_id → 签发你自己系统的token
- 没有 → 返回前端一个“未绑定”的状态码,让前端跳到绑定页面
这样你后面要加 企业微信登录、飞书登录 都能共用这一张表,登录逻辑是统一的。
8. 回调地址怎么配?
在钉钉开放平台应用的「登录与分享」或相关配置里,找到 回调域名 / 回调地址,把你的地址写进去,比如:
https://your-domain.com/api/dingtalk/callback
注意几点:
- 必须是 HTTPS(生产环境);
- 必须和你前端里跳转的 redirect_uri 一致;
- 有时候钉钉会校验域名白名单,域名要和你在钉钉后台配置的一致。
9. 本地调试怎么搞?
- 本地起个后端:
http://localhost:8080 - 用一个内网穿透 / 本地反向代理工具,把本地映射成一个公网 HTTPS,比如:
https://test.your-domain.com→http://localhost:8080 - 钉钉后台里配置这个公网地址当回调
- 前端本地页面访问本地接口就行了
这样你就能在本地真实走一遍钉钉扫码登录。
10. 常见坑
- code 已使用 / code 过期:临时授权码只能用一次,而且有效期短,前端千万别复用。
- 回调域名不一致:钉钉回调和你配置的不一样,就拿不到 code。
- 企业内部应用 vs 三方应用 API 不同:看文档里的接口路径,选对类型。
- 前端跨域:如果前端直接调你后端
/api/dingtalk/login,记得开 CORS。 - 用户第一次登录还没绑定:别直接报错,给前端一个“去绑定”的提示。
- token 缓存:
access_token有效期 2 小时,不要每次都去钉钉拿,缓存一下。
11. 小结一下
- 钉钉登录的核心就是“拿 code → 换用户 → 建立自己系统的会话”。
- 前端的工作只是把 code 交给你,后端才是主战场。
- 只要你把“钉钉用户ID → 系统用户ID”这条线绑住了,后面都简单。
如果你是 Java 项目,可以把上面第 6 节拆成:
DingTalkClient:专门调钉钉开放平台DingTalkAuthService:封装登录逻辑AuthController:提供接口给前端
这样结构就挺清爽了。
104

被折叠的 条评论
为什么被折叠?



