Springboot+vue微信扫码登录
# SpringBoot + Vue 实现微信扫码登录 微信扫码登录是一种常见的第三方登录方式,下面我将详细介绍如何实现SpringBoot后端和Vue前端的微信扫码登录功能。 ## 一、准备工作 1. 注册微信开放平台账号(https://open.weixin.qq.com) 2. 创建网站应用,获取AppID和AppSecret 3. 设置授权回调域(需要备案的域名) ## 二、后端实现(SpringBoot) 1. 添加依赖 ```xml <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>4.5.13</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.83</version> </dependency> ``` 2. 创建微信登录工具类 ```java import org.apache.http.HttpEntity; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; import org.apache.http.util.EntityUtils; import java.io.IOException; public class WeChatAuthUtil { private static final String APP_ID = "你的AppID"; private static final String APP_SECRET = "你的AppSecret"; // 获取微信登录二维码URL public static String getQrCodeUrl(String redirectUri, String state) { return "https://open.weixin.qq.com/connect/qrconnect?appid=" + APP_ID + "&redirect_uri=" + redirectUri + "&response_type=code&scope=snsapi_login&state=" + state + "#wechat_redirect"; } // 通过code获取access_token public static String getAccessToken(String code) throws IOException { String url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=" + APP_ID + "&secret=" + APP_SECRET + "&code=" + code + "&grant_type=authorization_code"; return doGet(url); } // 获取用户信息 public static String getUserInfo(String accessToken, String openid) throws IOException { String url = "https://api.weixin.qq.com/sns/userinfo?access_token=" + accessToken + "&openid=" + openid; return doGet(url); } // 发送GET请求 private static String doGet(String url) throws IOException { CloseableHttpClient httpClient = HttpClients.createDefault(); HttpGet httpGet = new HttpGet(url); CloseableHttpResponse response = httpClient.execute(httpGet); HttpEntity entity = response.getEntity(); String result = EntityUtils.toString(entity); response.close(); httpClient.close(); return result; } } ``` 3. 创建控制器 ```java import com.alibaba.fastjson.JSONObject; import org.springframework.web.bind.annotation.*; import javax.servlet.http.HttpServletRequest; import java.io.IOException; @RestController @RequestMapping("/api/auth") public class AuthController { @GetMapping("/wechat/qrCode") public String getWeChatQrCode(@RequestParam String redirectUri, @RequestParam String state) { return WeChatAuthUtil.getQrCodeUrl(redirectUri, state); } @GetMapping("/wechat/callback") public JSONObject wechatCallback(@RequestParam String code) throws IOException { // 1. 获取access_token String accessTokenResult = WeChatAuthUtil.getAccessToken(code); JSONObject accessTokenObj = JSONObject.parseObject(accessTokenResult); // 2. 获取用户信息 String userInfo = WeChatAuthUtil.getUserInfo( accessTokenObj.getString("access_token"), accessTokenObj.getString("openid") ); // 3. 处理用户信息(如保存到数据库等) JSONObject userInfoObj = JSONObject.parseObject(userInfo); // 4. 返回用户信息给前端 return userInfoObj; } } ``` ## 三、前端实现(Vue) 1. 安装依赖 ```bash npm install qrcode.vue --save ``` 2. 创建微信登录组件 ```vue <template> <div> <qrcode-vue v-if="qrCodeUrl" :value="qrCodeUrl" :size="200" level="H" /> <div v-else>加载中...</div> </div> </template> <script> import QrcodeVue from 'qrcode.vue' import axios from 'axios' export default { components: { QrcodeVue }, data() { return { qrCodeUrl: '', timer: null } }, mounted() { this.initWeChatLogin() }, beforeDestroy() { clearInterval(this.timer) }, methods: { async initWeChatLogin() { // 生成随机state防止CSRF攻击 const state = Math.random().toString(36).substring(2) // 获取微信登录二维码URL const res = await axios.get('/api/auth/wechat/qrCode', { params: { redirectUri: encodeURIComponent(window.location.origin + '/wechatCallback'), state } }) this.qrCodeUrl = res.data // 轮询检查登录状态 this.timer = setInterval(() => { this.checkLoginStatus(state) }, 2000) }, async checkLoginStatus(state) { try { const res = await axios.get('/api/auth/wechat/callback', { params: { state } }) if (res.data && res.data.openid) { clearInterval(this.timer) // 登录成功,处理用户信息 this.$emit('login-success', res.data) } } catch (error) { console.error('检查登录状态出错:', error) } } } } </script> ``` 3. 使用组件 ```vue <template> <div> <h1>微信扫码登录</h1> <wechat-login @login-success="handleLoginSuccess" /> </div> </template> <script> import WechatLogin from '@/components/WechatLogin.vue' export default { components: { WechatLogin }, methods: { handleLoginSuccess(userInfo) { // 存储用户信息 localStorage.setItem('userInfo', JSON.stringify(userInfo)) // 跳转到首页或其他页面 this.$router.push('/home') } } } </script> ``` ## 四、注意事项 1. 微信开放平台要求回调域名必须备案且与申请时填写的一致 2. 生产环境需要使用HTTPS协议 3. state参数用于防止CSRF攻击,应该随机生成并验证 4. 用户扫码后,微信会重定向到回调地址并带上code和state参数 5. 前端轮询检查登录状态的方式可以改为WebSocket实现更高效 ## 五、额外逻辑点 1. 微信返回的access_token有效期较短(7200秒),如需长期存储用户信息应考虑使用自己的token机制 2. 用户信息中的unionid是同一用户在多个微信应用中的唯一标识,建议存储 3. 微信扫码登录涉及敏感信息传输,务必使用HTTPS确保通信安全 [2025-06-03 11:51:27 | AI写代码神器 | 1660点数解答]
- [讯飞星火] cannot read properties of null (reading 'userid') typeerror: cannot read properties of null (reading 'userid') at eval (webpack-internal:///./node_modules/babel-loader/lib/index.js??clonedruleset-40.use[0]!./node_modules/vue-loader/dist/index.js??ruleset[0].use[0]!./src/views/businesslistview.vue?vue&type=script&setup=true&lang=js:28:88) at eval (webpack-internal:///./node_modules/@vue/runtime-core/dist/runtime-core.esm-bundler.js:2677:40) at callwitherrorhandling (webpack-internal:/(614点数解答 | 2024-11-28 14:31:57)245
- [讯飞星火] cannot read properties of null (reading 'userid') typeerror: cannot read properties of null (reading 'userid') at eval (webpack-internal:///./node_modules/babel-loader/lib/index.js??clonedruleset-40.use[0]!./node_modules/vue-loader/dist/index.js??ruleset[0].use[0]!./src/views/businesslistview.vue?vue&type=script&setup=true&lang=js:28:88)(523点数解答 | 2024-11-28 14:32:05)230
- [讯飞星火] cannot read properties of null (reading 'userid') typeerror: cannot read properties of null (reading 'userid') at eval (webpack-internal:///./node_modules/babel-loader/lib/index.js??clonedruleset-40.use[0]!./node_modules/vue-loader/dist/index.js??ruleset[0].use[0]!./src/views/businesslistview.vue?vue&type=script&setup=true&lang=js:28:88) 要怎么修改代码(516点数解答 | 2024-11-28 14:32:43)257
- [字节豆包] 后端技术栈:springboot + mybatis + springmvc 前端技术栈:vue + axios + router 数据库:mysql 1 可行性分析 1.1 市场分析 1.2 政策分析 1.3 竞争实力分析 1.4 技术可行分析 1.5 时间和资源可行性分析 1.6 知识产权分析 2 项目计划 2.1 项目介绍 2.1.1 项目范围 (1)用简练的语言说明本项目“是什么”,“说明用途”。 (2)说明本项目“应当包含的内容”和“不包含的内容”。 (3)说明本项目“适用的领域”和“不适用的领域”。 2.1.2 项目目标 说明本项目的目标,这些目标必须是“可实现”、“可验证”的 2.1.3 客户与最终用户介绍 如果是合同项目,请说明本项目的客户及其责任人是谁,描述最终用户的特征。如果不是合同项目,请描述潜在客户和最终用户的特征。 2.1.4 开发方介绍 如果是合同项目,请说明本项目的开发方是谁,责任人是谁。 2.1.5 制约 (1)请说明在项目开发过程中应当遵循的标准或规范,注意可能存在特殊的行业规定,请不要遗漏。(2)请说明相关项目可能对本项(1703点数解答 | 2024-12-25 01:52:35)225
- [字节豆包] springboot + mysql + vue 📊 功能: 管理员多权限管理 用户登录与密码修改 管理员注册与权限管理 学生信息管理(增删改查) 学生成绩管理(增删改查)(131点数解答 | 2024-12-29 00:14:07)197
- [字节豆包] 问ai springboot + mysql + vue 📊 功能: 管理员多权限管理 用户登录与密码修改 管理员注册与权限管理 学生信息管理(增删改查) 学生成绩管理(增删改查)具体代码(948点数解答 | 2024-12-29 00:15:10)195
- [阿里通义] 作为javascript开发,vue 3.0 所采用的 composition api 与 vue 2.x使用的options api 有什么区别?(342点数解答 | 2023-11-09 01:34:53)307
- [阿里通义] 作为javascript开发,vue.extend 和 vue.component 的区别是什么?(339点数解答 | 2023-11-09 01:36:22)288
- [GPT] <script setup> import { ref, onmounted } from 'vue' import { useroute } from 'vue-router' import { selectbyid } from '@/api/job' import { selectqiye } from '@/api/qiye' import { selectjianli } from '@/api/jianli' import { applyforjob, checkshenqing } from '@/api/shenqing' import { elmessage } from 'element-plus' import { addshoucang, cancelshoucang, checkshoucang } from '@/api/shoucang' const token = localstorage.getitem('token') const route = useroute() const userrole = localstorage.getitem('us(136点数解答 | 2024-12-29 17:09:05)214
- [讯飞星火] 用java创建窗体jframe综合使用空间容器进行界面的布局,并编程实现在多个不同的界面之间相互跳转。 (1)单击“登录”按钮,能够根据输入的账号密码进行登录;如果登录失败,能够提示;如果登录成功,提示登录成功之后,能到达操作界面。 (2)单击“注册”按钮,登录界面消失,出现注册界面。 (3)单击“退出”按钮,程序退出。 或者,在上面图二中: (1)当单击“添加个人信息”菜单后进入“个人信息添加”界面,添加完成后跳转到个人信息显示界面,如果不想添加可返回到图二。 (2)当单击“修改个人信息”菜单进入到“个人信息修改”界面,修改成功后跳转到个人信息显示界面,如果不想修改可返回到图二。 (3)当单击“查看个人信息”菜单进入到“个人信息显示”界面,查看完毕可返回到图二。 (4)当单击“删除个人信息”菜单进入到“个人信息删除”界面,删除成功后跳转到个人信息显示界面,如果不想修改可返回到图二。(503点数解答 | 2024-06-06 23:49:29)371
- [GPT] 密码锁(20分): 界面要求:数字键盘 登录 退出 删除 账号框 密码框 功能要求:1、点击键盘,在账号框,密码框实时显示数字,将输入的密码、账号跟文本1.txt的账号密码比对。(10分) 2、账号密码正确,进度条进入功能界面。(5分) 3、账号密码错误,限定输入次数,超过三次,锁定界面。(5分)(2535点数解答 | 2024-12-05 20:48:02)152
- [字节豆包] 使用vue3写一个登录页面,页面颜色为浅蓝色,在页面正中创建一个盒子,盒子颜色为白色,盒子宽200px,高180px,盒子上下内边距为30px,左右内边距为20px,盒子中包含用户名按钮、密码按钮、登录按钮,其中登录按钮为蓝色,各按钮竖着排列,用户名按钮的上外边距为40px、下外边距为25px,内边距为10px,密码按钮外边距为25px,内边距为10px,登录按钮上外边距为30px,下外边距为15px,在盒子下方写一个“登录/注册”(333点数解答 | 2025-03-07 08:31:30)191