微信小程序开发之登录逻辑的处理

微信小程序开发之登录逻辑的处理

2019-03-29 | |

说到 App 的登录,想必大家都不会陌生。当我们打开一个 App 的时候,如果之前已经登录了,那么就直接进入到首页。如果还没有登录,则需要跳转到登录页面进行登录。这是一个很正常的业务流程,但是在实际的开发过程中,我们需要考虑的肯定不止这一点。比如:登录状态失效的逻辑、登录唯一性的逻辑、登录状态判断的时机等,这些都是需要我们开发人员来考虑的。那么我们该如何处理登录这一块的逻辑呢?这里总结下有关微信小程序登录的逻辑。

注:这里我们只讨论小程序客户端登录的问题,后台的处理逻辑不在本文的讨论范围。
博文中引用的 Demo 已经放到 github 上面了,有需要的小伙伴可以去下载

登录流程

微信官方的登录流程



从微信官方提供的登录流程图中,我们不难看出,对于小程序客户端的登录来说,需要的操作并不复杂。

主要是以下三步:

  1. 调用 wx.login() 方法来获取 code。
  2. 将 code 作为参数传递给自己公司的后台,并获取后台返回的登录状态。
  3. 缓存并维护登录状态。

小程序登录业务逻辑


微信官方提供给我们的主要是如何获取这个登录状态,也就是我们具体登录时需要做的事。但是实际开发中,我们除了获取这个登录状态之外,还需要维护这个登录的状态,也就是针对登录状态的存、取、删除的操作。

下面我们从四个时间点来说明这个问题:

启动小程序

当启动小程序的时候,就需要判断当前小程序是否已经登录,然后根据这个登录状态来做页面的跳转。也就是说我们需要将缓存在本地的登录状态读取出来,然后判断其是否为空,如果为空,则表示没有登录,就需要显示登录页面。反之就表示已经登录,直接跳转到首页。
通常情况下,我们会在小程序启动的时候执行这段代码,也就是需要将判断的逻辑写在 app.js 文件中的 onLaunch 方法中。但是在在真机调试的时候,发现了一个很奇怪的问题,启动小程序后进入登录页面,然后将小程序挂入后台并从另外一个入口打开小程序(发现 -> 小程序 -> 最近使用),小程序直接跳转到了首页,而不是刚刚的登录页面。这里我们在 app.json 中配置的第一个页面的路径是首页的路径,然后在 app.js 文件中的 onLaunch 方法中加入了登录状态的逻辑判断。正常情况下,如果是启动小程序,那么肯定会调用 app.js 文件中的 onLaunch 方法。当小程序是从后台返回前台,那么就应该显示挂入后台之前的页面(登录页面)。我不太清楚这是否是微信的一个 Bug,但这毕竟是一个问题,出现了 Bug,就需要解决。这里有一种解决方案,添加一 个空白页面,可以理解为启动页面(launch),然后将登录状态判断的逻辑代码放在这个页面的 onLoad 方法中,并将 app.json 中配置的第一个页面的路径改为此页面的路径。这样就保证了登录状态判断的逻辑一定会执行,也就不会出现上述的问题。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
/// launch.js

const app = getApp();

Page({
onLoad: function (options) {
/// 判断登录状态
// 取出缓存在本地的 sessionId
app._sessionId = wx.getStorageSync('SESSIONID');
if ((null != app._sessionId) && ('' != app._sessionId)) {
// 已经登录登录
// 跳转到 首页页面
wx.reLaunch({
url: '/pages/index/index',
});
} else {
// 没有登录
// 跳转到 登录页面
wx.reLaunch({
url: '/pages/login/login',
});
}
}
})

访问后台接口

如果小程序之前已经登录了,那么就会记录这个登录状态,下次打开小程序的时候就直接跳转到首页了。这个时候可能会访问后台服务器,请求数据并显示在页面上。一般情况下,我们会将之前缓存在的登录信息(sessionId、userId)传递给后台,可以将这些参数添加到请求头中。后台拿到这些登录信息后会去数据库中进行匹配,查看这个人的登录状态是否已经失效,比如:这个账号是否已经在其它设备上登录,登录的状态是否已经过期等,然后用一个特定的状态码将这个消息返回给客户端。我们需要做的是拦截所有的网络请求(网络请求最好做一层封装),然后解析请求完成的回调,根据后台返回的状态码做对应的操作。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
/// index.js

const app = getApp();

Page({
onLoad: function (options) {
wx.request({
url: 'xxx/xxx/xxx',
header: {
'content-type': 'application/json',
/// 通常情况下,我们会将登录状态添加到后台的请求头中发送给后台
/// 后台拿到这个值后会在数据库中进行匹配,并判断登录是否失效
'sessionId': app._seccsionId
},
data: {
xxx:'xxx'
},
/// 请求完成
complete(res) {
if (200 == res.statusCode) { /// 接口访问成功
// 可以和后台协商下,用一个特定的 code 值来表示登录失效的情况
/// 这里仅做模拟,0 表示成功;1004 表示登录失效
const code = 1004;
if (code === 0) { // 请求成功
// 刷新 UI
// ...
} else if (code === 1004) { // 登录失效
/// 移除登录状态的缓存
// 1、清除内存中的登录状态
app._sessionId = null;
// 2、移除本地的登录登录状态
wx.removeStorage({
key: 'SESSIONID',
});

/// 跳转到登录页面
wx.reLaunch({
url: '/pages/login/login',
});
} else { // 其它异常
// 略...
}
} else { /// 接口访问失败
// 一般是网络问题、服务器异常、参数问题等
// ...
}
}
})
}
})

登录

登录的操作其实就是上面介绍的微信官方提供的那 三个步骤
登录成功之后,我们就需要保存好登录相关的信息,一般包括用户相关的信息以及登录状态。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
/// login.js

Page({

/**
* 点击登录按钮的回调
*/
clickLoginAction(e) {
/// 1、调用 wx.login() 获取 code
wx.login({
success: res => {
/// 2、发送 res.code 到后台换取 openId, sessionKey, unionId
/// 注意:对于网络请求,最好能够自己封装一下,这里只是做演示
wx.request({
// 2.1 后台登录接口地址
url: 'xxx/xxx/xxx',
// 2.2 请求参数,一般包括 登录账号、密码(验证码)、code
data: {
code: res.code,
// phone: xxx
// password: xxx
},
/// 3、登录成功,接收后台返回的数据,一般包括用户相关的信息以及登录状态
success(res) {
// 3.1 缓存登录状态
// 3.1.1 内存中缓存,防止频繁的 IO 操作
app._sessionId = 'xxx';
// 3.1.2 本地缓存
wx.setStorage({
key: 'SESSIONID',
data: app._sessionId
})

// 3.2 跳转到首页
wx.reLaunch({
url: '/pages/order/order'
});
}
});
});
}
})
退出登录

退出登录的操作就比较简单了,只需要将缓存在本地和内存中的登录信息清空掉就可以了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/// index.js

Page({

/// ...

/**
* 点击退出登录的回调
*/
clickLogoutAction(e) {
/// 清空登录状态
// 1、清除内存中的登录状态
app._sessionId = null;
// 2、移除本地的登录登录状态
wx.removeStorage({
key: 'SESSIONID',
});

/// 跳转到登录页面
wx.reLaunch({
url: '/pages/login/login',
})
}
})