在《使用uView UI+UniApp開發微信小程式》的隨筆中,介紹了基於uView UI+UniApp開發微信小程式的一些基礎知識和準備工作,其中也大概介紹了一下基本的登入過程,本篇隨筆詳細介紹一下微信小程式的相關登入處理以及登入後設置使用者身份資訊,並跳轉到相應頁面的處理過程。

1、令牌判斷和登入方式

在之前介紹過,在業務系統中,我們需要根據登入使用者的身份獲取對應的資料,如果使用者沒有登入,這些資訊是無法獲到的,那麼我們可以在app.vue中判斷使用者是否登入,然後跳轉到對應的頁面,如下所示。

也就是系統啟動的進入的時候,我們需要對系統使用者的身份做一次判斷,判斷token是否存在,並且是否有效(因為token是有時效的)。

我們先來介紹下如何如何判斷token是否存在的處理過程,由於token本身在登陸的時候,設定了儲存,因此只需要通過uView的token獲取操作即可讀取出來,並進行判斷即可。

我們只需要簡單判斷this.vuex_token 是否存在值即可,因為this.vuex_token是由於uView在載入Mixin的時候,已經自動映射了儲存的鍵值,因此我們可以通過this.vuex_token訪問到對應的值。

如果是簡單的判斷,我們在app.vue的如下程式碼即可處理

<script>
export default {
globalData: {
username: ''
},
onLaunch() {
//如果使用者沒有登入或令牌失效,跳轉到登入介面
// console.log(this.vuex_token)
if(!this.vuex_token) {
this.$u.route({
url: 'pages/template/login/password'
});
} else {
uni.switchTab({
url: '/pages/example/myinfo'
});
}
},
}
</script>

不過我們需要通過判斷它的時限有效性,那麼通過判斷失效日期進行處理,如下程式碼所示。

<script>
export default {
onLaunch() {
//如果使用者沒有登入或令牌失效,跳轉到登入介面
// console.log(this.vuex_token)
console.log(this.$u.http.config.baseUrl)
var authed = this.checkToken()
if(!authed) {
this.$u.route({
url: '/pages/task/login/index'
});
} else {
this.$u.route({
type:'tab',
url: 'pages/task/login/myinfo'
})
}
},
methods: {
checkToken() {
if(this.vuex_token && this.vuex_user) {
var expired = new Date(this.vuex_user.expired) //token過期時間
const now = Date.now()
if(expired - now > 0) {
return true
}
}
return false
}
}
}
</script>

其中expired是我們獲取到token的時間,並加上token的失效時間的。

我們這裡使用了一個checkToken的函式,用來判斷是否正常登入並且有效的,如果令牌無效,那麼跳轉到登陸介面,否則直接跳到個人資訊頁面下。

我們先來看看登入介面,我們這裡提供了幾種登入方式,賬號密碼登入、簡訊驗證碼登陸、微信授權登入幾種方式。

這幾種不同的登入方式,都是在驗證成功後,需要獲取使用者的身份資訊,並設定到Storage儲存中去,邏輯上有相同之處。

2、登入的處理邏輯

使用者登入的時候,需要輸入使用者名稱,密碼,構建相關的引數後,進行登入處理,處理過程程式碼如下所示。

submit() {
this.$refs.uForm.validate(valid => {
if (valid) {
this.$u.api.User.login(this.model).then(data => {
// 登陸成功跳轉到Tab頁面
uni.switchTab({
url: '/pages/task/login/myinfo'
});
});
} else {
console.log('驗證失敗');
}
});
},

其中 this.$u.api.User 是使用者API介面的統一呼叫方式,其中http.api.js的程式碼如下所示。

import User from '../api/user.js'
import Task from '../api/task.js' const install = (Vue, vm) => { // 將各個定義的介面名稱,統一放進物件掛載到vm.$u.api(因為vm就是this,也即this.$u.api)下
vm.$u.api = { // 將 vm 物件傳遞到模組中
User: User(vm),
Task: Task(vm)
}
} export default { install }

其中api/user.js裡面定義了訪問遠端WebAPI的操作,同時也是我們封裝一些處理邏輯的操作函式,我們可以通過ES6的Promise進行封裝一個簡單的登入函式。

由於我們這裡登入過程,除了使用者名稱密碼外,還需要appid、時間戳以及簽名引數等資訊組合,因此構建引數比較多一點。

登入成功後,我們就呼叫resolve的執行即可,如果失敗,呼叫reject的處理。

這樣我們就可以直接通過Promise的操作處理登入成功後的操作了,如下程式碼所示。

this.$u.api.User.login(this.model).then(data => {
uni.switchTab({
url: '/pages/task/login/myinfo'
});
});

而其中setUserToken函式,主要是便於重用的目的抽取出來,因為設定令牌和使用者資訊,是其他兩個登入方式(簡訊登陸、微信登陸)所通用的操作。

簡訊驗證碼的登入方式也是類似,需要後端配合判斷簡訊的有效性即可,前端先呼叫後端的傳送簡訊操作,如下程式碼所示

//傳送簡訊驗證碼
var params = { PhoneNumber: this.tel }
this.$u.api.User.SendPhoneLoginSmsCode(params).then(res => {
if(res.success) {
this.$u.toast(`驗證碼已傳送至手機 ${this.tel},請注意查收!`)
this.$u.route({
url: 'pages/task/login/code',
params: {
mobile:this.tel
}
});
} else {
this.$u.toast('傳送出現錯誤:' + res.errorMessage)
}
})

而前端呼叫的函式也就是在api/user.js中簡單封裝一下對API的呼叫即可。

SendPhoneLoginSmsCode(data) { // 傳送登入動態碼
return vm.$u.post('/api/framework/User/SendPhoneLoginSmsCode', data)
},

傳送的後端程式碼如下所示,主要就是放在快取中一段時間供驗證即可。

        /// <summary>
/// 傳送登入動態碼
/// </summary>
/// <returns></returns>
[AllowAnonymous]
public CommonResult SendPhoneLoginSmsCode(PhoneCaptchaModel model)
{
//獲取隨機6位數字動態驗證碼
var code = RandomChinese.GetRandomNumber(6); //使用自定義模板處理簡訊傳送
string message = string.Format(ConfigData.MySmsCodeTemplate, code);
var smsSender = new MySmsSender();
var result = smsSender.Send(model.PhoneNumber, message);
if (result.Success)
{
var cacheKey = model.PhoneNumber;//以手機號碼作為鍵儲存驗證碼快取
var cacheItem = new SmsLoginCodeCacheItem { Code = code, PhoneNumber = model.PhoneNumber }; var cache = CacheManagerHelper.GetCacheItem(cacheKey, () =>
{
return cacheItem;
}, TimeSpan.FromMinutes(ConfigData.SmsCodeExpiredMinutes));
} return result;
}

驗證的時候,只需要判斷快取裡面是否存在記錄和對應驗證碼是否匹配即可,如果順利通過,那麼構建使用者的token資訊返回給前端就是。

如果前端傳送驗證碼成功,那麼登陸介面跳轉到等待輸入驗證碼的介面,如下所示。

輸入正確的驗證碼即可順利登陸,否則過期則要求重新發送簡訊驗證碼。

submit() {
var params = { mobile: this.mobile, smscode: this.smscode };
console.log(params);
this.$u.api.User.dynamiclogin(params)
.then(res => {
this.$u.toast('驗證成功'); uni.switchTab({
url: '/pages/task/login/myinfo'
});
})
.catch(error => {
console.log('驗證失敗' + error);
this.$u.toast(error);
});
},

如果順利登陸,則跳轉到我的頁面裡面去,展示一些常用的資訊彙總,以及常見處理操作。

這裡面涉及一個退出登入的操作,主要就是登出當前使用者的身份,只要清空身份資訊,並跳轉到登入首頁即可。

logout() {
this.$u.vuex('vuex_token', null) // 重置
this.$u.vuex('vuex_user', null) // 重置
this.$u.toast('退出成功,請重新登入!')
this.second = 0
setTimeout(()=> {
this.$u.route({ url: '/pages/task/login/index' })
}, 1500)
},

鑑於篇幅原因,先介紹到這裡,關於微信授權登陸及繫結的操作過程,後續再介紹。