首先附上官方文档地址和授权流程
官方地址:https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/login.html
流程图:
大致逻辑:授权 -> 发送code到服务器获取session_key - > 保存在小程序缓存内 -> 调用wx.getUserInfo和session_key获取用户信息 -> 登录成功返回访问token -> 记录登录状态 -> 执行登录成功监听(失败则不监听)
直接上代码,一下均为小程序组件模式有兴趣的可以看下官方文档
创建components(自定义名称)文件夹pages文件夹同级主要放置组件文件
创建 authorize (自定义名称)文件夹 还是一样的创建 对应的authorize.js ,authorize.wxml .authorize.wxss,authorize.json特别注意这里的 authorize.json 文件里面要定义当前页面为组件
{
"component": true
}
到这里准备工作完成
authorize.js 换成组件的写法,具体参考小程序官方文档,这里展示我定义的
Component({
//组件的对外属性 说的确实很官方,用过vue组件的就很容易理解这点
//父级向子级传值这里就是接收值得地方
properties:{
//名称要和父级绑定的名称相同
//这里主要是控制自动授权弹框是否显示 true=隐藏 false=显示
iShidden:{
type:Boolean,//定义类型
value: true,//定义默认值
},
//是否自动登录 这里主要用于没有授权是否自动弹出授权提示框
//**用在不自动登录页面但是某些操作需要授权登录**
isAuto:{
type: Boolean,
value: true,
},
},
//组件的内部数据,和 properties 一同用于组件的模板渲染
data:{
cloneIner:null
},
//组件所在页面的生命周期声明对象
pageLifetimes:{
//页面隐藏
hide:function(){
//关闭页面时销毁定时器
if(this.data.cloneIner) clearInterval(this.data.clearInterval);
},
//页面打开
show:function(){
//打开页面销毁定时器
if (this.data.cloneIner) clearInterval(this.data.clearInterval);
},
},
//组件生命周期函数,在组件实例进入页面节点树时执行
attached(){
},
//组件的方法
methods:{
}
});
注:以下的方法都需写在 methods 内
第一步:未授权用户判断是否执行授权还是直接进行获取用户信息
//检测登录状态并执行自动登录
setAuthStatus(){
var that = this;
that.setErrorCount();
wx.getSetting({
success(res) {
//这里会检测是否授权,如果授权了会直接调用自动登录
if (!res.authSetting['scope.userInfo']) {
//没有授权不会自动弹出登录框
if (that.data.isAuto === false) return;
//自动弹出授权
that.setData({ iShidden: false });
} else {
//自动登录
that.setData({ iShidden: true });
if (app.globalData.token) {
//这里是授权回调
that.triggerEvent('onLoadFun', app.globalData.token);
that.WatchIsLogin();
} else {
wx.showLoading({ title: '正在登录中' });
//这里是已授权调用wx.getUserInfo
that.getUserInfoBydecryptCode();
}
}
}
})
}
第二步,没有授权执行打开授权弹出框
//授权
setUserInfo(e){
var that = this, pdata={};
pdata.userInfo = e.detail.userInfo;
pdata.spid = app.globalData.spid;
wx.showLoading({ title: '正在登录中' });
wx.login({
success: function (res) {
if (!res.code) return app.Tips({ title: '登录失败!' + res.errMsg});
//获取session_key并缓存
that.getSessionKey(res.code, function () {
that.getUserInfoBydecryptCode();
});
},
fail() {
wx.hideLoading();
}
})
},
//从缓存中获取session_key,如果没有则请求服务器再次缓存
getSessionKey(code,successFn,errotFn){
var that=this;
wx.checkSession({
success: function (res){
if(wx.getStorageSync('session_key'))
successFn && successFn();
else
that.setCode(code, successFn, errotFn);
},
fail:function(){
that.setCode(code, successFn, errotFn);
}
});
},
//访问服务器获得session_key 并存入缓存中
setCode(code, successFn, errotFn){
var that = this;
app.basePost(app.U({ c: 'Login', a: 'setCode' }), { code: code }, function (res) {
wx.setStorageSync('session_key', res.data.session_key);
successFn && successFn(res);
}, function (res) {
if (errotFn) errotFn(res);
else return app.Tips({ title: '获取session_key失败' });
});
}
第三步:执行getUserInfoBydecryptCode 登录获取访问权限
getUserInfoBydecryptCode: function () {
var that = this;
var session_key = wx.getStorageSync('session_key')
//没有获取到session_key,打开授权页面
//这里必须的判断存在缓存中的session_key是否存在,因为在第一步的时候,判断了
//授权了将自动执行获取用户信息的方法
if (!session_key) {
wx.hideLoading();
if(that.data.isAuto) that.setData({ iShidden: false })
return false;
};
wx.getUserInfo({
lang: 'zh_CN',
success: function (res) {
var pdata = res;
pdata.userInfo = res.userInfo;
pdata.spid = app.globalData.spid;//获取推广人ID
pdata.code = app.globalData.code;//获取推广人分享二维码ID
if (res.iv) {
pdata.iv = encodeURI(res.iv);
pdata.encryptedData = res.encryptedData;
pdata.session_key = session_key;
//获取用户信息生成访问token
app.basePost(app.U({ c: 'login', a: 'index' }), { info: pdata},function(res){
if (res.data.status == 0) return app.Tips(
{ title: '抱歉,您已被禁止登录!' },
{ tab: 4, url: '/pages/login-status/login-status' }
);
else if(res.data.status==410){
wx.removeStorage({ key:'session_key'});
wx.hideLoading();
if (that.data.iShidden == true) that.setData({ iShidden: false });
return false;
}
//取消登录提示
wx.hideLoading();
//关闭登录弹出窗口
that.setData({ iShidden: true, ErrorCount:0});
//保存token和记录登录状态
app.globalData.token = res.data.token;
app.globalData.isLog = true;
//执行登录完成回调
that.triggerEvent('onLoadFun', app.globalData.uid);
//监听登录状态
that.WatchIsLogin();
},function(res){
wx.hideLoading();
return app.Tips({title:res.msg});
});
} else {
wx.hideLoading();
return app.Tips({ title: '用户信息获取失败!'});
}
},
fail: function () {
wx.hideLoading();
that.setData({ iShidden: false });
},
})
}
第四步:监听登录状态
再服务器无法获取到token时,当前页面会一直监听token是否为空,防止无限获取token设置错误次数,终止监听
监听token的用意为:token是服务器返回当前用户的访问凭证,凭证有过期的时候这时候所有的网络请求将无法访问,所以用了一个愚蠢的方法来监听token
//监听登录状态
WatchIsLogin:function(){
this.data.cloneIner=setInterval(function(){
//防止死循环,超过错误次数终止监听
if (this.getErrorCount()) return clearInterval(this.data.clearInterval);
if (app.globalData.token == '') this.setAuthStatus();
}.bind(this),800);
this.setData({ cloneIner:this.data.cloneIner});
}
/**
* 处理错误次数,防止死循环
*
*/
setErrorCount:function(){
if (!this.data.ErrorCount) this.data.ErrorCount=1;
else this.data.ErrorCount++;
this.setData({ ErrorCount: this.data.ErrorCount});
},
/**
* 获取错误次数,是否终止监听
*
*/
getErrorCount:function(){
return this.data.ErrorCount >= 10 ? true : false;
}
Copyright © 2019- starchart.cn 版权所有
违法及侵权请联系:TEL:199 18 7713 E-MAIL:2724546146@qq.com
本站由北京市万商天勤律师事务所王兴未律师提供法律服务