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


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 检测键盘按键信息及键码值对应介绍
Jan 03 Javascript
window.open关于浏览器拦截问题分析及解决方法
Feb 05 Javascript
JS实现一个按钮的方法
Feb 05 Javascript
浅谈javascript中onbeforeunload与onunload事件
Dec 10 Javascript
JS实现隐藏同级元素后只显示JS文件内容的方法
Sep 04 Javascript
将JSON字符串转换成Map对象的方法
Nov 30 Javascript
JS实现的五级联动菜单效果完整实例
Feb 23 Javascript
JS中跳出循环的示例代码
Sep 14 Javascript
解决Vue使用mint-ui loadmore实现上拉加载与下拉刷新出现一个页面使用多个上拉加载后冲突问题
Nov 07 Javascript
详解vue-admin和后端(flask)分离结合的例子
Feb 12 Javascript
Vue cli3 库模式搭建组件库并发布到 npm的流程
Oct 12 Javascript
layDate插件设置开始和结束时间
Nov 15 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/07/01 PHP
解析数组非数字键名引号的必要性
2013/08/09 PHP
php命令行用法入门实例教程
2014/10/27 PHP
php限制上传文件类型并保存上传文件的方法
2015/03/13 PHP
Laravel框架模型的创建及模型对数据操作示例
2019/05/07 PHP
ie 处理 gif动画 的onload 事件的一个 bug
2007/04/12 Javascript
JS无限树状列表实现代码
2011/01/11 Javascript
获取内联和链接中的样式(js代码)
2013/04/11 Javascript
jQuery/CSS3图片特效插件整理推荐
2014/12/07 Javascript
JS实现的通用表单验证插件完整实例
2015/08/20 Javascript
jquery层级选择器的实现(匹配后代元素div)
2016/09/05 Javascript
JavaScript中apply方法的应用技巧小结
2016/09/29 Javascript
微信小程序 location API实例详解
2016/10/02 Javascript
JS变量及其作用域
2017/03/29 Javascript
了解前端理论:rscss和rsjs
2019/05/23 Javascript
javascript实现切割轮播效果
2019/11/28 Javascript
js仿360开机效果
2019/12/26 Javascript
通过实例解析vuejs如何实现调试代码
2020/07/16 Javascript
python生成指定尺寸缩略图的示例
2014/05/07 Python
简单理解Python中的装饰器
2015/07/31 Python
python使用threading获取线程函数返回值的实现方法
2017/11/15 Python
python实现简单http服务器功能
2018/09/17 Python
python自带tkinter库实现棋盘覆盖图形界面
2019/07/17 Python
python实现大文本文件分割
2019/07/22 Python
Python 使用 Pillow 模块给图片添加文字水印的方法
2019/08/30 Python
python3 tkinter实现添加图片和文本
2019/11/26 Python
Python中itertools的用法详解
2020/02/07 Python
Python日期格式和字符串格式相互转换的方法
2020/02/18 Python
scrapy中如何设置应用cookies的方法(3种)
2020/09/22 Python
pytorch加载语音类自定义数据集的方法教程
2020/11/10 Python
美国美食礼品篮网站:Gourmet Gift Baskets
2019/12/15 全球购物
Pandora德国官网:购买潘多拉手链、戒指、项链和耳环
2020/02/20 全球购物
EJB3推出JPA的原因
2013/10/16 面试题
法院四风对照检查材料思想汇报
2014/10/06 职场文书
抢劫罪辩护词
2015/05/21 职场文书
教师节主题班会方案
2015/08/17 职场文书