微信QQ的二维码登录原理js代码解析
具有一定的参考价值,感兴趣的小伙伴们可以参考一下
在很多地方就是都出现了使用二维码登录,二维码付款,二维码账户等应用(这里的二维码种马,诈骗就不说了),
二维码验证,多终端辅助授权应用开始多起来,这里先说下啥是二维码,其实二维码就是存了二进制数据的黑白图片,
当出现要求二维码登录的时候,服务器会生成一条临时的唯一的二维码信息,发送到客户端以二维码(图片)的形式写入到网页,
然后你就会看到统一的四个方形的二维码,如果做的好这个二维码信息应该是有时效的,这里暂且不考虑这些,
就简单的微信登录作为例子看看吧:
首先说下整个授权流程:
在客户端网页中会不断向服务器发送https连接,并且这里传输很少的数据之后就断开连接了,下面看下微信网页中这个login1c709c.js文件:
(function($, _aoWin) { _aoWin.QRLogin = {}; _aoWin.LoginLog = ""; var _sBaseHost = "", _oLoginQrCodeImg = document.getElementById("loginQrCode"); if (document.domain == "qq.com") { _sBaseHost = "weixin.qq.com"; } else if(location.hostname.match(/(wechat\.com)$/)){ _sBaseHost = "wechat.com"; }else{ _sBaseHost = "wechatapp.com"; } var show_tip = 1, _sCurUUId, _oResetTimeout, _aWebMMCallbacks = [], _oDetactWebMMInterval = setInterval(function(){ if(_aoWin.WebMM){ clearInterval(_oDetactWebMMInterval); var callback; while(callback = _aWebMMCallbacks.shift()){ if(typeof(callback) != "function") continue; callback(); } } }, 1000); function _logInPage(_asLog){ _aoWin.LoginLog = LoginLog + _asLog + "\n"; } function _afterLoadWebMMDo(callback){ if(!_aoWin.WebMM){ _aWebMMCallbacks.push(callback); }else{ callback(); } } function _reportNow(text){ _logInPage(text); _afterLoadWebMMDo(function(){ WebMM.ossLog({Text: text}); WebMM.flushOssLog(); }); } var reLoadQRImgCount = 0, loadQRCodeTime = 0, loadQRImgSucc = function(){ clearInterval(loadQRImgWatchDog); _logInPage("Load QRCode Success, time=" + (new Date().getTime() - loadQRCodeTime) + "ms, reload count: " + reLoadQRImgCount); }, loadQRImgFail = function(img){ _reportNow("Load QRcode fail!" + status + ", src: " + img.src + ", time: " + (new Date().getTime() - loadQRCodeTime) + "ms"); }, loadQRImgWatchDog = null; function _loadQRImg(uuid) { _poll(uuid); _logInPage("Load QRCode Start"); loadQRCodeTime = new Date().getTime(); _oLoginQrCodeImg.onload = function(){ loadQRImgSucc(); _oLoginQrCodeImg.onload = null; }; _oLoginQrCodeImg.onerror = function(){loadQRImgFail(this)}; _oLoginQrCodeImg.src = "https://login."+_sBaseHost+"/qrcode/"+uuid+"?t=webwx"; loadQRImgWatchDog = setInterval(function(){ if (reLoadQRImgCount >= 5) { _reset(); return; } reLoadQRImgCount++; var _img = new Image(); _img.onload = function () { if(!_oLoginQrCodeImg.onload) return; _oLoginQrCodeImg.onload = null; _oLoginQrCodeImg.src = this.src;//replace loadQRImgSucc(); }; _img.onerror = function(){loadQRImgFail(this)}; _img.src = _oLoginQrCodeImg.src + "&r=" + new Date().getTime(); }, 5000); } var _sSecondRequestTime = 0, _nAjaxTimeout = 100 * 1000, _nNewLoginFuncErrCount = 0; function _poll(_asUUID) { var _self = arguments.callee, _nTime = 0; _sCurUUId = _asUUID; _logInPage("_poll Request Start, time: " + new Date().getTime()); _nTime = new Date().getTime(); $.ajax({ type: "GET", url: "https://login." + _sBaseHost + "/cgi-bin/mmwebwx-bin/login?uuid=" + _asUUID + "&tip=" + show_tip, dataType: "script", cache: false, timeout: _nAjaxTimeout, success: function(data, textStatus, jqXHR) { _logInPage("_poll Request Success, code: " + window.code + ", time: " + (new Date().getTime() - _nTime) + "ms"); switch (_aoWin.code) { case 200: _sSecondRequestTime = new Date().getTime() - _sSecondRequestTime; _logInPage("Second Request Success, time: " + _sSecondRequestTime + "ms"); clearTimeout(_oResetTimeout); var _fNewLoginFunc = function(){ $.ajax({ url: _aoWin.redirect_uri + "&fun=new",//new login page type: "GET", success:function(msg) { _logInPage("new func reponse, reponseMsg: " + msg); var code = msg.match(/<script>(.*)<\/script>/); var skey=msg.match(/<skey>(.*)<\/skey>/); if(code){ eval(code[1]); }else{ $("#container").show(); $("#login_container").hide(); } if(skey && skey[1]){ WebMM.model("account").setSkey(skey[1]); } }, error:function(jqXHR, textStatus, errorThrown){ _nNewLoginFuncErrCount++; if(_nNewLoginFuncErrCount > 5){ if(confirm("Call new login page func error, refresh?")){location.reload()} return; } _reportNow(_aoWin.redirect_uri + " New login page func error: " + textStatus +" retryCount:" + _nNewLoginFuncErrCount); setTimeout(_fNewLoginFunc, 500); } }); }; _fNewLoginFunc(); _reportNow("/cgi-bin/mmwebwx-bin/login, Second Request Success, uuid: " + _asUUID + ", time: " + _sSecondRequestTime + "ms"); break; case 201: clearTimeout(_oResetTimeout); show_tip = 0; $('.errorMsg').hide(); $('.normlDesc').hide(); $('.successMsg').show(); _reportNow("/cgi-bin/mmwebwx-bin/login, First Request Success, uuid: " + _asUUID); _reportNow("/cgi-bin/mmwebwx-bin/login, Second Request Start, uuid: " + _asUUID); _sSecondRequestTime = new Date().getTime(); //_nAjaxTimeout = 5 * 1000; _self(_asUUID); break; case 408: setTimeout(function(){ _self(_asUUID); }, 500); break; case 400: case 500: _reset(); _afterLoadWebMMDo(function(){ _aoWin.Log.d("500, Login Poll Svr Exception"); }); break; } }, error: function(jqXHR, textStatus, errorThrown) { if (textStatus == 'timeout') { setTimeout(function(){ _self(_asUUID); }, 500); } else { setTimeout(function(){ _self(_asUUID); }, 5000); _logInPage("_poll Request Error:" + textStatus); _afterLoadWebMMDo(function(){ _aoWin.Log.e("Login Poll Error:" + textStatus); }); } } }); } var getUUIDCount = 0, _getUUIDWatchDog, _bGetUUIDSuccess = false;//ajax successִ function _getUUID() { getUUIDCount++; var _self = arguments.callee, _loadError = function(errorText){ _reportNow("Load UUID Error! ErrorText: " + errorText + " getUUIDCount=" + getUUIDCount); if(getUUIDCount > 5){ if (confirm("Load uuid error. Refresh?")) { location.reload(); } } setTimeout(function(){ _self(); }, 500); }; clearTimeout(_getUUIDWatchDog); _getUUIDWatchDog = setTimeout(function(){ if(!_aoWin.QRLogin.code){ _logInPage("GetUUID Timeout, WatchDog Run"); _self(); } }, 10000); $.ajax({ type: "GET", url: "https://login." + _sBaseHost + "/jslogin?appid=wx782c26e4c19acffb&redirect_uri="+encodeURIComponent(location.protocol+"//"+location.host+"/cgi-bin/mmwebwx-bin/webwxnewloginpage")+"&fun=new&lang=" + document.lang, dataType: "script", cache: false, success : function(){ clearTimeout(_getUUIDWatchDog); if(_bGetUUIDSuccess) return; if (_aoWin.QRLogin && _aoWin.QRLogin.code == 200) { _logInPage("GetUUID Success, UUID=" + QRLogin.uuid); _bGetUUIDSuccess = true; clearTimeout(_oResetTimeout); _oResetTimeout = setTimeout(function(){ location.reload();//Note: Don't run _reset(). If you run _reset(), there will may have many _poll request, as they get 408 return code }, 5 * 60 *1000);//5 mins _loadQRImg(QRLogin.uuid); } else { var QRLoginCode = (_aoWin.QRLogin && _aoWin.QRLogin.code) ? _aoWin.QRLogin.code : "None"; _logInPage("GetUUID Error, QRLogin.code=" + QRLoginCode); _loadError("QRLogin.code= " + QRLoginCode); } }, error : function(xhr, textStatus, errorThrown){ _logInPage("GetUUID Error, textStatus=" + textStatus); _loadError(textStatus); } }); } function _reset(){ location.reload(); } if ($("#login_container").is(":visible") ) { _getUUID(); } var _bHadLog = false; function _ossLog() { if (_bHadLog) return; _bHadLog = true; var _sUvid = document.cookie.match(new RegExp( "(^| )"+"webwxuvid"+"=([^;]*)(;|$)")); if(!_sUvid || _sUvid.length < 3) return; _sUvid = _sUvid[2]; (new Image()).src = "/cgi-bin/mmwebwx-bin/webwxstatreport?funkey=indexdemo&uvid="+_sUvid+"&uuid="+_sCurUUId; } if($("img.guide").length > 0) { var _nTimer = 0, _oGuide$ = $(".guide"), _oGuideTrigger$ = $("#guideTrigger, #tipTrigger"), _oMask$ = $(".mask"); function _back() { _nTimer = setTimeout(function() { _oMask$.stop().animate({opacity:0}, function(){$(".mask").hide()}); _oGuide$.stop().animate({marginLeft:"-120px",opacity:0}, "400", "swing",function(){ _oGuide$.hide(); }); }, 100); } /*guide*/ _oGuide$.css({"left":"50%", "opacity":0}); _oGuideTrigger$.css({"backgroundColor":"white", "opacity":"0"}); _oGuideTrigger$.mouseover(function(){ clearTimeout(_nTimer); _oMask$.show().stop().animate({"opacity":0.2}); _oGuide$.css("display", "block").stop().animate({marginLeft:"+168px", opacity:1}, 900, "swing", function() { _oGuide$.animate({marginLeft:"+153px"}, 300); }); _ossLog(); }).mouseout(_back); _oGuide$.mouseover(function(){ clearTimeout(_nTimer); }).mouseout(_back); }
})(jQuery, window);
细读js之后,你就会从网页客户端这边看到请求登录的一面,网页客户端每隔500毫秒就向服务器发起ssl请求,请求当前的二维码是否被其他客户端(手机)授权,如果返回结果是201,就是说明已经获取扫描二维码终端相同的账号登录授权,如果是其他情况就再隔500毫秒再循环发请求。这个过程会一直持续到二维码被扫描通过或者二维码超时(失效)为止。
其中使用的工具有: 抓包工具 Fidller ,Chrome F12开发人员工具,注意偶然的发现,微信的客户端有一个min-webmm1cba21.js ,其中清晰可见的XSS filter规范, 这对于那些喜欢白盒测试XSS的鸽子又有希望拿Q仔了!!!
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多支持Myblog。
原文地址:http://www.jb51.net/article/87250.htm
具有一定的参考价值,感兴趣的小伙伴们可以参考一下
在很多地方就是都出现了使用二维码登录,二维码付款,二维码账户等应用(这里的二维码种马,诈骗就不说了),
二维码验证,多终端辅助授权应用开始多起来,这里先说下啥是二维码,其实二维码就是存了二进制数据的黑白图片,
当出现要求二维码登录的时候,服务器会生成一条临时的唯一的二维码信息,发送到客户端以二维码(图片)的形式写入到网页,
然后你就会看到统一的四个方形的二维码,如果做的好这个二维码信息应该是有时效的,这里暂且不考虑这些,
就简单的微信登录作为例子看看吧:
首先说下整个授权流程:
在客户端网页中会不断向服务器发送https连接,并且这里传输很少的数据之后就断开连接了,下面看下微信网页中这个login1c709c.js文件:
- (function($, _aoWin) {
- _aoWin.QRLogin = {};
- _aoWin.LoginLog = "";
- var _sBaseHost = "",
- _oLoginQrCodeImg = document.getElementById("loginQrCode");
- if (document.domain == "qq.com") {
- _sBaseHost = "weixin.qq.com";
- } else if(location.hostname.match(/(wechat\.com)$/)){
- _sBaseHost = "wechat.com";
- }else{
- _sBaseHost = "wechatapp.com";
- }
- var show_tip = 1,
- _sCurUUId,
- _oResetTimeout,
- _aWebMMCallbacks = [],
- _oDetactWebMMInterval = setInterval(function(){
- if(_aoWin.WebMM){
- clearInterval(_oDetactWebMMInterval);
- var callback;
- while(callback = _aWebMMCallbacks.shift()){
- if(typeof(callback) != "function") continue;
- callback();
- }
- }
- }, 1000);
- function _logInPage(_asLog){
- _aoWin.LoginLog = LoginLog + _asLog + "\n";
- }
- function _afterLoadWebMMDo(callback){
- if(!_aoWin.WebMM){
- _aWebMMCallbacks.push(callback);
- }else{
- callback();
- }
- }
- function _reportNow(text){
- _logInPage(text);
- _afterLoadWebMMDo(function(){
- WebMM.ossLog({Text: text});
- WebMM.flushOssLog();
- });
- }
- var reLoadQRImgCount = 0,
- loadQRCodeTime = 0,
- loadQRImgSucc = function(){
- clearInterval(loadQRImgWatchDog);
- _logInPage("Load QRCode Success, time=" + (new Date().getTime() - loadQRCodeTime) + "ms, reload count: " + reLoadQRImgCount);
- },
- loadQRImgFail = function(img){
- _reportNow("Load QRcode fail!" + status + ", src: " + img.src + ", time: " + (new Date().getTime() - loadQRCodeTime) + "ms");
- },
- loadQRImgWatchDog = null;
- function _loadQRImg(uuid) {
- _poll(uuid);
- _logInPage("Load QRCode Start");
- loadQRCodeTime = new Date().getTime();
- _oLoginQrCodeImg.onload = function(){
- loadQRImgSucc();
- _oLoginQrCodeImg.onload = null;
- };
- _oLoginQrCodeImg.onerror = function(){loadQRImgFail(this)};
- _oLoginQrCodeImg.src = "https://login."+_sBaseHost+"/qrcode/"+uuid+"?t=webwx";
- loadQRImgWatchDog = setInterval(function(){
- if (reLoadQRImgCount >= 5) {
- _reset();
- return;
- }
- reLoadQRImgCount++;
- var _img = new Image();
- _img.onload = function () {
- if(!_oLoginQrCodeImg.onload) return;
- _oLoginQrCodeImg.onload = null;
- _oLoginQrCodeImg.src = this.src;//replace
- loadQRImgSucc();
- };
- _img.onerror = function(){loadQRImgFail(this)};
- _img.src = _oLoginQrCodeImg.src + "&r=" + new Date().getTime();
- }, 5000);
- }
- var _sSecondRequestTime = 0,
- _nAjaxTimeout = 100 * 1000,
- _nNewLoginFuncErrCount = 0;
- function _poll(_asUUID) {
- var _self = arguments.callee,
- _nTime = 0;
- _sCurUUId = _asUUID;
- _logInPage("_poll Request Start, time: " + new Date().getTime());
- _nTime = new Date().getTime();
- $.ajax({
- type: "GET",
- url: "https://login." + _sBaseHost + "/cgi-bin/mmwebwx-bin/login?uuid=" + _asUUID + "&tip=" + show_tip,
- dataType: "script",
- cache: false,
- timeout: _nAjaxTimeout,
- success: function(data, textStatus, jqXHR) {
- _logInPage("_poll Request Success, code: " + window.code + ", time: " + (new Date().getTime() - _nTime) + "ms");
- switch (_aoWin.code) {
- case 200:
- _sSecondRequestTime = new Date().getTime() - _sSecondRequestTime;
- _logInPage("Second Request Success, time: " + _sSecondRequestTime + "ms");
- clearTimeout(_oResetTimeout);
- var _fNewLoginFunc = function(){
- $.ajax({
- url: _aoWin.redirect_uri + "&fun=new",//new login page
- type: "GET",
- success:function(msg) {
- _logInPage("new func reponse, reponseMsg: " + msg);
- var code = msg.match(/<script>(.*)<\/script>/);
- var skey=msg.match(/<skey>(.*)<\/skey>/);
- if(code){
- eval(code[1]);
- }else{
- $("#container").show();
- $("#login_container").hide();
- }
- if(skey && skey[1]){
- WebMM.model("account").setSkey(skey[1]);
- }
- },
- error:function(jqXHR, textStatus, errorThrown){
- _nNewLoginFuncErrCount++;
- if(_nNewLoginFuncErrCount > 5){
- if(confirm("Call new login page func error, refresh?")){location.reload()}
- return;
- }
- _reportNow(_aoWin.redirect_uri + " New login page func error: " + textStatus +" retryCount:" + _nNewLoginFuncErrCount);
- setTimeout(_fNewLoginFunc, 500);
- }
- });
- };
- _fNewLoginFunc();
- _reportNow("/cgi-bin/mmwebwx-bin/login, Second Request Success, uuid: " + _asUUID + ", time: " + _sSecondRequestTime + "ms");
- break;
- case 201:
- clearTimeout(_oResetTimeout);
- show_tip = 0;
- $('.errorMsg').hide();
- $('.normlDesc').hide();
- $('.successMsg').show();
- _reportNow("/cgi-bin/mmwebwx-bin/login, First Request Success, uuid: " + _asUUID);
- _reportNow("/cgi-bin/mmwebwx-bin/login, Second Request Start, uuid: " + _asUUID);
- _sSecondRequestTime = new Date().getTime();
- //_nAjaxTimeout = 5 * 1000;
- _self(_asUUID);
- break;
- case 408:
- setTimeout(function(){
- _self(_asUUID);
- }, 500);
- break;
- case 400:
- case 500:
- _reset();
- _afterLoadWebMMDo(function(){
- _aoWin.Log.d("500, Login Poll Svr Exception");
- });
- break;
- }
- },
- error: function(jqXHR, textStatus, errorThrown) {
- if (textStatus == 'timeout') {
- setTimeout(function(){
- _self(_asUUID);
- }, 500);
- } else {
- setTimeout(function(){
- _self(_asUUID);
- }, 5000);
- _logInPage("_poll Request Error:" + textStatus);
- _afterLoadWebMMDo(function(){
- _aoWin.Log.e("Login Poll Error:" + textStatus);
- });
- }
- }
- });
- }
- var getUUIDCount = 0,
- _getUUIDWatchDog,
- _bGetUUIDSuccess = false;//ajax successִ
- function _getUUID() {
- getUUIDCount++;
- var _self = arguments.callee,
- _loadError = function(errorText){
- _reportNow("Load UUID Error! ErrorText: " + errorText + " getUUIDCount=" + getUUIDCount);
- if(getUUIDCount > 5){
- if (confirm("Load uuid error. Refresh?")) {
- location.reload();
- }
- }
- setTimeout(function(){
- _self();
- }, 500);
- };
- clearTimeout(_getUUIDWatchDog);
- _getUUIDWatchDog = setTimeout(function(){
- if(!_aoWin.QRLogin.code){
- _logInPage("GetUUID Timeout, WatchDog Run");
- _self();
- }
- }, 10000);
- $.ajax({
- type: "GET",
- url: "https://login." + _sBaseHost + "/jslogin?appid=wx782c26e4c19acffb&redirect_uri="+encodeURIComponent(location.protocol+"//"+location.host+"/cgi-bin/mmwebwx-bin/webwxnewloginpage")+"&fun=new&lang=" + document.lang,
- dataType: "script",
- cache: false,
- success : function(){
- clearTimeout(_getUUIDWatchDog);
- if(_bGetUUIDSuccess) return;
- if (_aoWin.QRLogin && _aoWin.QRLogin.code == 200) {
- _logInPage("GetUUID Success, UUID=" + QRLogin.uuid);
- _bGetUUIDSuccess = true;
- clearTimeout(_oResetTimeout);
- _oResetTimeout = setTimeout(function(){
- location.reload();//Note: Don't run _reset(). If you run _reset(), there will may have many _poll request, as they get 408 return code
- }, 5 * 60 *1000);//5 mins
- _loadQRImg(QRLogin.uuid);
- } else {
- var QRLoginCode = (_aoWin.QRLogin && _aoWin.QRLogin.code) ? _aoWin.QRLogin.code : "None";
- _logInPage("GetUUID Error, QRLogin.code=" + QRLoginCode);
- _loadError("QRLogin.code= " + QRLoginCode);
- }
- },
- error : function(xhr, textStatus, errorThrown){
- _logInPage("GetUUID Error, textStatus=" + textStatus);
- _loadError(textStatus);
- }
- });
- }
- function _reset(){
- location.reload();
- }
- if ($("#login_container").is(":visible") ) {
- _getUUID();
- }
- var _bHadLog = false;
- function _ossLog() {
- if (_bHadLog) return;
- _bHadLog = true;
- var _sUvid = document.cookie.match(new RegExp( "(^| )"+"webwxuvid"+"=([^;]*)(;|$)"));
- if(!_sUvid || _sUvid.length < 3) return;
- _sUvid = _sUvid[2];
- (new Image()).src = "/cgi-bin/mmwebwx-bin/webwxstatreport?funkey=indexdemo&uvid="+_sUvid+"&uuid="+_sCurUUId;
- }
- if($("img.guide").length > 0) {
- var _nTimer = 0,
- _oGuide$ = $(".guide"),
- _oGuideTrigger$ = $("#guideTrigger, #tipTrigger"),
- _oMask$ = $(".mask");
- function _back() {
- _nTimer = setTimeout(function() {
- _oMask$.stop().animate({opacity:0}, function(){$(".mask").hide()});
- _oGuide$.stop().animate({marginLeft:"-120px",opacity:0}, "400", "swing",function(){
- _oGuide$.hide();
- });
- }, 100);
- }
- /*guide*/
- _oGuide$.css({"left":"50%", "opacity":0});
- _oGuideTrigger$.css({"backgroundColor":"white", "opacity":"0"});
- _oGuideTrigger$.mouseover(function(){
- clearTimeout(_nTimer);
- _oMask$.show().stop().animate({"opacity":0.2});
- _oGuide$.css("display", "block").stop().animate({marginLeft:"+168px", opacity:1}, 900, "swing", function() {
- _oGuide$.animate({marginLeft:"+153px"}, 300);
- });
- _ossLog();
- }).mouseout(_back);
- _oGuide$.mouseover(function(){
- clearTimeout(_nTimer);
- }).mouseout(_back);
- }
- })(jQuery, window);
细读js之后,你就会从网页客户端这边看到请求登录的一面,网页客户端每隔500毫秒就向服务器发起ssl请求,请求当前的二维码是否被其他客户端(手机)授权,如果返回结果是201,就是说明已经获取扫描二维码终端相同的账号登录授权,如果是其他情况就再隔500毫秒再循环发请求。这个过程会一直持续到二维码被扫描通过或者二维码超时(失效)为止。
其中使用的工具有: 抓包工具 Fidller ,Chrome F12开发人员工具,注意偶然的发现,微信的客户端有一个min-webmm1cba21.js ,其中清晰可见的XSS filter规范, 这对于那些喜欢白盒测试XSS的鸽子又有希望拿Q仔了!!!
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多支持Myblog。
原文地址:http://www.jb51.net/article/87250.htm
微信QQ的二维码登录原理js代码解析相关推荐
- 微信QQ的二维码登录原理浅析
在非常多地方就是都出现了使用二维码登录,二维码付款,二维码账户等应用(这里的二维码种马,诈骗就不说了),二维码验证,多终端辅助授权应用開始多起来,这里先说下啥是二维码,事实上二维码就是存了二进制数据的 ...
- 图示扫描二维码登录原理
想要了解手机端扫描二维码登录原理,首先我们要了解二维码和token认证机制两个内容,接下来我们将用图示的方法来直观感受这个面试时候的paper tiger. (第一次用visio画图,用熟练之后就感觉 ...
- 二维码登录原理及生成与解析
一.前言 这几天在研究二维码的扫码登录.初来乍到,还有好多东西不懂.在网上看到有人写了一些通过QRCode或者Zxing实现二维码的生成和解码.一时兴起,决定自己亲手试一试.本人是通过QRCode实现 ...
- 电脑版和手机版QQ都要手机版QQ扫描二维码登录?
是的,电脑版和手机版 QQ 都需要使用手机版 QQ 扫描二维码登录.这是因为扫描二维码登录是 QQ 的安全认证方式之一.
- QQ网页微信、QQ二维码登录原理分析(整理)
QQ和微信的登录过程中,使用二维码登录,这里根据网上的一些资料简单总结: 二维码是包含二进制数据的黑白图片.当进行登录时,服务器生成一条二维码信息,发送给PC客户端.这时,手机终端(已经存在指定账号登 ...
- Android安卓开发集成微信第三方扫描二维码登录-超级无敌具详细
Android安卓开发中集成微信二维码登录的步骤: 写在前面的: 该教程使用AS作为演示,使用ecplise请参照微信官方文档下载相应jar等所需参考文档和资源.在最后,我会附上这个Activity的 ...
- 形象理解二维码登录原理
之前在极客时间看到一个介绍二维码登录的原理,这里写篇文章记录一下.二维码是我们日常生活中随处可见,支付扫码,登录扫码,添加好友扫码,或者查看某些内容也需要扫码.今天分享一下二维码背后的技术和逻辑,并且 ...
- 二维码登录原理+Web端即时通讯技术
前言 上周在写项目过程中遇到需要实现二维码的登录功能,将这个过程细节记录下来 二维码的登录过程,主要难点在于用户扫码了浏览器展示的二维码,但是浏览器本身是无法知道的,需要服务端告知信息. 涉及到 we ...
- 二维码登录——原理区
2019独角兽企业重金招聘Python工程师标准>>> 1.PC端的逻辑 用户点击二维码按钮,向后台发送创建二维码的ajax异步请求,后台生成二维码后以二进制数据流的形式返回给前台, ...
最新文章
- js截取最后一个斜杠之后的内容
- spring ResponseEntity
- linux查看进程调用接口,查看某个程序都调用哪些api函数
- WPF、Windows Forms和Silverlight区别
- es中的高效文件读取方式
- 部署hexo后github pages页面未更新或无法打开问题
- 大数据Spark技术数据分析综合实验:出租车数据分析
- 电压传感器: 工作原理、类型及电路图
- 适用于protel99SE初学者
- 华硕电脑重装系统后电池管理软件ASUS Battery Health Charging不见了
- LeaRun快速开发平台,.Net Core加持,功能更全面
- 富贵论坛的来历和背景
- 名帖332 王献之 草书《鸭头丸帖》
- 大学生在线书籍网站 二手交易书籍网站制作 网页设计制作作业作品下载 dreamweaver制作静态html网页设计作业作品
- 【Error】西部数据磁盘插上不显示盘符
- vuex的state数据丢失
- 零中频接收机频率转换图_【新品情报站】俄罗斯产VisAir HF DDC/DUC SDR 收发信机视频|接收机|转换器|ddc|天线|调谐器...
- 雷达杂波matlab,基于MATLAB的雷达杂波建模与仿真研究
- EasyExcel报错com.alibaba.excel.exception.ExcelGenerateException: java.lang.ExceptionInInitializerError
- Java多线程——计算1-20阶乘和