在微信小程序开发中,用户登录和信息获取是基础且重要的功能。本文将详细介绍如何实现微信小程序的一键登录、账号密码登录、获取用户手机号、退出登录以及获取用户当前位置等功能。我们将基于一个实际的医疗试验项目代码,解析这些功能的实现原理和关键代码。
微信小程序一键登录主要依赖于微信提供的uni.login()
接口获取临时登录凭证code,然后通过后端服务与微信服务器交互获取用户的openid。
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)
// ...后续处理
})
}
})
}
后端通过WxHttpUtil.getOpenId()
方法获取用户openid:
javapublic 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");
}
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>
后端在AuthWxController.login()
方法中处理账号密码登录:
javaif (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();
}
html<up-button v-if="aggreeAuthPhone" type="success" shape="circle" size="large" text="一键登录" open-type="getPhoneNumber" @getphonenumber="getPhoneNumber" />
javascriptconst getPhoneNumber = (e) => {
if (e.detail.errMsg === 'getPhoneNumber:ok') {
loginForm.value.phoneCode = e.detail.code
toLogin()
} else {
uni.$u.toast('您已取消授权')
}
}
后端通过WxHttpUtil.getPhone()
方法解密手机号:
javapublic 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");
}
javascriptexport const logout = (openId) => {
return http('/wx/auth/logout', {openId})
}
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();
}
javascriptconst 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——>微信小程序配置——>微信小程序权限配置——>位置接口(描述:需要获取用户的位置信息)
通过高德地图API逆向解析地址:
yml# application-dev.yml配置
wx-mini:
geo-address_url: https://restapi.amap.com/v3/geocode/regeo?output=JSON
geo-key: xxxxxxxxxxxxxx # 高德地图API key
javascriptconst handleOpenPrivacyContract = () => {
wx.openPrivacyContract()
}
javaif (valueSet.size() >= 5) {
RedisUtil.set(ACCESS_LOCK + request.getSession().getId(), System.currentTimeMillis(), 600L);
return R.warning("您已经达到了最大登录失败次数,账号冻结10分钟!");
}
javaif (Objects.nonNull(entity) && !StrUtil.equals(entity.getOpenId(), memberInfo.getOpenId())) {
return R.warning("授权的手机号已存在账户,请重新用改手机号登录!");
}
本文详细介绍了微信小程序中常见的用户登录和信息获取功能的实现方法,包括:
这些功能在实现时不仅要考虑功能完整性,还需要特别注意用户隐私保护和安全性问题。通过合理的架构设计和代码实现,可以为用户提供既安全又便捷的登录体验。
希望本文能为你的微信小程序开发提供有价值的参考!