Java 实现企业微信扫码登录
Java 实现企业微信扫码登录引言企业微信扫码登录是目前企业应用中常见的身份认证方式尤其适合企业内部的Web管理系统。用户通过企业微信App扫描二维码即可完成登录无需输入账号密码提升了用户体验和安全性。本文将从原理出发结合Java代码示例逐步实现企业微信扫码登录功能。## 企业微信扫码登录原理企业微信扫码登录基于OAuth2.0协议主要流程如下1.生成二维码后端生成一个包含临时授权码code的URL前端将其渲染为二维码。2.用户扫码用户使用企业微信扫描二维码确认登录请求。3.回调通知企业微信服务器将授权码通过回调地址发送给后端。4.获取用户信息后端使用授权码、企业ID、应用Secret等参数调用企业微信API获取用户的access_token和userid。5.完成登录根据userid查询用户信息生成Session或JWT令牌完成登录。## 准备工作### 1. 注册企业微信应用- 登录企业微信管理后台创建自建应用获取CorpID和Secret。- 配置应用的“网页授权及JS-SDK”域名以及“回调域名”。### 2. 依赖引入使用Spring Boot作为框架引入以下依赖xmldependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId/dependencydependency groupIdcom.squareup.okhttp3/groupId artifactIdokhttp/artifactId version4.9.3/version/dependency## 核心实现步骤### 1. 生成二维码URL扫码登录需要提供一个指向企业微信授权页的URL示例代码如下javaimport org.springframework.beans.factory.annotation.Value;import org.springframework.stereotype.Controller;import org.springframework.ui.Model;import org.springframework.web.bind.annotation.GetMapping;Controllerpublic class LoginController { Value(${wechat.corpId}) private String corpId; Value(${wechat.redirectUri}) private String redirectUri; GetMapping(/login) public String login(Model model) { // 构造授权URL注意需要URL编码 String authorizeUrl https://open.work.weixin.qq.com/wwopen/sso/qrConnect? appid corpId agentid1000002 // 需要替换为你的应用AgentId redirect_uri java.net.URLEncoder.encode(redirectUri) statestate; model.addAttribute(qrCodeUrl, authorizeUrl); return login; // 返回模板页面 }}前端页面login.html可使用img标签或第三方库如qrcode.js生成二维码html!DOCTYPE htmlhtmlbody h2企业微信扫码登录/h2 img th:src${qrCodeUrl} alt扫码登录二维码 //body/html### 2. 回调处理与获取用户信息用户扫码后企业微信会回调redirect_uri携带code和state参数。后端需处理回调获取用户信息javaimport okhttp3.OkHttpClient;import okhttp3.Request;import okhttp3.Response;import com.fasterxml.jackson.databind.JsonNode;import com.fasterxml.jackson.databind.ObjectMapper;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RequestParam;import org.springframework.web.bind.annotation.RestController;import javax.servlet.http.HttpSession;RestControllerpublic class CallbackController { Value(${wechat.corpId}) private String corpId; Value(${wechat.secret}) private String secret; private final OkHttpClient client new OkHttpClient(); private final ObjectMapper mapper new ObjectMapper(); GetMapping(/callback) public String callback(RequestParam(code) String code, RequestParam(state) String state, HttpSession session) throws Exception { // 1. 获取access_token String tokenUrl https://qyapi.weixin.qq.com/cgi-bin/gettoken? corpid corpId corpsecret secret; Request tokenRequest new Request.Builder().url(tokenUrl).get().build(); Response tokenResponse client.newCall(tokenRequest).execute(); JsonNode tokenJson mapper.readTree(tokenResponse.body().string()); String accessToken tokenJson.get(access_token).asText(); // 2. 通过code获取用户userid String userInfoUrl https://qyapi.weixin.qq.com/cgi-bin/user/getuserinfo? access_token accessToken code code; Request userRequest new Request.Builder().url(userInfoUrl).get().build(); Response userResponse client.newCall(userRequest).execute(); JsonNode userJson mapper.readTree(userResponse.body().string()); String userId userJson.get(UserId).asText(); // 注意企业微信返回的是UserId不是OpenId // 3. 模拟登录将userId存入Session session.setAttribute(userId, userId); return 登录成功用户ID: userId; }}## 深入原理分析### OAuth2.0授权码模式上述流程本质上是OAuth2.0的授权码模式-资源所有者企业微信用户-客户端我们的Web应用-授权服务器企业微信服务器-资源服务器企业微信用户信息API关键点在于-code是一次性的有效期很短约5分钟防止重放攻击。-state参数用于防止CSRF攻击后端需验证state值是否与发起请求时的一致。-access_token是企业微信服务器颁发的临时令牌用于调用后续API。### 安全性考虑1.Secret保护CorpSecret是敏感信息应存储在配置中心或环境变量避免硬编码。2.HTTPS请求所有与企业微信的通信必须使用HTTPS。3.Session管理用户登录后应使用安全的Session或JWT并设置过期时间。## 完整代码示例含异常处理以下是一个更完整的回调处理示例包含异常处理和日志记录javaimport org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Value;import org.springframework.web.bind.annotation.*;import javax.servlet.http.HttpSession;import java.io.IOException;RestControllerpublic class WeChatLoginService { private static final Logger log LoggerFactory.getLogger(WeChatLoginService.class); Value(${wechat.corpId}) private String corpId; Value(${wechat.secret}) private String secret; GetMapping(/auth/callback) public String handleCallback(RequestParam(code) String code, RequestParam(state) String state, HttpSession session) { try { // 验证state实际项目中应检查与session中存储的state是否一致 if (!state.equals(state)) { return state校验失败可能存在CSRF攻击; } // 获取access_token String accessToken getAccessToken(); if (accessToken null) { return 获取access_token失败; } // 通过code获取用户信息 String userId getUserId(accessToken, code); if (userId null) { return 获取用户信息失败; } // 登录成功存储用户信息 session.setAttribute(userId, userId); log.info(用户 {} 通过扫码登录成功, userId); return 登录成功欢迎 userId; } catch (Exception e) { log.error(回调处理异常, e); return 登录失败请重试; } } private String getAccessToken() throws IOException { String url String.format(https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid%scorpsecret%s, corpId, secret); Request request new Request.Builder().url(url).get().build(); Response response new OkHttpClient().newCall(request).execute(); JsonNode json new ObjectMapper().readTree(response.body().string()); if (json.has(errcode) json.get(errcode).asInt() ! 0) { log.error(获取access_token失败: {}, json); return null; } return json.get(access_token).asText(); } private String getUserId(String accessToken, String code) throws IOException { String url String.format(https://qyapi.weixin.qq.com/cgi-bin/user/getuserinfo?access_token%scode%s, accessToken, code); Request request new Request.Builder().url(url).get().build(); Response response new OkHttpClient().newCall(request).execute(); JsonNode json new ObjectMapper().readTree(response.body().string()); if (json.has(errcode) json.get(errcode).asInt() ! 0) { log.error(获取用户信息失败: {}, json); return null; } return json.get(UserId).asText(); }}## 总结本文从原理到代码实现详细介绍了Java实现企业微信扫码登录的完整流程。核心步骤包括生成授权URL、处理回调获取code、通过企业微信API获取access_token和用户信息最终完成登录。实际开发中还需注意配置管理、异常处理、Session安全等细节。扫码登录不仅提升了用户体验也增强了系统安全性是企业级应用的常用认证方式。建议读者结合企业微信官方文档根据实际业务需求进行扩展如绑定已有账号、权限校验等。

相关新闻

C++二进制序列化实战:从协议栈到字节流的高效实现

C++二进制序列化实战:从协议栈到字节流的高效实现

1. 项目概述:从协议栈到字节流 搞通信协议开发,尤其是用C这种贴近硬件的语言,你迟早会碰到一个核心问题:如何把内存里那些结构体、对象,变成一串能在网线、串口或者总线上飞驰的字节流,到了对端再原封不动地…

2026/7/24 4:51:17阅读更多 →
AI直播场控系统:从架构设计到部署实践

AI直播场控系统:从架构设计到部署实践

1. 项目概述:AI直播场控系统的核心价值直播行业正在经历从人工运营向智能化管理的转型。传统直播中,场控人员需要同时监控多个平台的数据、实时调整直播策略、处理突发情况,工作强度大且容易出错。这套AI直播场控系统正是为解决这些痛点而生&…

2026/7/24 4:51:17阅读更多 →
Godot 4.0状态机实现:从原理到平台游戏下落状态实战

Godot 4.0状态机实现:从原理到平台游戏下落状态实战

在游戏开发中,角色状态管理是核心挑战之一。Godot 引擎内置的节点和信号机制为状态机实现提供了灵活的基础,但直接使用if-else或match语句管理状态容易导致代码臃肿和难以维护。有限状态机(FSM)模式将每个状态封装为独立对象&…

2026/7/24 4:51:17阅读更多 →
C++实现人民币大写转换:华为OD机试经典题解与工程实践

C++实现人民币大写转换:华为OD机试经典题解与工程实践

1. 项目概述与核心价值最近在准备华为OD机试的朋友,应该都绕不开“人民币转换”这道经典题目。它不仅是B卷的常客,更是检验一个程序员基本功和思维严谨性的绝佳试金石。题目本身并不复杂:给你一个不超过两位小数的数字,要求你将其…

2026/7/24 6:09:33阅读更多 →
AI辅助提示工程:从手工调优到自动化生成

AI辅助提示工程:从手工调优到自动化生成

1. 提示工程架构师的进化:从手工调优到AI辅助自动化三年前我刚接触提示工程时,还停留在反复修改关键词的手工调优阶段。记得当时为生成一个合格的电商产品描述,需要手动测试二十多个提示词变体。如今,AI辅助的提示词自动化生成技术…

2026/7/24 6:09:33阅读更多 →
C++项目集成Lua:轻量级封装库的设计与实现

C++项目集成Lua:轻量级封装库的设计与实现

1. 项目概述:为什么我们需要LuaCpp? 在C项目的开发中,我们常常面临一个经典的矛盾:性能与灵活性的权衡。C以其卓越的运行时效率和精细的内存控制能力,成为构建大型系统、游戏引擎、高频交易系统等核心组件的首选。然而…

2026/7/24 6:09:33阅读更多 →
思维链技术:提升大模型逻辑推理能力的关键方法

思维链技术:提升大模型逻辑推理能力的关键方法

1. 思维链技术概述&#xff1a;大模型推理能力的催化剂第一次在数学题测试中看到GPT-3.5把"若A>B且B>C&#xff0c;则A与C的关系是&#xff1f;"直接回答成"A<C"时&#xff0c;我就意识到大模型在逻辑推理上存在明显短板。直到2022年思维链&#…

2026/7/24 6:09:33阅读更多 →
TVMSTofu视频管理平台:多光谱智能监控与AI分析实践

TVMSTofu视频管理平台:多光谱智能监控与AI分析实践

1. TVMSTofu视频管理平台概述TVMSTofu Video Management System&#xff08;简称TVMS&#xff09;是一款面向多光谱智能监控场景的综合视频管理平台&#xff0c;由Tofu Intelligence公司研发。作为专为安防、边防、森林防火等专业领域设计的解决方案&#xff0c;该系统集成了视…

2026/7/24 6:09:33阅读更多 →
自回归与Seq2Seq模型:核心差异与应用场景解析

自回归与Seq2Seq模型:核心差异与应用场景解析

1. 自回归模型与序列到序列模型的核心差异1.1 模型架构的本质区别自回归模型&#xff08;如GPT系列&#xff09;采用单向注意力机制&#xff0c;每个时间步只能看到当前及之前的token。这种结构决定了它天然适合文本生成任务——就像人类写作时逐字思考的过程。我在实际使用GPT…

2026/7/24 6:07:33阅读更多 →
Go语言静态资源打包方案对比与实践指南

Go语言静态资源打包方案对比与实践指南

1. 项目背景与核心需求在Go语言开发中&#xff0c;我们经常需要处理静态资源文件的打包问题。无论是Web应用的模板文件、前端资源&#xff0c;还是配置文件、证书等&#xff0c;都需要随程序一起分发。传统做法是将这些文件与编译后的二进制文件放在同一目录下&#xff0c;但这…

2026/7/24 0:58:53阅读更多 →
Go语言实现高性能LDAP认证服务的架构与实践

Go语言实现高性能LDAP认证服务的架构与实践

1. 项目背景与核心价值LDAP&#xff08;轻量级目录访问协议&#xff09;作为企业级身份认证的黄金标准&#xff0c;已经服务了超过80%的财富500强公司。我在金融科技领域实施统一认证体系时&#xff0c;发现传统Java方案存在启动慢、内存占用高等痛点。而Go语言凭借其协程并发模…

2026/7/24 0:58:53阅读更多 →
【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

更多请点击&#xff1a; https://intelliparadigm.com 第一章&#xff1a;AI面试官实战指南的核心价值与适用场景 AI面试官并非替代人类HR的“黑箱工具”&#xff0c;而是以可解释、可审计、可迭代的方式&#xff0c;赋能招聘全链路的关键基础设施。其核心价值在于将主观经验沉…

2026/7/24 0:58:53阅读更多 →
我的编程之路:第一篇博客

我的编程之路:第一篇博客

大家好&#xff0c;我是一名编程初学者&#xff0c;同时这也是我编程学习之路上的第一篇博客。在这里&#xff0c;我想要向大家介绍我的一些想法和规划。a.自我介绍我是一个刚刚接触编程的新手&#xff0c;目前在学习c语言&#xff0c;我对编程世界充满了强烈的好奇。当然&…

2026/7/24 0:00:06阅读更多 →
【LeetCode 54】螺旋矩阵

【LeetCode 54】螺旋矩阵

问题描述&#xff1a; 解法&#xff1a; 1、模拟&#xff08;参考自【LeetCode 54】螺旋矩阵-CSDN博客&#xff09; int *spiralOrder(int **matrix, int matrixSize, int *matrixColSize, int *returnSize) {static const int dirs[4][2] {{0, 1}, {1, 0}, {0, -1}, {-1, …

2026/7/24 0:00:06阅读更多 →
2026 WAIC:模型隐身、智能体疯野,厂商竞赛聚焦办公场景与商业闭环

2026 WAIC:模型隐身、智能体疯野,厂商竞赛聚焦办公场景与商业闭环

知春路不相信模型领先今年WAIC大会&#xff0c;昔日AI六小龙来了五家&#xff0c;分别是Kimi、阶跃星辰、Minimax、百川智能、零一万物。连放弃基模的百川和零一万物都来了&#xff0c;唯一缺席的竟是近几个月来风光无限的智谱。&#xff08;DeepSeek一直不参加&#xff09;WAI…

2026/7/24 0:00:06阅读更多 →
YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

如果你在部署 YOLOv8 时&#xff0c;发现推理速度只有可怜的 1-2 FPS&#xff0c;而别人的演示视频却能跑到 30 FPS 以上&#xff0c;那么问题很可能不在模型本身&#xff0c;而在于你的整个处理链路。很多开发者拿到一个训练好的 YOLOv8 模型后&#xff0c;会直接使用官方示例…

2026/7/23 22:58:43阅读更多 →
Coze与Dify对比指南:低代码AI应用开发从入门到实战

Coze与Dify对比指南:低代码AI应用开发从入门到实战

1. 从零到一&#xff1a;为什么你需要了解 Coze 和 Dify&#xff1f;如果你对 AI 应用开发感兴趣&#xff0c;但一看到“大模型”、“智能体”、“工作流”这些词就头疼&#xff0c;觉得门槛太高&#xff0c;那这篇文章就是为你准备的。很多开发者&#xff0c;包括我自己&#…

2026/7/23 18:58:18阅读更多 →
AI生图工具怎么选?2026年6月版实测对比

AI生图工具怎么选?2026年6月版实测对比

做自媒体的朋友应该都有体会&#xff1a;配图一直是个让人头疼的问题。2026年&#xff0c;AI生图工具已经非常成熟了&#xff0c;但工具太多反而不知道怎么选。以下是截至2026年6月我对主流AI生图工具的实测对比。Midjourney V8.1&#xff1a;速度之王2026年6月11日&#xff0c…

2026/7/23 18:58:18阅读更多 →