通过扫小程序码实现网站登陆功能


Posted in Javascript onAugust 22, 2019

网络上关于实现本本功能的文章很多,但是给出案列的几乎没有,今天笔者实现用小程序码实现网站登陆,体验地址如下

https://idea.techidea8.com/open/login.shtml

思路

通过扫小程序码实现网站登陆功能

核心流程

关键流程

建立场景sceneid和websocket的绑定关系

获得sceneid

场景ID可以前端生成,也可以后端生成,只需要保证sceneid的同一时间唯一性即可。

前端生成可以采用随机数加时间戳的形式,也可以用uuid算法

//时间戳
var sceneid ="scend-" + new Data().getTime() + Math.ceil(Math.random()*888888+1000000);
建立websocket
var ws = new WebSocket("ws://192.168.0.106/websocket?clientid="+sceneid )
ws.onopen=function(env){
 console.log(env)
} 
ws.onmessage=function(env){
 var data = env.data;
 //这个data 就是后端发来的用户数据
}

后端建立websocket

后端采用go语言github.com/gorilla/websocket包建立websocket.因为golang 非常适合高并发场景。

func (ctrl *PushCtrl) websocket(w http.ResponseWriter, req *http.Request) {
 //fmt.Printf("%+v",request.Header)
 //todo 检验接入是否合法
 //checkToken(userId int64,token string)
 query := req.URL.Query()
 clientid := query.Get("clientid")
 conn, err := (&websocket.Upgrader{
  CheckOrigin: func(r *http.Request) bool {
   return true
  },
 }).Upgrade(w, req, nil)
 if err != nil {
  log.Println(err.Error())
  return
 }
 clientMap.Store(clientid, conn)
 go func(clientId string, conn *websocket.Conn) {
  //处理出错信息
  defer func() {
   conn.Close()
   clientMap.Delete(clientid)
  }()
  for {
   _, _, err := conn.ReadMessage()
   if err != nil {
    log.Println(err.Error())
    return
   }
  }
 }(clientid, conn)
}

我们采用sync.map建立sceneid和websocket的对应关系

clientMap.Save(sceneid,conn)

对于因为异常断开的con我们需要移除

clientMap.Delete(sceneid)

获得小程序二维码

获得小程序的accesstoken

小程序access 请求接口如下
``

该接口日使用频率有限制,因此我们需要将这些数据缓存起来,缓存方案很多,有redis,也有内存,我们这里直接用一个变量即可存储

accesstoken :=""
func GetAccessToken() string{
 return accesstoken 
}
func RefreshAccessToken()string{
 url = ""
 resp := httpget(url)
 //resp 是一个包含accesstoken的json字符串,我们解析这个json即可
 accesstoken = decodeaccesstokenfromjson(resp)
 return accesstoken 
}

我们还需要一个滴答计数器用来刷新accesstoken,accesstoken 的有效期是7200秒,我们4000秒刷新一次accesstoken 即可

func refreshAccessToken(){
 ticker := time.NewTicker(time.Second *4000)
 for{
  select {
   case <-ticker.C:
    RefreshAccessToken()
  }
 }
}

在init.go 中的init方法中启动协程

go refreshAccessToken()

小程序二维码编程技巧

小程序二维码请求接口如下

https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=ACCESSTOKEN

由于该链接会返回俩种结果

错误返回Json

{
"errcode":400001,
"errmsg":"什么什么原因"
}

正确返回j图片buffer

这是一个二进制码流,因此我们需要对返回结果进行标准化处理

我们建议一种标准化结果

{
code:0,
data:"",
msg:"结果说明"
}

参数 说明
code 标识成功或者失败,200为成功,400为失败
data 图片的base64格式编码
msg 结果说明,或者出错提示

代码示例如下

url := fmt.Sprintf("https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=%s", token)
ret, err := util.PostJSON(url, arg)
if err != nil {
    util.FailMsg(w, err.Error())
    return
}

jsonstr := string(ret)
if strings.Contains(jsonstr, "errmsg") {
  util.FailMsg(w, jsonstr)
  return
} else {
  base64data := base64.StdEncoding.EncodeToString(ret)
  util.RespOk(w, "data:image/png;base64,"+base64data)
}

其中util是笔者封装的常用工具包

通过扫小程序码实现网站登陆功能

常用工具包

前端请求成功后获得data,可以利用$("#qrcode").attr("src",res.data)刷新图片二维码

function refreshqrcode(){
  clientId = "scene-"+new Date().getTime();
  var api = restgo.buildapi("miniapp/getwxacodeunlimit")
  restgo.post(api,{"scene":clientId}).then(res=>{
    if(res.code==200){
      $("#qrcode").attr("src",res.data)
    }else{
      alert(res.msg)  
    }
    intiwebsocket()
  },res=>{
    alert(res.msg)
  })
}

小程序处理关键点

采用好的框架

我们编程过程才用了uniapp,这个框架不错,完全是vue的语法,

一套代码可以生成H5/小程序/android/ios

我们采用了vue的watch特性,通过监听userid来确定是否发送信息

watch:{
   userid:function(a,b){
      
      if(a==0){
        return 
      }
      
      this.loaddata()
      //如果clientid是空的说明不是扫码进来的  
      if(!this.clientid){
        return 
      }
//如果是扫码进来的,那么我们还需要推送消息到服务器后端
server.PublishMsg(this.clientid,this.userid,this.role,this.avatarUrl,this.nickName).then(res=>{
        tip.error(res.msg)
      },res=>{
        tip.error(res.msg)
      })
      
   }
 }

获取sceneid

我们通过onload方法获得sceneid

onLoad(arg) {
    if(!!arg && !!arg.scene){
          this.clientid = decodeURIComponent(arg.scene)
    }
        
  },

核心代码如下

通过gotUserInfo获得用户头像、昵称等,通过uni.login获得code

gotUserInfo :function(e) {
       //获得用户头像、昵称、
       uni.login(
       {
         success:(res) =>{
              //通过wx.login获得code
              userInfo.code = res.code
                        //统一传递到后端   
            this.authwithcode(userInfo)
         }
       }
       )
      }
     },
    authwithcode:function(userInfo){
            //code获得openid在后端做,做了后继续去查User表
      server.AuthWithCode(userInfo).then(res=>{
          //如果这个openid绑定了用户                                  
          if(res.data.id>0){
            //这里res.data 就是user对象,可以继续操作
            return ;
          }
          //如果没有那么注册
          server.RegisterWithOpenId(res.data.mini_openid,userInfo.avatarUrl,userInfo.nickName)#.then(res=>{
            //注册成功则返回
            //这里res.data 就是user对象可以继续操作
            
          },res=>{
            tip.error(res.msg)
          })
        },res=>{
          tip.error(res.msg||"");
        })
      }
    },

体验地址

本文所有应用体验地址如下

互联网行业解决方案吧https://idea.techidea8.com/open/idea.shtml?id=5

关于代码

代码获得地址

小程序码登陆

总结

以上所述是小编给大家介绍的通过扫小程序码实现网站登陆功能,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!
如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!

Javascript 相关文章推荐
JavaScript游戏之是男人就下100层代码打包
Nov 08 Javascript
Jquery阻止事件冒泡 event.stopPropagation
Dec 11 Javascript
jquery ajax同步异步的执行最终解决方案
Apr 26 Javascript
利用jQuery及AJAX技术定时更新GridView的某一列数据
Dec 04 Javascript
Javascript 字符串模板的简单实现
Feb 13 Javascript
JavaScript的String字符串对象常用操作总结
May 26 Javascript
BootStrap 实现各种样式的进度条效果
Dec 07 Javascript
浅谈AngularJs 双向绑定原理(数据绑定机制)
Dec 07 Javascript
微信小程序网络层封装的实现(promise, 登录锁)
May 08 Javascript
原生js实现无缝轮播图
Jan 11 Javascript
js HTML DOM EventListener功能与用法实例分析
Apr 27 Javascript
uniapp 微信小程序 自定义tabBar 导航
Apr 22 Javascript
vue中实现上传文件给后台实例详解
Aug 22 #Javascript
js的新生代垃圾回收知识点总结
Aug 22 #Javascript
JS实现移动端在线签协议功能
Aug 22 #Javascript
jQuery表单选择器用法详解
Aug 22 #jQuery
node实现简单的增删改查接口实例代码
Aug 22 #Javascript
微信小程序实现上传图片裁剪图片过程解析
Aug 22 #Javascript
ES6基础之 Promise 对象用法实例详解
Aug 22 #Javascript
You might like
php截取中文字符串不乱码的方法
2013/12/25 PHP
PHP微信支付实例解析
2016/07/22 PHP
php+ajax实现无刷新文件上传功能(ajaxuploadfile)
2018/02/11 PHP
PHP面向对象五大原则之单一职责原则(SRP)详解
2018/04/04 PHP
Aster vs KG BO3 第一场2.18
2021/03/10 DOTA
jquery $.getJSON()跨域请求
2011/12/21 Javascript
让人蛋疼的JavaScript语法特性
2014/09/30 Javascript
Javascript 字符串模板的简单实现
2016/02/13 Javascript
理解javascript封装
2016/02/23 Javascript
BootStrap智能表单实战系列(四)表单布局介绍
2016/06/13 Javascript
js时间查询插件使用详解
2017/04/07 Javascript
微信小程序新手教程之启动页的重要性
2019/03/03 Javascript
一篇文章弄懂javascript中的执行栈与执行上下文
2019/08/09 Javascript
js实现滚动条自动滚动
2020/12/13 Javascript
Python中zip()函数用法实例教程
2014/07/31 Python
Django使用HttpResponse返回图片并显示的方法
2018/05/22 Python
django传值给模板, 再用JS接收并进行操作的实例
2018/05/28 Python
numpy判断数值类型、过滤出数值型数据的方法
2018/06/09 Python
详解Django的model查询操作与查询性能优化
2018/10/16 Python
python3使用matplotlib绘制条形图
2020/03/25 Python
用python给自己做一款小说阅读器过程详解
2019/07/11 Python
Python3+PyInstall+Sciter解决报错缺少dll、html等文件问题
2019/07/15 Python
pytorch 共享参数的示例
2019/08/17 Python
python绘制封闭多边形教程
2020/02/18 Python
css3加js做一个简单的3D行星运转效果实例代码
2017/01/18 HTML / CSS
HTML5 Canvas绘制文本及图片的基础教程
2016/03/14 HTML / CSS
预订奥兰多和佛罗里达州公园门票:FloridaTix
2018/01/03 全球购物
Notino法国:购买香水和化妆品
2019/04/15 全球购物
编辑找工作求职信分享
2014/01/03 职场文书
大专生毕业的自我评价
2014/02/06 职场文书
教师专业自荐书范文
2014/02/10 职场文书
英语演讲稿3分钟
2014/04/29 职场文书
优秀党员自我评价范文
2014/09/15 职场文书
如何将JavaScript将数组转为树形结构
2021/06/02 Javascript
python3操作redis实现List列表实例
2021/08/04 Python
Spring Security动态权限的实现方法详解
2022/06/16 Java/Android