springboot結(jié)合vue2實現(xiàn)微信掃碼登錄的完整指南
要實現(xiàn) Spring Boot + Vue2 的微信掃碼登錄功能,需遵循微信開放平臺的 OAuth2.0 授權(quán)流程。以下是詳細步驟:
一、準(zhǔn)備工作
1.注冊微信開放平臺賬號?:訪問 微信開放平臺,注冊并認(rèn)證企業(yè)賬號(個人賬號不支持網(wǎng)站應(yīng)用)。
2.創(chuàng)建網(wǎng)站應(yīng)用?
- 進入「管理中心」→「創(chuàng)建網(wǎng)站應(yīng)用」,填寫應(yīng)用名稱、域名等信息。
- 審核通過后,獲取 AppID? 和 AppSecret(后續(xù)接口調(diào)用需使用)。
3.配置授權(quán)回調(diào)域?:在應(yīng)用詳情頁設(shè)置「授權(quán)回調(diào)域」(如 example.com,無需加 http://或路徑),確保前端頁面與回調(diào)域名一致。
二、后端(Spring Boot)實現(xiàn)
1. 添加依賴
<!-- Spring Web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- HTTP 客戶端(用于調(diào)用微信 API) -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</dependency>
<!-- JSON 解析 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.76</version>
</dependency>
2. 配置文件(application.yml)
wechat:
login:
appid: your_appid # 微信開放平臺 AppID
secret: your_secret # 微信開放平臺 AppSecret
redirect-uri: http://localhost:8080/api/wechat/callback # 回調(diào)接口地址(需與開放平臺配置一致)
scope: snsapi_login # 授權(quán)作用域(固定為 snsapi_login)
3. 核心代碼實現(xiàn)
(1) 配置類讀取參數(shù)
@Component
@ConfigurationProperties(prefix = "wechat.login")
public class WeChatConfig {
private String appid;
private String secret;
private String redirectUri;
private String scope;
// getter/setter
}
(2) 生成微信登錄二維碼 URL
微信掃碼登錄需引導(dǎo)用戶跳轉(zhuǎn)至微信授權(quán)頁,生成帶參數(shù)的 URL:
@Service
public class WeChatAuthService {
@Autowired
private WeChatConfig weChatConfig;
/**
* 生成微信掃碼登錄的授權(quán) URL
*/
public String generateLoginUrl() {
String baseUrl = "https://open.weixin.qq.com/connect/qrconnect";
Map<String, String> params = new HashMap<>();
params.put("appid", weChatConfig.getAppid());
params.put("redirect_uri", URLEncoder.encode(weChatConfig.getRedirectUri(), StandardCharsets.UTF_8));
params.put("response_type", "code");
params.put("scope", weChatConfig.getScope());
params.put("state", "STATE"); // 可選:隨機字符串,防止 CSRF 攻擊
// 拼接 URL
String url = baseUrl + "?";
for (Map.Entry<String, String> entry : params.entrySet()) {
url += entry.getKey() + "=" + entry.getValue() + "&";
}
return url.substring(0, url.length() - 1) + "#wechat_redirect"; // 必須以 #wechat_redirect 結(jié)尾
}
}
(3) 回調(diào)接口處理授權(quán)碼(Code)
用戶掃碼確認(rèn)登錄后,微信會重定向到 redirect_uri并攜帶 code和 state,后端需通過 code換取 access_token和用戶信息:
@RestController
@RequestMapping("/api/wechat")
public class WeChatCallbackController {
@Autowired
private WeChatAuthService weChatAuthService;
@Autowired
private RestTemplate restTemplate; // 注入 RestTemplate 用于 HTTP 請求
/**
* 微信授權(quán)回調(diào)接口
*/
@GetMapping("/callback")
public ResponseEntity<?> handleCallback(
@RequestParam String code,
@RequestParam String state) {
try {
// 1. 用 code 換取 access_token
String tokenUrl = String.format(
"https://api.weixin.qq.com/sns/oauth2/access_token?appid=%s&secret=%s&code=%s&grant_type=authorization_code",
weChatConfig.getAppid(), weChatConfig.getSecret(), code
);
String tokenResult = restTemplate.getForObject(tokenUrl, String.class);
JSONObject tokenJson = JSON.parseObject(tokenResult);
if (tokenJson.containsKey("errcode")) {
return ResponseEntity.badRequest().body("獲取 access_token 失?。? + tokenJson.getString("errmsg"));
}
String accessToken = tokenJson.getString("access_token");
String openId = tokenJson.getString("openid");
// 2. 用 access_token 和 openid 獲取用戶信息
String userInfoUrl = String.format(
"https://api.weixin.qq.com/sns/userinfo?access_token=%s&openid=%s",
accessToken, openId
);
String userInfoResult = restTemplate.getForObject(userInfoUrl, String.class);
JSONObject userInfoJson = JSON.parseObject(userInfoResult);
if (userInfoJson.containsKey("errcode")) {
return ResponseEntity.badRequest().body("獲取用戶信息失?。? + userInfoJson.getString("errmsg"));
}
// 3. 處理用戶信息(如創(chuàng)建/更新本地用戶,生成 JWT Token 等)
String nickname = userInfoJson.getString("nickname");
String headImgUrl = userInfoJson.getString("headimgurl");
// ... 其他字段(sex、province、city 等)
// 示例:返回用戶信息給前端(實際需根據(jù)業(yè)務(wù)生成 Token)
Map<String, Object> result = new HashMap<>();
result.put("openid", openId);
result.put("nickname", nickname);
result.put("headimgurl", headImgUrl);
return ResponseEntity.ok(result);
} catch (Exception e) {
return ResponseEntity.internalServerError().body("登錄失?。? + e.getMessage());
}
}
}
(4) 提供生成登錄 URL 的接口(供前端調(diào)用)
@RestController
@RequestMapping("/api/auth")
public class AuthController {
@Autowired
private WeChatAuthService weChatAuthService;
@GetMapping("/wechat/login-url")
public ResponseEntity<String> getWeChatLoginUrl() {
String loginUrl = weChatAuthService.generateLoginUrl();
return ResponseEntity.ok(loginUrl);
}
}
三、前端(Vue2)實現(xiàn)
1. 安裝依賴(可選)
如需展示二維碼,可使用 qrcode庫將微信登錄 URL 轉(zhuǎn)換為二維碼圖片:
npm install qrcode --save
2. 核心代碼實現(xiàn)
(1) 獲取微信登錄 URL 并生成二維碼
<template>
<div class="wechat-login">
<h3>微信掃碼登錄</h3>
<!-- 二維碼展示區(qū)域 -->
<canvas id="wechat-qrcode"></canvas>
<p v-if="errorMsg" class="error">{{ errorMsg }}</p>
</div>
</template>
<script>
import QRCode from 'qrcode';
import axios from 'axios';
export default {
data() {
return {
wechatLoginUrl: '',
errorMsg: ''
};
},
mounted() {
this.getWeChatLoginUrl();
},
methods: {
// 從后端獲取微信登錄 URL
async getWeChatLoginUrl() {
try {
const res = await axios.get('http://localhost:8080/api/auth/wechat/login-url');
this.wechatLoginUrl = res.data;
this.generateQRCode(this.wechatLoginUrl);
} catch (err) {
this.errorMsg = '獲取登錄鏈接失敗,請重試';
console.error(err);
}
},
// 生成二維碼
generateQRCode(url) {
const canvas = document.getElementById('wechat-qrcode');
QRCode.toCanvas(canvas, url, { width: 200 }, (error) => {
if (error) {
this.errorMsg = '生成二維碼失敗';
console.error(error);
}
});
}
}
};
</script>
<style scoped>
.wechat-login { text-align: center; margin-top: 50px; }
.error { color: red; margin-top: 10px; }
#wechat-qrcode { margin: 20px auto; }
</style>
(2) 處理登錄成功后的回調(diào)
微信授權(quán)成功后,后端會重定向到 redirect_uri(即后端的 /api/wechat/callback),并將用戶信息返回給前端。若前端需要直接接收用戶信息(而非后端重定向),可調(diào)整流程:
- 后端回調(diào)接口驗證
code后,將用戶信息存儲到 Session 或 Redis,然后重定向到前端頁面(如http://localhost:8081/login-success?token=xxx)。 - 前端監(jiān)聽路由變化,在
login-success頁面獲取 Token 并完成本地登錄狀態(tài)保存。
四、關(guān)鍵注意事項
HTTPS 要求:生產(chǎn)環(huán)境必須使用 HTTPS,否則微信授權(quán)可能失敗(開發(fā)環(huán)境可暫時使用 HTTP,但需確保回調(diào)域名與開放平臺配置一致)。
跨域問題:若前后端分離部署,需在后端配置 CORS 允許前端域名訪問:
@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/api/**")
.allowedOrigins("http://localhost:8081") // 前端域名
.allowedMethods("GET", "POST")
.allowCredentials(true);
}
}
安全性:
state參數(shù)需隨機生成并校驗,防止 CSRF 攻擊。access_token和openid需妥善保管,避免泄露。
錯誤處理:需處理微信 API 返回的錯誤碼(如 40029表示 code無效,40163表示 code已被使用)。
五、完整流程總結(jié)
- 前端請求后端獲取微信登錄 URL。
- 后端生成帶參數(shù)的微信授權(quán) URL 并返回給前端。
- 前端將 URL 轉(zhuǎn)換為二維碼展示給用戶。
- 用戶掃碼并在微信客戶端確認(rèn)登錄。
- 微信重定向到后端回調(diào)接口,攜帶
code。 - 后端通過
code換取access_token和用戶信息。 - 后端處理用戶信息(如生成 Token),并返回結(jié)果給前端。
- 前端根據(jù)返回結(jié)果完成本地登錄狀態(tài)保存(如存儲 Token 到 localStorage)。
通過以上步驟,即可實現(xiàn)基于 Spring Boot + Vue2 的微信掃碼登錄功能。
到此這篇關(guān)于springboot結(jié)合vue2實現(xiàn)微信掃碼登錄的完整指南的文章就介紹到這了,更多相關(guān)springboot微信掃碼登錄內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SpringCloud?Nacos服務(wù)分級存儲模型詳解
Nacos服務(wù)分級存儲模型是Nacos存儲服務(wù)注冊信息和配置信息的核心模型之一,本文將對?Nacos?服務(wù)分級存儲模型進行深入解析,感興趣的朋友一起看看吧2024-02-02
詳解SpringBoot 使用Spring Initializr 快速構(gòu)建工程(官方推薦)
本篇文章主要介紹了SpringBoot 使用Spring Initializr 快速構(gòu)建工程(官方推薦),非常具有實用價值,需要的朋友可以參考下2017-10-10
IDEA項目啟動時Flyway數(shù)據(jù)庫遷移中的checksum不匹配問題及最新解決方案
面對IDEA項目啟動時報出的Flyway遷移校驗和不匹配問題,核心在于保持遷移腳本的一致性、正確管理和理解Flyway的工作機制,本文介紹IDEA項目啟動時Flyway數(shù)據(jù)庫遷移中的checksum不匹配問題及最新解決方案,感興趣的朋友一起看看吧2024-01-01
Java面試Logback打印日志如何獲取當(dāng)前方法名稱題解
這篇文章主要為大家介紹了Java面試Logback打印日志如何獲取當(dāng)前方法名稱題解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-11-11
SpringBoot整合Hibernate Validator實現(xiàn)參數(shù)驗證功能
這篇文章主要介紹了SpringBoot整合Hibernate Validator實現(xiàn)參數(shù)驗證功能,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-06-06

