Files
MirageToolServer/QRAuthCode.go
2023-02-23 10:51:48 +08:00

169 lines
3.8 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package main
import (
"crypto/rand"
"encoding/json"
"net/http"
"time"
"github.com/rs/zerolog/log"
)
type fetchQRRes struct {
Status string `json:"status"`
Code string `json:"code"`
}
// 由蜃境服务器拉取小程序码或者授权状态
func (tool *MirageTool) fetchQR(
w http.ResponseWriter,
r *http.Request,
) {
reqData := make(map[string]string)
json.NewDecoder(r.Body).Decode(&reqData)
if user, ok := tool.QRCache.Get(reqData["state"]); ok {
if user != nil { // 该state码已被扫码授权过
authCode := tool.GenAuthCode()
tool.AuthCodeCache.Set(authCode, user, 2*time.Minute)
res := fetchQRRes{
Status: "OK",
Code: authCode,
}
w.Header().Set("Content-Type", "application/json; charset=utf-8")
w.WriteHeader(http.StatusOK)
err := json.NewEncoder(w).Encode(&res)
if err != nil {
log.Error().
Caller().
Err(err).
Msg("Failed to write response")
}
return
}
// 该state码已拉取过二维码但未被扫码授权过
res := fetchQRRes{
Status: "Wait",
Code: "",
}
w.Header().Set("Content-Type", "application/json; charset=utf-8")
w.WriteHeader(http.StatusOK)
err := json.NewEncoder(w).Encode(&res)
if err != nil {
log.Error().
Caller().
Err(err).
Msg("Failed to write response")
}
return
}
// 该state码还未获取过二维码
miniQR := tool.genMiniProgramQR(reqData["state"])
if miniQR != "" {
// 需注意cache里以state为索引记录的是user信息而不进行二维码缓存
tool.QRCache.Set(reqData["state"], nil, 2*time.Minute)
res := fetchQRRes{
Status: "New",
Code: miniQR,
}
w.Header().Set("Content-Type", "application/json; charset=utf-8")
w.WriteHeader(http.StatusOK)
err := json.NewEncoder(w).Encode(&res)
if err != nil {
log.Error().
Caller().
Err(err).
Msg("Failed to write response")
}
return
}
res := fetchQRRes{
Status: "Error",
Code: "",
}
w.Header().Set("Content-Type", "application/json; charset=utf-8")
w.WriteHeader(http.StatusOK)
err := json.NewEncoder(w).Encode(&res)
if err != nil {
log.Error().
Caller().
Err(err).
Msg("Failed to write response")
}
return
}
type authQRRes struct {
Status string
}
// 小程序上用户完成授权确认
func (tool *MirageTool) authQR(
w http.ResponseWriter,
r *http.Request,
) {
reqData := make(map[string]string)
json.NewDecoder(r.Body).Decode(&reqData)
openID := tool.exchangeCodeToIDs(reqData["logincode"])
user := tool.GetUserByID(openID)
if user == nil {
res := authQRRes{
Status: "NoUser",
}
w.Header().Set("Content-Type", "application/json; charset=utf-8")
w.WriteHeader(http.StatusOK)
err := json.NewEncoder(w).Encode(&res)
if err != nil {
log.Error().
Caller().
Err(err).
Msg("Failed to write response")
}
return
}
stateCode := reqData["state"]
userInterface, expiration, ok := tool.QRCache.GetWithExpiration(stateCode)
if !ok || userInterface != nil {
res := authQRRes{
Status: "StateExpire",
}
w.Header().Set("Content-Type", "application/json; charset=utf-8")
w.WriteHeader(http.StatusOK)
err := json.NewEncoder(w).Encode(&res)
if err != nil {
log.Error().
Caller().
Err(err).
Msg("Failed to write response")
}
return
}
tool.QRCache.Set(stateCode, *user, expiration.Sub(time.Now()))
res := authQRRes{
Status: "OK",
}
w.Header().Set("Content-Type", "application/json; charset=utf-8")
w.WriteHeader(http.StatusOK)
err := json.NewEncoder(w).Encode(&res)
if err != nil {
log.Error().
Caller().
Err(err).
Msg("Failed to write response")
}
return
}
func (t *MirageTool) GenAuthCode() string {
const letterBytes = "_-0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
b := make([]byte, 64)
index := make([]byte, 64)
rand.Read(index)
for i := 0; i < 64; i++ {
b[i] = letterBytes[index[i]&63]
}
return string(b)
}