自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

手寫一個仿微信登錄的Nodejs程序

網絡 通信技術
本篇教你手寫一個仿微信登錄的Nodejs程序,希望對你有所幫助。

[[357291]]

 前言

首先,我們看一下微信開放文檔中的一張圖:

上面的一幅圖中清楚地介紹了微信登錄整個過程,下面對圖上所示進行總結:

一、二維碼的獲得

  1. 用戶打開登錄網頁后,登錄網頁后臺根據(jù)微信OAuth2.0協(xié)議向微信開發(fā)平臺請求授權登錄,并傳遞事先在微信開發(fā)平臺中審核通過的AppID和AppSecrect等參數(shù);
  2. 微信開發(fā)平臺對AppID等參數(shù)進行驗證,并向登錄網頁后臺返回二維碼;
  3. 登錄網頁后臺將二維碼傳送至前臺進行顯示;

二、微信客戶端授權登錄

  1. 用戶使用微信客戶端掃描二維碼并授權登錄;
  2. 微信客戶端將二維碼特定的uid與微信賬號綁定,傳送至微信開發(fā)平臺;
  3. 微信開發(fā)平臺驗證綁定數(shù)據(jù),調用登錄網頁后臺的回調接口,發(fā)送授權臨時票據(jù)code;

三、網頁后臺請求數(shù)據(jù)

  1. 登錄網頁后臺接收到code,表明微信開發(fā)平臺同意數(shù)據(jù)請求;
  2. 登錄網頁后臺根據(jù)code參數(shù),再加上AppID和AppSecret請求微信開發(fā)平臺換取access_token;
  3. 微信開發(fā)平臺驗證參數(shù),并返回access_token;
  4. 登錄網頁后臺收到access_token后即可進行參數(shù)分析獲得用戶賬號數(shù)據(jù)。

實現(xiàn)

了解了大致原理之后,我們就開始簡單實現(xiàn)這個邏輯。因為沒有直接調用微信開發(fā)平臺,所以這里只是演示效果。你也可以通過訪問:

  1. https://www.maomin.club/qrcodelogin/ 

這個我的線上網址體驗一下。以下代碼是主要邏輯,結合線上網址體驗更容易理解。

  1. let http = require("http"); 
  2. let express = require("express"); 
  3. let qrcode = require("qr-image"); 
  4. let app = express(); 
  5. let path = require("path"); 
  6. let server = http.createServer(app); 
  7. let url = require("url"); 
  8. let fs = require("fs"); 
  9. let UUID = require("uuid-js"); 
  10. let generateHTML = null
  11.  
  12. app.use(express.static("./public")); 
  13.  
  14. /* 
  15.  * Description: 讀取網頁文件,用于替換關鍵字,相當于簡易模板 
  16.  * Params: 
  17.  * sessionID - 生成的uid 
  18.  * req - 網頁請求 
  19.  * res - 網頁應答 
  20.  * fileName - 網頁文件所在路徑 
  21.  */ 
  22. generateHTML = function (sessionID, req, res, fileName) { 
  23.   fs.readFile(fileName, "UTF-8"function (err, data) { 
  24.     if (!err) { 
  25.       data = data.replace(/SESSION_UID/g, sessionID); 
  26.       res.writeHead(200, { 
  27.         "Content-Type""text/html; charset=UTF-8"
  28.       }); 
  29.       res.end(data); 
  30.     } else { 
  31.       console.log(err); 
  32.  
  33.       res.writeHead(404, { 
  34.         "Content-Type""text/html; charset=UTF-8"
  35.       }); 
  36.       res.end(); 
  37.     } 
  38.   }); 
  39. }; 
  40.  
  41. /* 
  42.  * Description: 寫入JSON文件 
  43.  * Params: 
  44.  * fileName - JSON文件所在路徑 
  45.  * uid - 生成的uid 
  46.  * writeData - 需要寫入的JSON格式數(shù)據(jù) 
  47.  * 
  48.  */ 
  49. let setJSONValue = function (fileName, uid, writeData) { 
  50.   let data = fs.readFileSync(fileName); 
  51.  
  52.   let users = JSON.parse(data.toString()); 
  53.   let addFlag = true
  54.   let delFlag = writeData === null
  55.  
  56.   for (let i = 0; i < users.data.length; i++) { 
  57.     if (users.data[i].uid === uid) { 
  58.       addFlag = false
  59.  
  60.       if (delFlag) { 
  61.         users.data.splice(i, 1); 
  62.       } else { 
  63.         users.data[i].status = writeData.status; 
  64.  
  65.         console.log( 
  66.           "writeJSON: " + JSON.stringify(users.data[i]) + " modified." 
  67.         ); 
  68.       } 
  69.     } 
  70.   } 
  71.  
  72.   if (addFlag) { 
  73.     users.data.push(writeData); 
  74.     console.log("writeJSON: " + JSON.stringify(writeData) + " inserted."); 
  75.   } 
  76.  
  77.   // 同步寫入文件 
  78.   let writeJSON = JSON.stringify(users); 
  79.   fs.writeFileSync(fileName, writeJSON); 
  80. }; 
  81.  
  82. /* 
  83.  * Description: 讀取JSON文件(要返回數(shù)據(jù),選擇同步讀取) 
  84.  * Params: 
  85.  * fileName - JSON文件所在路徑 
  86.  * uid - 生成的uid 
  87.  * 
  88.  */ 
  89. getJSONValue = function (fileName, uid) { 
  90.   let readData = null
  91.  
  92.   // 同步讀取文件 
  93.   let data = fs.readFileSync(fileName); 
  94.  
  95.   let users = JSON.parse(data.toString()); 
  96.  
  97.   for (let i = 0; i < users.data.length; i++) { 
  98.     if (users.data[i].uid === uid) { 
  99.       readData = JSON.stringify(users.data[i]); 
  100.       break; 
  101.     } 
  102.   } 
  103.  
  104.   return readData; 
  105. }; 
  106.  
  107. // 顯示網站首頁 
  108. app.get("/"function (req, res) { 
  109.   // 生成唯一的ID 
  110.   let uid = UUID.create(); 
  111.   console.log("uid: '" + uid + "' generated."); 
  112.   // 替換網頁模板內的UID關鍵字 
  113.   generateHTML(uid, req, res, path.join(__dirname, "/views/main.html")); 
  114. }); 
  115.  
  116. // 生成二維碼圖片并顯示 
  117. app.get("/qrcode"function (req, res, next) { 
  118.   let uid = url.parse(req.url, true).query.uid; 
  119.  
  120.   try { 
  121.     if (typeof uid !== "undefined") { 
  122.       // 寫入二維碼內的網址,微信掃描后自動跳轉。下面的網址是我的網址,https://www.maomin.club/qrcodelogin ,你可以換成自己的線上網址或者本地服務器。加上后面的"/scanned?uid=" 
  123.       let jumpURL = "https://www.maomin.club/qrcodelogin/scanned?uid=" + uid; 
  124.       // 生成二維碼(size:圖片大小, margin: 邊框留白) 
  125.       let img = qrcode.image(jumpURL, { size: 6, margin: 2 }); 
  126.       res.writeHead(200, { "Content-Type""image/png" }); 
  127.       img.pipe(res); 
  128.     } else { 
  129.       res.writeHead(414, { "Content-Type""text/html" }); 
  130.       res.end("<h1>414 Request-URI Too Large</h1>"); 
  131.     } 
  132.   } catch (e) { 
  133.     res.writeHead(414, { "Content-Type""text/html" }); 
  134.     res.end("<h1>414 Request-URI Too Large</h1>"); 
  135.   } 
  136. }); 
  137.  
  138. // 顯示手機掃描后的確認界面 
  139. app.get("/scanned"function (req, res) { 
  140.   let uid = url.parse(req.url, true).query.uid; 
  141.  
  142.   if (typeof uid !== "undefined") { 
  143.     generateHTML(uid, req, res, path.join(__dirname, "/views/confirm.html")); 
  144.  
  145.     console.log("uid: '" + uid + "' scanned."); 
  146.  
  147.     // 獲取JSON文件內對應uid的數(shù)據(jù),更改其數(shù)據(jù)狀態(tài) 
  148.     let jsonData = getJSONValue(path.join(__dirname, "/bin/data.json"), uid); 
  149.  
  150.     if (jsonData === null) { 
  151.       jsonData = { 
  152.         uid: uid, 
  153.         status: "scanned"
  154.         name"USER"
  155.       }; 
  156.     } else { 
  157.       jsonData = JSON.parse(jsonData); 
  158.       jsonData.status = "scanned"
  159.     } 
  160.  
  161.     // 寫入JSON文件 
  162.     setJSONValue(path.join(__dirname, "/bin/data.json"), uid, jsonData); 
  163.   } else { 
  164.     res.writeHead(414, { "Content-Type""text/html" }); 
  165.     res.end("<h1>414 Request-URI Too Large</h1>"); 
  166.   } 
  167. }); 
  168.  
  169. // 在確認界面操作的響應 
  170. app.get("/confirmed"function (req, res) { 
  171.   let uid = url.parse(req.url, true).query.uid; 
  172.   let operate = url.parse(req.url, true).query.operate; 
  173.  
  174.   if (typeof uid !== "undefined") { 
  175.     console.log("uid: '" + uid + "' " + operate); 
  176.  
  177.     let jsonData = getJSONValue(path.join(__dirname, "/bin/data.json"), uid); 
  178.     let status = operate === "confirm" ? "verified" : "canceled"
  179.  
  180.     if (jsonData === null) { 
  181.       jsonData = { 
  182.         uid: uid, 
  183.         status: status, 
  184.         name"USER"
  185.       }; 
  186.     } else { 
  187.       jsonData = JSON.parse(jsonData); 
  188.       jsonData.status = status; 
  189.     } 
  190.  
  191.     setJSONValue(path.join(__dirname, "/bin/data.json"), uid, jsonData); 
  192.  
  193.     if (status === "verified") { 
  194.       res.writeHead(200, { "Content-Type""text/html" }); 
  195.       res.end("<h1 style='textAlign:center;'>登錄成功!</h1>"); 
  196.     } else { 
  197.       res.writeHead(200, { "Content-Type""text/html" }); 
  198.       res.end("<h1 style='textAlign:center;'>Canceled!</h1>"); 
  199.     } 
  200.   } else { 
  201.     res.writeHead(414, { "Content-Type""text/html" }); 
  202.     res.end("<h1 style='textAlign:center;'>414 Request-URI Too Large</h1>"); 
  203.   } 
  204. }); 
  205.  
  206. // 響應主頁不斷的AJAX請求 
  207. app.get("/verified"function (req, res) { 
  208.   let uid = url.parse(req.url, true).query.uid; 
  209.  
  210.   // normal   - 沒有任何觸發(fā) 
  211.   // scanned  - 已掃描 
  212.   // canceled - 已取消 
  213.   // verified - 已驗證 
  214.   let dataStatus = { 
  215.     cmd: "normal"
  216.     user""
  217.   }; 
  218.  
  219.   console.log("uid: '" + uid + "' query ..."); 
  220.  
  221.   if (typeof uid !== "undefined") { 
  222.     let userData = getJSONValue(path.join(__dirname, "/bin/data.json"), uid); 
  223.  
  224.     // 返回JSON數(shù)據(jù)用于首頁AJAX操作 
  225.     if (userData !== null) { 
  226.       userData = JSON.parse(userData); 
  227.       dataStatus.cmd = userData.status; 
  228.       dataStatus.user = userData.name
  229.     } 
  230.   } 
  231.  
  232.   res.end(JSON.stringify(dataStatus)); 
  233. }); 
  234.  
  235. server.listen(4000); 
  236. console.log( 
  237.   "Express server listening on port %d in %s mode"
  238.   server.address().port, 
  239.   app.settings.env 
  240. ); 

看到這里,你是不是覺得代碼不夠全,咋就給了一個主要邏輯代碼,別著急,代碼滿漢全席馬上奉上,代碼解釋可以看注釋哦!以下是github網址,如果覺得對自己有用,歡迎star~

  1. https://github.com/maomincoding/qrcodelogin.git 

結語

看到這里了,你可能直接拉取代碼,發(fā)現(xiàn)項目咋運行不了呢?效果也不跟線上網址那樣。是這樣的,如果你有線上服務器,可以把它部署到云端。如果沒有線上服務器,你可以自己搭建一個本地局域網服務器。一定要保證手機跟電腦網頁在一個IP網段上。

效果圖如下:

登錄網頁


登錄授權頁


 

責任編輯:姜華 來源: 前端歷劫之路
相關推薦

2016-09-30 09:22:55

2015-09-22 10:43:37

微信雷達

2012-12-24 13:25:59

微信App

2019-03-19 19:19:19

Facebook微信轉型

2016-02-15 11:47:54

微信源碼下拉視頻

2013-04-01 13:15:49

微信微信公眾賬號微信推廣

2015-08-07 15:39:26

仿微信語音界面源碼

2021-10-26 00:25:14

程序登錄流程

2021-03-04 11:50:48

微信Spring Secu登錄

2022-03-09 09:43:01

工具類線程項目

2022-10-31 08:27:53

Database數(shù)據(jù)數(shù)據(jù)庫

2021-02-22 17:17:38

Proxy緩存代碼

2021-01-29 18:02:52

企業(yè)微信私域流量

2015-09-01 16:55:42

微信朋友圈圖片

2020-11-02 08:19:18

RPC框架Java

2013-08-20 15:22:47

2013-08-19 15:00:53

微信易信

2021-03-18 08:04:54

AQS工具CAS

2021-12-07 06:55:17

節(jié)流函數(shù)Throttle

2021-11-23 10:00:55

鴻蒙HarmonyOS應用
點贊
收藏

51CTO技術棧公眾號