1. 程式人生 > >掃碼登入 簡單實現

掃碼登入 簡單實現

簡單原理是 伺服器生成唯一的 key  附帶到login 上
使用者掃描 二維碼 並且訪問伺服器 伺服器反饋登入  狀態
前端 頁面 每隔一段時間掃描 伺服器 當前的key是否掃描, 然後後續操作

程式碼:

package main

import (
	"fmt"
	"io"
	"math/rand"
	"net/http"
	"time"

	. "github.com/soekchl/myUtils"
)

const file = `
<!DOCTYPE html>
<html lang="zh-ch">

<head>
  <meta charset="UTF-8">
  <title>掃碼</title>
</head>

<body>
 <br>

   <p>掃碼登入</p>
   <img id="keyImage" src="http://qr.liantu.com/api.php?text=%v" alt="My Eth Address" title="My ETH Address">



  <br>
  <br>
</body>
<script>


 setInterval("checkLogin()","1000");

  function checkLogin() {
    var xhr = ajaxFunction();
    xhr.onreadystatechange = function () {
      if (xhr.readyState === 4) {
        if (xhr.status == 200) {
          // 解析 資料欄位 按照js的名稱來給
          console.log(xhr.responseText, keyImage.src.slice(67,123))
          if (+xhr.responseText === 1) {
            alert('登入成功')
            location.reload()
          } else {
//            alert('Server Error!...')
          }

        }
      }
    }
    xhr.open("get", "http://10.0.82.88:8080/checkLogin?key="+keyImage.src.slice(67,123), true);
    xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded','Access-Control-Allow-Origin', '*');
        xhr.send("");
  }

  function ajaxFunction() {
    let xmlHttp;
    try { // Firefox, Opera 8.0+, Safari
      xmlHttp = new XMLHttpRequest();
    } catch (e) {
      try { // Internet Explorer
        xmlHttp = new ActiveXObject("Msxml2.XMLHTTP");
      } catch (e) {
        try {
          xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
        } catch (e) { }
      }
    }
    return xmlHttp;
  }
</script>

</html>
`

var (
	keyMap = make(map[string]int)
)

func HelloServer(w http.ResponseWriter, req *http.Request) {
	rand.Seed(time.Now().UnixNano())
	r := rand.Int()
	keyMap[fmt.Sprint(r)] = 1
	url := fmt.Sprint("http://10.0.82.88:8080/login?key=", r)
	Notice(url)
	io.WriteString(w, fmt.Sprintf(file, url))
}

func main() {
	http.HandleFunc("/", HelloServer)
	http.HandleFunc("/login", login)
	http.HandleFunc("/checkLogin", checkLogin)

	Notice("Server Start!")
	err := http.ListenAndServe(":8080", nil)
	if err != nil {
		panic("ListenAndServe: " + err.Error())
	}
}

func login(w http.ResponseWriter, req *http.Request) {
	key := req.FormValue("key")
	if keyMap[key] == 1 {
		Notice("login ok ", key)
		io.WriteString(w, fmt.Sprintf("<script> alert('%v 登入成功')</script>", key))
		Notice(len(key))
		keyMap[key] = 2
	} else {
		Notice("login ", key)
		io.WriteString(w, fmt.Sprintf("<script> alert('登入失敗') </script>"))
	}

}

func checkLogin(w http.ResponseWriter, req *http.Request) {
	key := req.FormValue("key")
	if keyMap[key] == 2 {
		Debug("checkLogin ok ", key)
		io.WriteString(w, "1") // 登入成功
	} else {
		io.WriteString(w, "0")
	}
}

這個東東弊端是 key 隨處可見,只是用於 學習,用在商務的話 需要慎重!!!