微信小程序非跳转式组件授权登录的方法示例
首先附上官方文档地址和授权流程
官方地址: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(){ varthat=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){ varthat=this,pdata={}; pdata.userInfo=e.detail.userInfo; pdata.spid=app.globalData.spid; wx.showLoading({title:'正在登录中'}); wx.login({ success:function(res){ if(!res.code)returnapp.Tips({title:'登录失败!'+res.errMsg}); //获取session_key并缓存 that.getSessionKey(res.code,function(){ that.getUserInfoBydecryptCode(); }); }, fail(){ wx.hideLoading(); } }) }, //从缓存中获取session_key,如果没有则请求服务器再次缓存 getSessionKey(code,successFn,errotFn){ varthat=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){ varthat=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); elsereturnapp.Tips({title:'获取session_key失败'}); }); }
第三步:执行getUserInfoBydecryptCode登录获取访问权限
getUserInfoBydecryptCode:function(){ varthat=this; varsession_key=wx.getStorageSync('session_key') //没有获取到session_key,打开授权页面 //这里必须的判断存在缓存中的session_key是否存在,因为在第一步的时候,判断了 //授权了将自动执行获取用户信息的方法 if(!session_key){ wx.hideLoading(); if(that.data.isAuto)that.setData({iShidden:false}) returnfalse; }; wx.getUserInfo({ lang:'zh_CN', success:function(res){ varpdata=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)returnapp.Tips( {title:'抱歉,您已被禁止登录!'}, {tab:4,url:'/pages/login-status/login-status'} ); elseif(res.data.status==410){ wx.removeStorage({key:'session_key'}); wx.hideLoading(); if(that.data.iShidden==true)that.setData({iShidden:false}); returnfalse; } //取消登录提示 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(); returnapp.Tips({title:res.msg}); }); }else{ wx.hideLoading(); returnapp.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())returnclearInterval(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; elsethis.data.ErrorCount++; this.setData({ErrorCount:this.data.ErrorCount}); }, /** *获取错误次数,是否终止监听 * */ getErrorCount:function(){ returnthis.data.ErrorCount>=10?true:false; }
以上就是组件内全部的方法需要在组件生命周期函数内调用第一步的方法检测授权,执行登录
attached(){ this.setAuthStatus(); }
注:在网络请求中一定要处理token失效的操作,主要把app.globalData.token和app.globalData.isLog设置回空和false
这里附上没有定义的一些app内公用的快捷方法以下的方法最好是写在其他文件里面在app.js里面写一个快捷调用的方法
/* *post网络请求 *@paramstring|object请求地址 *@paramobjectdataPOST请求数组 *@paramcallablesuccessCallback成功执行方法 *@paramcallableerrorCallback失败执行方法 */ constbasePost=function(url,data,successCallback,errorCallback,header){ if(typeofurl=='object')url=U(url); wx.request({ url:url, data:data, dataType:'json', method:'POST', header:header, success:function(res){ try{ if(res.data.code==200){ successCallback&&successCallback(res.data); }else{ if(res.data.code==402)getApp().globalData.token='',getApp().globalData.isLog=false; //返回状态为401时,用户被禁止访问关闭当前所有页面跳转至用户禁止登录页面 if(res.data.code==401)returnTips({title:res.data.msg},{tab:4,url:'/pages/login-status/login-status'}); errorCallback&&errorCallback(res.data); } }catch(e){ console.log(e); } },fail:function(res){ errorCallback&&errorCallback(res); }, complete:function(res){ } }); } /* *组装URl *@paramobjectopt */ constU=function(opt,url){ varm=opt.m||'routine_two',c=opt.c||'auth_api',a=opt.a||'index',q=opt.q||'', p=opt.p||{},params='',gets=''; if(url==undefined)url=getApp().globalData.url; params=Object.keys(p).map(function(key){ returnkey+'/'+p[key]; }).join('/'); gets=Object.keys(q).map(function(key){ returnkey+'='+q[key]; }).join('&'); returnurl+'/'+m+'/'+c+'/'+a+(params==''?'':'/'+params)+'.html'+(gets==''?'':'?'+gets); }
代码量有点多,都是能用到的,望大神们多多指点
本小程序后台框架由http://github.crmeb.net/u/blue提供
TP5+EasyWeChat技术支持
如果对微信小程序授权不熟悉的可以用EasyWeChat,确实好用;不是来吹这个EasyWeChat来了,只是个人觉得好用勿喷
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。