主机参考:VPS测评参考推荐/专注分享VPS服务器优惠信息!若您是商家可以在本站进行投稿,查看详情!此外我们还提供软文收录、PayPal代付、广告赞助等服务,查看详情! |
我们发布的部分优惠活动文章可能存在时效性,购买时建议在本站搜索商家名称可查看相关文章充分了解该商家!若非中文页面可使用Edge浏览器同步翻译!PayPal代付/收录合作 |
小程序是如何实现登录功能的?本文把小程序登录的正确打开方法介绍给大家,希望对大家有所帮助!
Applet网络组件
https://developers . weixin . QQ . com/mini program/dev/API/network/request/wx . request . html
请求任务描述
方法描述RequestTask.abort()中断请求的任务。请求任务。onheadersreceived(函数回调)侦听HTTP响应头事件。将早于完成事件的请求。请求任务。offheadersreceived(函数回调)取消侦听HTTP响应头事件。请求任务。onchunkreceived(函数回调)侦听transfer -encoding chunk received事件。收到新块时触发。请求任务。offchunkreceived(函数回调)取消侦听transfer -encodingchunk received事件。wx . request(Object对象)属性
这里只列出了常用的属性。请检查所有属性的链接。
属性类型的默认值必须指示urlstring是developer server的接口地址datastring/object/array buffer No requested参数headerObject未设置请求的头,并且不能在头中设置Referer。content -类型默认为application/jsontimeoutnumber,无超时,单位为毫秒methodstringGET,无HTTP请求方法successfunction,无回调函数在接口调用中失败,无回调函数completefunction在接口调用中失败,无回调函数在接口调用中结束(成功和失败的调用都将执行),即使是中止请求!综上所述,所有小程序界面基本上都有两个特点:
参数都是一个对象。易于记忆,同时易于扩展。
都有相同的结果处理方法:都有三个回调属性:成功、失败和完成。
在各种接口执行情况下引入errMsg对象。
回调属性errMsg对象成功{errmsg:“请求:确定“...}失败{errmsg:“请求:失败“...}有些系统在这个fail后面有一个空格,因此要使用这个判断,最好使用正则表达式。还可以使用大于-1的indexOf函数进行判断。中止{errmsg:“请求:失败中止“...}示例代码
let req task = wx . request({ URL:getApp()global data . API,success(RES){ if(RES . errmsg = = = = = & quot;请求:确定& quot)控制台。log(& quot;res & quot,RES);},fail(err){//if(err . errmsg . index of(& amp;#39;请求:失败。#39;)& gt-1)console . log#39;错误&。#39;,err);if(/^request:fail/i.test(err.errmsg))console . log(& quot;呃& quot,err);},complete(RES){ console . log(& quot;resOrErr & quot,RES);}, });const reqTaskOnHeadersReceived =(headers)= & gt;{ req task . offheaders received(reqTaskOnHeadersReceived);console . log(& quot;标题& quot标题);//由于请求没有完全完成,我们无法获取请求的状态码,但可以通过返回的requestBody的长度来判断。//两个解释:1。Two ~ ~可以快速将字符串数字转换为数字。// 2.为什么不到19?是因为后台未经允许返回requestBody时,content -长度为“18”,正常情况下大于19。所以多少要看具体情况。if(~ ~ headers . header【& quot;内容-长度& quot】& lt19)req task . abort();};req task . onheadersreceived(reqTaskOnHeadersReceived);小程序登录界面
wx.getUserProfile(对象对象)
获取用户信息。该页面只能在click事件发生后调用(例如,在button上bindtap的回调中),每次发出请求时都会弹出一个授权窗口,用户同意后将返回userInfo。此接口用于替换wx.getUserInfo .详细信息请参见用户信息接口调整说明。
wx . check session(Object对象)
检查登录状态是否已过期。通过wx.login接口获取的用户登录状态具有一定的时效性。用户不使用小程序的时间越长,用户登录状态越有可能无效。另一方面,如果用户一直在使用小程序,则用户登录状态保持有效。具体的时效逻辑由微信维护,对开发者透明。开发人员只需要调用wx.checkSession接口来检查当前用户的登录状态是否有效。
登录状态过期后,开发人员可以调用wx.login来获取新的用户登录状态。成功的调用意味着当前会话密钥尚未过期,而失败的调用意味着会话密钥已过期。更多使用方法见小程序登录。
wx.login(对象对象)
调用接口以获取登录凭据(代码)。通过凭证交换用户登录状态信息,包括用户在当前小程序下的唯一ID、微信开放平台账户下的唯一ID(如果当前小程序绑定到微信开放平台账户,则为unionid)以及本次登录的会话密钥(session_key)。用户数据的加密和解密通信需要依赖会话密钥。更多使用方法见小程序登录。
后端登录接口的代码实现
后端使用NodeJS,web框架KOA版本2.13.4,路由框架@koa/router版本10.1.1,框架请求版本2.88.2,jsonwebtoken用于加密和解密令牌信息,版本8.5.1。
//app . jsconst Koa = require(& quot;koa & quot);const Router = require(& quot;@ KOA/router & quot;);const weixin auth = require(& quot;。/lib/KOA 2-weixin -auth & quot;);const jsonwebtoken = require(& quot;jsonwebtoken & quot);const app = new Koa();//小程序票证信息const miniProgramAppId =“* * * * * * * * * & quot;;const miniProgramAppSecret = & quot;* * * * * * * * * & quot;const weixin auth = new weixin auth(miniProgramAppId,miniProgramAppSecret);const JWT _ SECRET = & quot;JWTSECRET & quot;//路由中间件需要安装@koa/router//并使用group constructor = new router({ prefix:“/user & quot;,});//这是一个普通的登录方法//添加一个参数sessionKeyIsValid,该参数表示sessionKey是否仍然有效。router . post(& quot;/weixin -登录& quot,async(CTX)= & gt;{ let { code,userInfo,encryptedData,iv,session keyi valid } = CTX . request . body;//Parse OpenID Const Token = Await weixin auth。getaccesstoken(代码);userinfo . OpenID = token . data . OpenID;//您可以在这里自己处理,例如将其记录在数据库中,并处理token = jsonwebtoken . sign({ name:userinfo . nickname },jwt _ secret,{ expires in:“1d & quot;} );object . assign(userInfo,{ authorization token });ctx.status = 200ctx.body = { code: 200,msg:& quot;好的,data: userInfo,};});//lib/KOA 2-weixin -auth . jsconst query string = require(& quot;查询字符串& quot);const request = require(& quot;请求& quot);const access token = function(data){ if(!(AccessToken的这个实例)){ return new access token(data);} this.data = data};/*!*检查AccessToken是否有效,检查规则是将当前时间与过期时间进行比较* *示例:* ` ` ` * token . is valid();* ` ` ` */access token . prototype . is valid = function(){ return(!!this.data.session_key && amp新日期()。getTime()& lt;this . data . create _ at+this . data . expires _ in * 1000);};/* * *根据appid和appsecret创建OAuth接口的构造函数*如果需要跨进程和跨机器操作,则需要全局维护访问令牌*使用令牌的优先级为:* * 1。使用当前缓存的令牌对象* 2。调用获取令牌的异步方法,并在获取令牌后使用它(并缓存它)。*示例:* ````* var OAuth = require(& amp;#39;oauth & amp#39;);* var API = new OAuth(& amp;#39;appid & amp#39;,& amp#39;秘密& amp#39;);* ``` * @param {String}应用于公共平台的appID * @ param { String }应用于公共平台的app secret */const auth = function(appID,app secret){ this。AppID = appIDthis . app secret = app secret;this . store = { };this . gettoken = function(OpenID){ return this . store【OpenID】;};this . save token = function(OpenID,token){ this . store【OpenID】= token;};};/* * *获取重定向后要跳转的授权页面的URL地址* @ param {string}开发者可以提供的* @ param {string}范围的数据,值为snsapi_userinfo和snsapi_base。前者用于弹出,后者用于跳转*/auth . prototype . getauthorizeurl = function(redirect _ uri,scope,state){ return new promise((resolve,reject)=》{ const URL = & quot;https://open.weixin.qq.com/connect/oauth2/authorize";let info = { appid: this.appid,redirect_uri: redirect_uri,scope:scope | | & quot;snsapi _ base & quot,state:state | | & quot;",响应类型:& quot代码& quot, };解析(URL+& quot;?"+query string . string ify(info)+& quot;#微信重定向& quot);});};/*!*处理令牌并更新到期时间*/auth . prototype . process token = function(data){ data . create _ at = new date()。gettime();//存储tokethissavetoken(数据。OpenID,data);返回AccessToken(数据);};/* * *根据授权获取的代码,换取访问令牌和openid *获取openid后,即可调用‘微信。以获取更多信息* @ param { String } code */auth . prototype . getaccesstoken = function(code){ return new promise((resolve,reject))=》{ const URL = & quot;https://api.weixin.qq.com/sns/jscode2session";//因为这个框架版本很久没有更新了,这里的地址发生了变化,需要修改为上面的地址,否则//会出现41008错误。这也是为什么没有直接使用框架的原因,引用本地使用。//const URL = & quot;https://api.weixin.qq.com/sns/oauth2/access_token";const info = { appid: this.appid,secret: this.appsecret,js_code: code,grant _ type:& quot;授权代码& quot, };request . post(URL,{ form: info },(err,res,body)= & gt;{ if(err){ reject(err);} else { const data = JSON . parse(body);resolve(this . process token(data));} });});};/* * *根据刷新令牌刷新访问令牌。在调用getAccessToken之前它不会生效* @ param { string } refresh token refresh token */auth . prototype . refresh token = function(refresh token){ return new promise((resolve,reject))=》{ const URL = & quot;https://api.weixin.qq.com/sns/oauth2/refresh_token";var info = { appid: this.appid,grant_type:刷新令牌& quot,refresh_token: refreshToken,};request . post(URL,{ form: info },(err,res,body)= & gt;{ if(err){ reject(err);} else { const data = JSON . parse(body);resolve(this . process token(data));} });});};/* * *根据openid,获取用户信息。*当访问令牌无效时,将通过刷新令牌自动获取新的访问令牌。然后获取用户信息* @param {Object|String} options并将其传入openid或查看options */auth . prototype . getuser = async function(OpenID){ const data = this . gettoken(OpenID);console . log(& quot;getUser & quot、数据);如果(!data){ var Error =新错误(& quot没有& quot的令牌+options . OpenID+& quot;,请先授权。");错误。= & quotNoOAuthTokenError & quot;投掷误差;} const token = access token(data);var accessTokenif(token . is valid()){ access token = token . data . session _ key;} else { var newToken = await this . refreshaccesstoken(token . data . refresh _ token);access token = new token . data . session _ key;} console . log(& quot;访问令牌& quot,access token);等待这个归来。_ getUser(OpenID,access token);};auth . prototype . _ getUser = function(OpenID,accessToken,lang){ return new Promise((resolve,reject)= & gt;{ const url = & quothttps://api.weixin.qq.com/sns/userinfo";const info = { access _ token:access token,openid: openid,lang:lang | | & quot;zh _ CN & quot, };request . post(URL,{ form: info },(err,res,body)= & gt;{ if(err){ reject(err);} else { resolve(JSON . parse(body));} });});};/* * *根据代码,获取用户信息。* @ param { String } code */auth . prototype . getuserbycode = async function(code){ const token = await this . getaccesstoken(code);return await this . getuser(token . data . OpenID);};module.exports = Authapplet端登录代码的实现
& lt!--页/索引。wxml --& gt;& lt视图class = & quot第3页以上部分& quot& gt& lttext class = & quotpage -section _ _ title & quot;& gt微信登录
对于一个软件来说,就代码级别而言,您需要追求最基本的方面(远不止这些,但让我们先做这些):
可维护性
所谓“维护”无非就是修复bug、修改旧代码、添加新代码。所谓“代码易于维护”是指可以快速修改或添加代码,而不会破坏原始代码设计和引入新的bug。所谓“代码不易维护”是指修改或添加代码会带来引入新bug的巨大风险,并且需要很长时间才能完成。
可读性(可读性)
软件设计大师马丁·福勒曾说:“任何傻瓜都能写出计算机能理解的代码。优秀的程序员可以编写人类可以理解的代码。”翻译成中文,“任何傻瓜都能写出计算机能理解的代码。优秀的程序员能写出人们能理解的代码。”谷歌甚至有一个名为可读性的特殊认证。只有获得此认证的工程师才有资格在代码审查期间批准其他人提交代码。可见代码的可读性有多重要。毕竟,代码被读取的次数远远超过了它被编写和执行的次数。我们需要看代码是否符合编码规范,命名是否令人满意,注释是否详细,功能长度是否合适,模块划分是否清晰,是否符合高内聚低耦合等等。
延展性(延展性)
扩展性也是评估代码质量的一个非常重要的标准。代码中保留了一些函数扩展点,您可以将新的函数代码直接插入扩展点,而不必大费周章地添加一个函数并更改大量原始代码。
可重用性(可重用性)
代码的可重用性可以简单地理解为尽量减少代码编写的重复和重用现有代码。
然后让我们优化代码:
模块化
登录代码可以模块化,代码如下:
//lib/login.js函数loginwithcallback(CB){//建议使用wx.getUserProfile获取用户信息。每次开发人员通过此接口获取用户个人信息时,用户都必须进行确认。//开发者应妥善保管用户快速填写的头像昵称,避免重复弹出窗口wx . get user profile({ desc:“用于完善会员信息”,//声明获取用户个人信息的目的,稍后将在弹出窗口中显示。请填写成功:(RES)= & gt;{ let { userInfo,encryptedData,iv } = resconst requestLoginApi =(code)= & gt;{//发起网络请求wx . request({ URL:“http://localhost:3000/user/weixin -log in & quot;,方法:& quot帖子& quot,标题:{ & quot内容-类型& quot:& quot应用程序/JSON & quot;,},data: { code,userInfo,encryptedData,iv,},success(RES){ console . log(& quot;请求成功“,RES . data);let token = RES . data . data . authorization token;wx . setstoragesync(& quot;令牌& quot,token);onUserLogin(令牌);console . log(& quot;授权& quot,token);},fail(err){ console . log(& quot;请求中的异常“,错误);}, });};const onuserlog in =(token)= & gt;{ getApp()global data . token = token;wx . show toast({ title:& quot;登录成功“,});中频(cb & amp& ampcb的类型= = & quot函数& quot)cb(代币);};wx . check session({ success:(RES)= & gt;{// session_key未过期,在此生命周期内一直有效。console . log(& quot;在落地上”);let token = wx . getstoragesync(& quot;令牌& quot);if(token)onuserlog in(token);},fail:(RES)= & gt;{// session_key已过期,需要重新执行登录流程wx . log in({ success(res0){ if(res0 . code){ request log in API(res0 . code));} else { console . log(& quot;登录失败!"+res0 . errmsg);} }, });}, });}, });}导出默认loginWithCallback承诺
回调地狱问题不利于代码的读取,所以接下来我们基于Promise优化代码。使用Promise对象,异步操作可以表示为同步操作的流程,从而避免嵌套回调函数。此外,Promise对象提供了一个统一的接口,这使得控制异步操作变得更加容易。
几种承诺方法简介
方法名表明Promise.prototype.then方法返回一个新的Promise对象,因此可以用chain编写。这种设计使嵌套的异步操作可以很容易地重写,从回调函数的“水平开发”到“向下开发”。Promise.prototype.catch是promise . prototype . then(null,rejection)的别名,用于指定出错时的回调函数。Promise对象的错误是“冒泡”的,将被传递回去,直到它被捕获为止。换句话说,错误总是被下一个catch语句捕获。Promise.prototype.finally方法返回一个承诺。在承诺结束时,无论结果是履行还是拒绝,都将执行指定的回调函数。这为成功完成Promise与否后需要执行的代码提供了一种方法。Promise .所有这些都避免了同一条语句需要在then()和catch()中编写一次的情况。Promise.all方法用于将多个Promise实例打包成一个新的Promise实例。Promise.all方法接受一个数组作为参数,var p = promise . all(【P1,p2,P3】);P1、p2和p3都是Promise对象的实例。(Promise.all方法的参数不一定是数组,但必须有迭代器接口,返回的每个成员都是Promise实例。)P的状态由p1、p2和p3决定,可以分为两种情况。(1)只有当p1、p2和p3的状态都满足时,P的状态才会满足。此时,p1、p2和p3的返回值形成一个数组,并被传递给P的回调函数..(2)只要p1、p2和p3中的一个被拒绝,P的状态就变成被拒绝,并且第一个被拒绝的实例的返回值将被传递给P的回调函数..Promise.racePromise.race的方法还将多个Promise实例打包成一个新的Promise实例。var p = promise . race(【P1,p2,P3】);在上面的代码中,只要p1、p2和p3中的一个实例首先改变状态,P的状态就会相应地改变。首先更改的Promise实例的返回值被传递给p. Promise.any的返回值接收Promise iterable对象,只要其中一个成功,它就会返回成功的Promise。所有子例程都处于拒绝状态,总承诺也处于拒绝状态。Promise.allSettled在所有给定的承诺都被履行或拒绝后返回一个承诺,并带有一个对象数组,每个对象代表相应的承诺结果。相比之下,Promise.all()更适合相互依赖或在其中任何一个被拒绝时立即结束。小程序的API接口是Promise,需要登录的调用接口是模块化的。
1.安装插件。请首先查看npm支持文档。
Npm安装--保存迷你程序-API -诺言2。在微信开发者工具右侧的详细信息中选中使用npm模块,然后在菜单栏工具中单击构建NPM。
3.初始化代码。
//app . js import { promisifyAll } from & amp;#39;迷你程序-API -承诺与承诺。#39;从& quot../lib/login";const wxp = { } Promisifyall(wx,wxp)//需要token的请求被统一处理登录并设置标头,错误消息wxp . requestneedlogin = async function(args){ let token = wx . getstoragesync(“token & quot;);如果(!token){ token = await loginwithspromise();}如果(!args . header)args . header = { };args . header【& quot;授权& quot】= `Bearer $ { token }返回wxp.request(参数)。catch(console . error);};//app . jsapp({ wxp:wxp,});4.重写login.js代码。
//lib/log in . js function log in(){ return new Promise((resolve,reject)= & gt;{//建议使用wx.getUserProfile获取用户信息。每次开发者通过该接口获取用户个人信息时,用户都必须进行确认。//开发者应妥善保管用户快速填写的头像昵称,避免重复弹窗wx . get user profile({ desc:“用于完善会员信息”,//声明获取用户个人信息的目的,稍后将在弹窗中显示。请成功填写:async(res0)= & gt;{ let { userInfo,encryptedData,iv } = res0const app = getApp();请尝试{ app . wxp . check session();} catch(err){ reject(err);} let token = wx . getstoragesync(& quot;令牌& quot);如果(!token){ let res1 = await app . wxp . log in()。catch(err = & gt;拒绝(错误));let code = res1.codelet RES = await app . wxp . request({ URL:& quot;http://localhost:3000/user/weixin -log in & quot;,方法:& quot帖子& quot,标题:{ & quot内容-类型& quot:& quot应用程序/JSON & quot;,},数据:{ code,userInfo,encryptedData,iv,} })。catch(err = & gt;拒绝(错误));token = RES . data . data . authorization token;wx . setstoragesync(& quot;令牌& quot,token);app . global data . token = token;wx . show toast({ title:& quot;登录成功“,});解析(令牌);} }, });})}导出默认登录;5.呼叫代码
& lt视图class = & quot容器第3页+标题& quot& gt& lttext class = & quotpage -section _ _ title & quot;& gt要求登录调用的请求
这几篇文章你可能也喜欢:
- 了解微信小程序登录的前端设计和实现(微信小程序登录后端)
- 如何实现小程序的登录和授权(微信小程序登录授权流程)
- 如何解决帝国cms后台无法登录的问题(帝国cms移动终端)
- WordPress登录失败?这五个步骤帮你解决!(wordpress登录门户)
- WordPress后台登录难?试试这些有效的方法吧!
本文由主机参考刊发,转载请注明:浅析如何实现小程序的登录功能(如何登录小程序) https://zhujicankao.com/107288.html
评论前必须登录!
注册