2025-08-01
Uniapp
0

目录

微信小程序登录与用户信息获取全流程实现指南
前言
一、微信小程序一键登录
1.1 实现原理
1.2 前端实现
1.3 后端处理
二、微信小程序账号密码登录
2.1 前端表单设计
2.2 后端验证逻辑
三、获取用户手机号
3.1 前端授权按钮
3.2 获取手机号回调
3.3 后端解密手机号
四、退出登录
4.1 前端调用
4.2 后端处理
五、获取用户当前位置
5.1 前端获取位置
5.2 后端解析地址
六、安全与隐私考虑
七、总结

微信小程序登录与用户信息获取全流程实现指南

前言

在微信小程序开发中,用户登录和信息获取是基础且重要的功能。本文将详细介绍如何实现微信小程序的一键登录、账号密码登录、获取用户手机号、退出登录以及获取用户当前位置等功能。我们将基于一个实际的医疗试验项目代码,解析这些功能的实现原理和关键代码。

一、微信小程序一键登录

1.1 实现原理

微信小程序一键登录主要依赖于微信提供的uni.login()接口获取临时登录凭证code,然后通过后端服务与微信服务器交互获取用户的openid。

1.2 前端实现

javascript
// login.vue中的关键代码 const doLogin = () => { uni.showLoading({ title: '登录中,请稍后' }) uni.login({ success: response => { loginForm.value.code = response.code login(loginForm.value).then(res => { // 获取并缓存token token.value = res.data.tokenValue uni.setStorageSync('token', res.data.tokenValue) // ...后续处理 }) } }) }

1.3 后端处理

后端通过WxHttpUtil.getOpenId()方法获取用户openid:

java
public static String getOpenId(String code) { Map<String, Object> form = new HashMap<>(); form.put("appid", staticAppId); form.put("secret", staticAppSecret); form.put("js_code", code); form.put("grant_type", "authorization_code"); HttpResponse response = HttpUtil.createGet(staticOpenIdUrl) .form(form) .execute(); JSONObject jsonObject = JSON.parseObject(response.body()); return jsonObject.getString("openid"); }

二、微信小程序账号密码登录

2.1 前端表单设计

html
<up-form ref="loginFormRef" :model="loginForm" :rules="rules" labelPosition="left" labelWidth="auto" > <up-form-item label="用户名" prop="username" :borderBottom="true" > <up-input v-model="loginForm.username" name="nickname" autocomplete="new-password" border="none" inputmode="text" type="text" placeholder="请输入用户名" clearable /> </up-form-item> <up-form-item label="密码" prop="password" :borderBottom="true" > <up-input v-model="loginForm.password" name="pwd" autocomplete="new-password" border="none" inputmode="text" type="text" placeholder="请输入密码" clearable /> </up-form-item> </up-form>

2.2 后端验证逻辑

后端在AuthWxController.login()方法中处理账号密码登录:

java
if (StrUtil.isNotBlank(eLogin.getUsername()) && StrUtil.isNotBlank(eLogin.getPassword())) { wrapper.eq(MemberInfo::getNickname, eLogin.getUsername()); wrapper.eq(MemberInfo::getPassword, eLogin.getPassword()); memberInfo = memberService.getOne(wrapper.last("limit 1")); if (Objects.isNull(memberInfo)) { // 登录失败处理逻辑 // ... return R.warning("用户名或密码有误,您还有" + (5 - valueSet.size()) + "次机会!"); } // 登录成功处理 RedisUtil.delete(WX_LOGIN_FAIL_LOG + eLogin.getUsername()); openId = memberInfo.getOpenId(); }

三、获取用户手机号

3.1 前端授权按钮

html
<up-button v-if="aggreeAuthPhone" type="success" shape="circle" size="large" text="一键登录" open-type="getPhoneNumber" @getphonenumber="getPhoneNumber" />

3.2 获取手机号回调

javascript
const getPhoneNumber = (e) => { if (e.detail.errMsg === 'getPhoneNumber:ok') { loginForm.value.phoneCode = e.detail.code toLogin() } else { uni.$u.toast('您已取消授权') } }

3.3 后端解密手机号

后端通过WxHttpUtil.getPhone()方法解密手机号:

java
public static String getPhone(String openId, String code) { // 获取access_token String accessToken = RedisUtil.get("wx-auth:accessToken", String.class); if (StrUtil.isBlank(accessToken)) { // 如果缓存中没有access_token,则重新获取 // ... } // 使用access_token获取手机号 JSONObject body = new JSONObject(); body.put("code", code); body.put("openid", openId); HttpResponse response = HttpUtil.createPost(staticPhoneNumberUrl + "?access_token=" + accessToken) .body(body.toJSONString()) .execute(); JSONObject jsonObject = JSON.parseObject(response.body()); jsonObject = jsonObject.getJSONObject("phone_info"); return jsonObject.getString("purePhoneNumber"); }

四、退出登录

4.1 前端调用

javascript
export const logout = (openId) => { return http('/wx/auth/logout', {openId}) }

4.2 后端处理

java
@Operation(summary = "用户退出") @GetMapping("/logout") public R<Boolean> logout(@Parameter(description = "记录编号") @NotNull(message = "记录编号不能为空") @RequestParam String openId) { UserUtil.removeWxLoginUser(openId); StpUtil.logout(openId, "APP"); return R.ok(); }

五、获取用户当前位置

5.1 前端获取位置

javascript
const getNearbyProjects = () => { uni.getLocation({ type: 'wgs84', success: function(pointResult) { const addressBo = { longitude: pointResult.longitude, latitude: pointResult.latitude, currentCode: currentCode.value } getCurrentAddress(addressBo).then(res => { searchData.address = res.data init() }) }, fail: (err) => { console.log('获取位置失败:' + JSON.stringify(err)) uni.$u.toast('获取位置失败') init() } }) }

注意

小程序平台需要申请wx.getFuzzyLocation接口访问权限,本地测试时HBuilder X需要勾选manifest.json——>微信小程序配置——>微信小程序权限配置——>位置接口(描述:需要获取用户的位置信息)

5.2 后端解析地址

通过高德地图API逆向解析地址:

yml
# application-dev.yml配置 wx-mini: geo-address_url: https://restapi.amap.com/v3/geocode/regeo?output=JSON geo-key: xxxxxxxxxxxxxx # 高德地图API key

六、安全与隐私考虑

  1. 隐私协议:在获取用户敏感信息前,必须让用户同意隐私协议
javascript
const handleOpenPrivacyContract = () => { wx.openPrivacyContract() }
  1. 登录失败限制:连续登录失败5次后,账号将被锁定10分钟
java
if (valueSet.size() >= 5) { RedisUtil.set(ACCESS_LOCK + request.getSession().getId(), System.currentTimeMillis(), 600L); return R.warning("您已经达到了最大登录失败次数,账号冻结10分钟!"); }
  1. 手机号唯一性检查:确保一个手机号只能绑定一个账号
java
if (Objects.nonNull(entity) && !StrUtil.equals(entity.getOpenId(), memberInfo.getOpenId())) { return R.warning("授权的手机号已存在账户,请重新用改手机号登录!"); }

七、总结

本文详细介绍了微信小程序中常见的用户登录和信息获取功能的实现方法,包括:

  1. 一键登录:通过微信临时code获取用户唯一标识openid
  2. 账号密码登录:传统登录方式,增加了安全限制
  3. 手机号获取:通过微信提供的接口解密用户手机号
  4. 退出登录:清理用户会话和缓存信息
  5. 位置获取:结合高德地图API将坐标转换为中文地址

这些功能在实现时不仅要考虑功能完整性,还需要特别注意用户隐私保护和安全性问题。通过合理的架构设计和代码实现,可以为用户提供既安全又便捷的登录体验。

希望本文能为你的微信小程序开发提供有价值的参考!