授权登录流程:
在UniApp中开发微信小程序的授权登录流程,主要涉及以下几个步骤:
1. 引入微信登录API
首先,确保在项目中引入了微信小程序的登录API。UniApp已经封装了相关API,可以直接使用。
2. 获取用户授权
用户需要授权小程序获取其基本信息。可以通过uni.getUserProfile
或uni.getUserInfo
来获取用户信息。
uni.getUserProfile({ desc: '获取用户信息用于登录', success: (res) => { console.log('用户信息:', res.userInfo); // 这里可以获取到用户的昵称、头像等信息 }, fail: (err) => { console.error('获取用户信息失败:', err); } });
3. 获取登录凭证(code)
使用uni.login
获取登录凭证code
,这个code
用于后续向微信服务器换取openid
和session_key
。
uni.login({ provider: 'weixin', success: (res) => { if (res.code) { console.log('登录凭证:', res.code); // 将code发送到服务器,换取openid和session_key } else { console.error('登录失败:', res.errMsg); } }, fail: (err) => { console.error('登录失败:', err); } });
4. 发送code到服务器
将获取到的code
发送到你的服务器,服务器通过微信接口换取openid
和session_key
。
uni.request({ url: 'https://your-server.com/api/login', method: 'POST', data: { code: res.code }, success: (response) => { console.log('服务器返回:', response.data); // 服务器返回的openid和session_key }, fail: (err) => { console.error('请求失败:', err); } });
5. 服务器端处理
服务器接收到code
后,调用微信的auth.code2Session
接口,换取openid
和session_key
。
GET https://api.weixin.qq.com/sns/jscode2session?appid=APPID&secret=SECRET&js_code=JSCODE&grant_type=authorization_code
-
APPID
: 小程序ID -
SECRET
: 小程序密钥 -
JSCODE
: 客户端传来的code
6. 返回用户信息
服务器在获取到openid
和session_key
后,可以根据业务逻辑生成自定义的登录态(如token),并返回给客户端。
7. 客户端存储登录态
客户端接收到服务器返回的登录态后,可以将其存储在本地(如uni.setStorageSync
),用于后续的接口请求。
uni.setStorageSync('token', response.data.token);
8. 检查登录状态
在每次启动小程序时,检查本地存储的登录态是否有效。如果失效,重新走登录流程。
const token = uni.getStorageSync('token'); if (!token) { // 重新登录 }
9. 用户信息更新
如果用户信息发生变化,可以通过uni.getUserInfo
或uni.getUserProfile
重新获取用户信息并更新到服务器。
10. 退出登录
用户退出登录时,清除本地存储的登录态。
uni.removeStorageSync('token');
注意事项
-
用户隐私:获取用户信息时,必须明确告知用户用途,并获取用户授权。
-
安全性:
session_key
是敏感信息,不应传输到客户端,应在服务器端妥善保管。 -
接口调用频率:微信接口有调用频率限制,需合理设计登录流程,避免频繁调用。
通过以上步骤,你可以在UniApp中实现微信小程序的授权登录功能。
示例代码:
- <view class="container">
- <button @click="handleLogin">微信登录button>
- <button @click="handleLogout">退出登录button>
- <view v-if="userInfo">
- <image :src="userInfo.avatarUrl" mode="aspectFill">image>
- <text>{
-
- { userInfo.nickName }}text>
- view>
- view>
-
- <script>
- export default {
- data() {
- return {
- userInfo: null, // 用户信息
- token: null, // 登录态
- };
- },
- onLoad() {
- this.checkLoginStatus();
- },
- methods: {
- // 检查登录状态
- checkLoginStatus() {
- const token = uni.getStorageSync('token');
- if (token) {
- this.token = token;
- this.getUserInfo();
- } else {
- console.log('未登录');
- }
- },
-
- // 处理登录
- async handleLogin() {
- try {
- // 1. 获取用户信息
- const userInfo = await this.getUserProfile();
- this.userInfo = userInfo;
-
- // 2. 获取登录凭证 code
- const code = await this.getLoginCode();
-
- // 3. 发送 code 到服务器,换取 token
- const token = await this.sendCodeToServer(code);
-
- // 4. 存储 token
- uni.setStorageSync('token', token);
- this.token = token;
-
- console.log('登录成功');
- } catch (error) {
- console.error('登录失败:', error);
- }
- },
-
- // 获取用户信息
- getUserProfile() {
- return new Promise((resolve, reject) => {
- uni.getUserProfile({
- desc: '获取用户信息用于登录',
- success: (res) => {
- resolve(res.userInfo);
- },
- fail: (err) => {
- reject(err);
- },
- });
- });
- },
-
- // 获取登录凭证 code
- getLoginCode() {
- return new Promise((resolve, reject) => {
- uni.login({
- provider: 'weixin',
- success: (res) => {
- if (res.code) {
- resolve(res.code);
- } else {
- reject(new Error('获取 code 失败'));
- }
- },
- fail: (err) => {
- reject(err);
- },
- });
- });
- },
-
- // 发送 code 到服务器
- async sendCodeToServer(code) {
- try {
- const response = await uni.request({
- url: 'https://your-server.com/api/login', // 替换为你的服务器地址
- method: 'POST',
- data: {
- code: code,
- },
- });
-
- if (response.statusCode === 200 && response.data.token) {
- return response.data.token; // 假设服务器返回 token
- } else {
- throw new Error('服务器返回错误');
- }
- } catch (error) {
- throw new Error('请求服务器失败');
- }
- },
-
- // 获取用户信息(已登录时)
- getUserInfo() {
- // 这里可以根据 token 从服务器获取用户信息
- console.log('获取用户信息');
- },
-
- // 退出登录
- handleLogout() {
- uni.removeStorageSync('token');
- this.token = null;
- this.userInfo = null;
- console.log('退出登录成功');
- },
- },
- };
- script>
-
- <style>
- .container {
- display: flex;
- flex-direction: column;
- align-items: center;
- justify-content: center;
- height: 100vh;
- }
- style>
评论记录:
回复评论: