Support account management
CREATE TABLE "users" ( "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, "phone" TEXT, "password" TEXT, "autokey" TEXT, "ticket" TEXT, "userid" INTEGER, "last_login_time" INTEGER ); CREATE TABLE "user_key" ( "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, "userid" INTEGER, "key" INTEGER ); Signed-off-by: Yuan Si <do4suki@gmail.com>
This commit is contained in:
+39
-28
@@ -1,6 +1,7 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
@@ -13,6 +14,8 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
_ "github.com/mattn/go-sqlite3"
|
||||
"github.com/tidwall/gjson"
|
||||
)
|
||||
|
||||
func AuthKeyHandler(ctx *gin.Context) {
|
||||
@@ -74,36 +77,34 @@ func LoginHandler(ctx *gin.Context) {
|
||||
reqTime := time.Now().Unix()
|
||||
|
||||
authorizeStr := ctx.Request.Header["Authorize"]
|
||||
// authToken, err := utils.GetAuthorizeToken(authorizeStr)
|
||||
// if err != nil {
|
||||
// ctx.String(http.StatusForbidden, ErrorMsg)
|
||||
// return
|
||||
// }
|
||||
authToken, err := utils.GetAuthorizeToken(authorizeStr)
|
||||
if err != nil {
|
||||
ctx.String(http.StatusForbidden, ErrorMsg)
|
||||
return
|
||||
}
|
||||
|
||||
// authData, err := database.RedisCli.HGetAll(database.RedisCtx, authToken).Result()
|
||||
// authData, err := database.LevelDb.Get([]byte(authToken))
|
||||
// CheckErr(err)
|
||||
authData, err := database.LevelDb.Get([]byte(authToken))
|
||||
CheckErr(err)
|
||||
// fmt.Println(authData)
|
||||
|
||||
// clientToken, serverToken := authData["client_token"], authData["server_token"]
|
||||
// clientToken := gjson.Get(string(authData), "client_token").String()
|
||||
// serverToken := gjson.Get(string(authData), "server_token").String()
|
||||
// clientToken64, err := base64.RawStdEncoding.DecodeString(clientToken)
|
||||
// CheckErr(err)
|
||||
// serverToken64, err := base64.RawStdEncoding.DecodeString(serverToken)
|
||||
// CheckErr(err)
|
||||
clientToken := gjson.Get(string(authData), "client_token").String()
|
||||
serverToken := gjson.Get(string(authData), "server_token").String()
|
||||
clientToken64, err := base64.RawStdEncoding.DecodeString(clientToken)
|
||||
CheckErr(err)
|
||||
serverToken64, err := base64.RawStdEncoding.DecodeString(serverToken)
|
||||
CheckErr(err)
|
||||
|
||||
// xmcKey := utils.SliceXor([]byte(clientToken64), []byte(serverToken64))
|
||||
// aesKey := xmcKey[0:16]
|
||||
xmcKey := utils.SliceXor([]byte(clientToken64), []byte(serverToken64))
|
||||
aesKey := xmcKey[0:16]
|
||||
|
||||
loginReq := model.LoginReq{}
|
||||
err := json.Unmarshal([]byte(ctx.PostForm("request_data")), &loginReq)
|
||||
err = json.Unmarshal([]byte(ctx.PostForm("request_data")), &loginReq)
|
||||
CheckErr(err)
|
||||
key64, err := base64.StdEncoding.DecodeString(loginReq.LoginKey)
|
||||
CheckErr(err)
|
||||
// key64, err := base64.StdEncoding.DecodeString(loginReq.LoginKey)
|
||||
// CheckErr(err)
|
||||
// pass64, err := base64.StdEncoding.DecodeString(loginReq.LoginPasswd)
|
||||
// CheckErr(err)
|
||||
// keyDescrypted := utils.Sub16(encrypt.AES_CBC_Decrypt(key64, aesKey))
|
||||
keyDescrypted := utils.Sub16(encrypt.AES_CBC_Decrypt(key64, aesKey))
|
||||
// fmt.Println(string(keyDescrypted))
|
||||
// passDescrypted := utils.Sub16(encrypt.AES_CBC_Decrypt(pass64, aesKey))
|
||||
// fmt.Println(string(passDescrypted))
|
||||
@@ -116,16 +117,26 @@ func LoginHandler(ctx *gin.Context) {
|
||||
}
|
||||
nonce++
|
||||
|
||||
// userId, err := database.GetUid(string(keyDescrypted))
|
||||
// if err != nil {
|
||||
// ctx.String(http.StatusForbidden, ErrorMsg)
|
||||
// return
|
||||
// }
|
||||
userId := 9999999
|
||||
db, err := sql.Open("sqlite3", "assets/account.db")
|
||||
CheckErr(err)
|
||||
defer db.Close()
|
||||
|
||||
stmt, err := db.Prepare("SELECT userid FROM user_key WHERE key = ?")
|
||||
CheckErr(err)
|
||||
rows, err := stmt.Query(string(keyDescrypted))
|
||||
CheckErr(err)
|
||||
var userId int
|
||||
for rows.Next() {
|
||||
err = rows.Scan(&userId)
|
||||
CheckErr(err)
|
||||
}
|
||||
|
||||
if userId == 0 {
|
||||
userId = 9999999
|
||||
}
|
||||
sUserId := strconv.Itoa(userId)
|
||||
authorizeToken := utils.RandomBase64Token(32)
|
||||
|
||||
// _, err = database.RedisCli.HSet(database.RedisCtx, "token_uid", authorizeToken, userId).Result()
|
||||
err = database.LevelDb.Put([]byte(authorizeToken), []byte(sUserId))
|
||||
CheckErr(err)
|
||||
|
||||
|
||||
+231
-56
@@ -1,23 +1,62 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"honoka-chan/encrypt"
|
||||
"honoka-chan/utils"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/forgoer/openssl"
|
||||
"github.com/gin-gonic/gin"
|
||||
_ "github.com/mattn/go-sqlite3"
|
||||
)
|
||||
|
||||
var (
|
||||
randKey string
|
||||
)
|
||||
|
||||
type LoginResp struct {
|
||||
Activation int `json:"activation"`
|
||||
Autokey string `json:"autokey"`
|
||||
CaptchaParams string `json:"captchaParams"`
|
||||
CheckCodeGUID string `json:"checkCodeGuid"`
|
||||
CheckCodeURL string `json:"checkCodeUrl"`
|
||||
HasExtendAccs int `json:"hasExtendAccs"`
|
||||
HasRealInfo int `json:"has_realInfo"`
|
||||
ImagecodeType int `json:"imagecodeType"`
|
||||
IsNewUser int `json:"isNewUser"`
|
||||
Message string `json:"message"`
|
||||
NextAction int `json:"nextAction"`
|
||||
PromptMsg string `json:"prompt_msg"`
|
||||
RealInfoNotification string `json:"realInfoNotification"`
|
||||
RealInfoForce int `json:"realInfo_force"`
|
||||
RealInfoForcePay int `json:"realInfo_force_pay"`
|
||||
RealInfoStatus int `json:"realInfo_status"`
|
||||
RealInfoStatusPay int `json:"realInfo_status_pay"`
|
||||
Result int `json:"result"`
|
||||
SdgHeight int `json:"sdg_height"`
|
||||
SdgWidth int `json:"sdg_width"`
|
||||
Ticket string `json:"ticket"`
|
||||
UserAttribute string `json:"userAttribute"`
|
||||
Userid string `json:"userid"`
|
||||
}
|
||||
|
||||
type LoginAutoResp struct {
|
||||
Result int `json:"result"`
|
||||
Message string `json:"message"`
|
||||
Autokey string `json:"autokey"`
|
||||
Userid string `json:"userid"`
|
||||
Ticket string `json:"ticket"`
|
||||
}
|
||||
|
||||
func ActiveHandler(ctx *gin.Context) {
|
||||
ctx.Header("Content-Type", "text/html;charset=utf-8")
|
||||
ctx.String(http.StatusOK, `{ "code": 0, "msg": "ok", "data": { "message": "ok", "result": 0 } }`)
|
||||
@@ -132,27 +171,70 @@ func GetCodeHandler(ctx *gin.Context) {
|
||||
}
|
||||
|
||||
func LoginAutoHandler(ctx *gin.Context) {
|
||||
// body, err := io.ReadAll(ctx.Request.Body)
|
||||
// CheckErr(err)
|
||||
// defer ctx.Request.Body.Close()
|
||||
body, err := io.ReadAll(ctx.Request.Body)
|
||||
CheckErr(err)
|
||||
defer ctx.Request.Body.Close()
|
||||
// fmt.Println(string(body))
|
||||
|
||||
// body64, err := base64.StdEncoding.DecodeString(string(body))
|
||||
// CheckErr(err)
|
||||
body64, err := base64.StdEncoding.DecodeString(string(body))
|
||||
CheckErr(err)
|
||||
// fmt.Println(string(body64))
|
||||
|
||||
// decryptedBody, err := openssl.Des3ECBDecrypt(body64, []byte(randKey)[0:24], openssl.PKCS7_PADDING)
|
||||
// CheckErr(err)
|
||||
// fmt.Println(string(decryptedBody))
|
||||
|
||||
// Unable to decrypt server data
|
||||
token := `{"message":"Hello, world!"}`
|
||||
encryptedToken, err := openssl.Des3ECBEncrypt([]byte(token), []byte(randKey)[0:24], openssl.PKCS7_PADDING)
|
||||
decryptedBody, err := openssl.Des3ECBDecrypt(body64, []byte(randKey)[0:24], openssl.PKCS7_PADDING)
|
||||
CheckErr(err)
|
||||
encryptedToken64 := base64.StdEncoding.EncodeToString(encryptedToken)
|
||||
// fmt.Println(encryptedToken64)
|
||||
queryStr := string(decryptedBody)
|
||||
// fmt.Println(params)
|
||||
|
||||
resp := fmt.Sprintf(`{ "code": 0, "msg": "ok", "data": "%s" }`, encryptedToken64)
|
||||
params, err := url.ParseQuery(queryStr)
|
||||
CheckErr(err)
|
||||
autoKey := params.Get("autokey")
|
||||
// fmt.Println(autoKey)
|
||||
if autoKey == "" {
|
||||
ctx.String(http.StatusForbidden, ErrorMsg)
|
||||
return
|
||||
}
|
||||
|
||||
db, err := sql.Open("sqlite3", "assets/account.db")
|
||||
CheckErr(err)
|
||||
defer db.Close()
|
||||
|
||||
stmt, err := db.Prepare("SELECT userid,ticket AS ct FROM users WHERE autokey = ?")
|
||||
CheckErr(err)
|
||||
rows, err := stmt.Query(autoKey)
|
||||
CheckErr(err)
|
||||
var userid, ticket string
|
||||
for rows.Next() {
|
||||
err = rows.Scan(&userid, &ticket)
|
||||
CheckErr(err)
|
||||
}
|
||||
|
||||
var resp string
|
||||
if userid != "" {
|
||||
autoResp := LoginAutoResp{
|
||||
Result: 0,
|
||||
Message: "ok",
|
||||
Autokey: autoKey,
|
||||
Userid: userid,
|
||||
Ticket: ticket,
|
||||
}
|
||||
data, err := json.Marshal(autoResp)
|
||||
// fmt.Println(string(data))
|
||||
CheckErr(err)
|
||||
encryptedData, err := openssl.Des3ECBEncrypt(data, []byte(randKey)[0:24], openssl.PKCS7_PADDING)
|
||||
CheckErr(err)
|
||||
encryptedData64 := base64.StdEncoding.EncodeToString(encryptedData)
|
||||
// fmt.Println(encryptedData64)
|
||||
|
||||
resp = fmt.Sprintf(`{ "code": 0, "msg": "ok", "data": "%s" }`, encryptedData64)
|
||||
} else {
|
||||
data := `{"message":"账号不存在或者登陆状态已过期!","result":31}`
|
||||
encryptedData, err := openssl.Des3ECBEncrypt([]byte(data), []byte(randKey)[0:24], openssl.PKCS7_PADDING)
|
||||
CheckErr(err)
|
||||
encryptedData64 := base64.StdEncoding.EncodeToString(encryptedData)
|
||||
// fmt.Println(encryptedData64)
|
||||
|
||||
resp = fmt.Sprintf(`{ "code": 31, "msg": "账号不存在或者登陆状态已过期!", "data": "%s" }`, encryptedData64)
|
||||
}
|
||||
|
||||
ctx.Header("Content-Type", "text/html;charset=utf-8")
|
||||
ctx.String(http.StatusOK, resp)
|
||||
@@ -161,7 +243,7 @@ func LoginAutoHandler(ctx *gin.Context) {
|
||||
func LoginAreaHandler(ctx *gin.Context) {
|
||||
userId := ctx.PostForm("userid")
|
||||
if userId != "" {
|
||||
fmt.Println(userId)
|
||||
// fmt.Println(userId)
|
||||
resp := fmt.Sprintf(`{ "code": 0, "msg": "ok", "data": { "userid": "%s" } }`, userId)
|
||||
ctx.Header("Content-Type", "text/html;charset=utf-8")
|
||||
ctx.String(http.StatusOK, resp)
|
||||
@@ -169,53 +251,146 @@ func LoginAreaHandler(ctx *gin.Context) {
|
||||
}
|
||||
|
||||
func AccountLoginHandler(ctx *gin.Context) {
|
||||
// body, err := io.ReadAll(ctx.Request.Body)
|
||||
// CheckErr(err)
|
||||
// defer ctx.Request.Body.Close()
|
||||
body, err := io.ReadAll(ctx.Request.Body)
|
||||
CheckErr(err)
|
||||
defer ctx.Request.Body.Close()
|
||||
// fmt.Println(string(body))
|
||||
|
||||
// body64, err := base64.StdEncoding.DecodeString(string(body))
|
||||
// CheckErr(err)
|
||||
body64, err := base64.StdEncoding.DecodeString(string(body))
|
||||
CheckErr(err)
|
||||
// fmt.Println(string(body64))
|
||||
|
||||
// decryptedBody, err := openssl.Des3ECBDecrypt(body64, []byte(randKey)[0:24], openssl.PKCS7_PADDING)
|
||||
// CheckErr(err)
|
||||
// fmt.Println(string(decryptedBody))
|
||||
|
||||
// userid: 实际登录用的账号
|
||||
// ticket: 实际登录用的密码(每次登录都会重新生成新的)
|
||||
// 注意:更换设备(deviceId 发生变化)会重新生成 autokey
|
||||
data := `{
|
||||
"activation":0,
|
||||
"autokey":"AUTOB36C64BA1CC84E37AC5694FD7BE6652F",
|
||||
"captchaParams":"",
|
||||
"checkCodeGuid":"",
|
||||
"checkCodeUrl":"",
|
||||
"hasExtendAccs":0,
|
||||
"has_realInfo":1,
|
||||
"imagecodeType":0,
|
||||
"isNewUser":0,
|
||||
"message":"ok",
|
||||
"nextAction":0,
|
||||
"prompt_msg":"",
|
||||
"realInfoNotification":"",
|
||||
"realInfo_force":1,
|
||||
"realInfo_force_pay":0,
|
||||
"realInfo_status":0,
|
||||
"realInfo_status_pay":0,
|
||||
"result":0,
|
||||
"sdg_height":0,
|
||||
"sdg_width":0,
|
||||
"ticket":"810171225920071361680690948",
|
||||
"userAttribute":"0",
|
||||
"userid":"2592007136"
|
||||
}`
|
||||
encryptedToken, err := openssl.Des3ECBEncrypt([]byte(data), []byte(randKey)[0:24], openssl.PKCS7_PADDING)
|
||||
decryptedBody, err := openssl.Des3ECBDecrypt(body64, []byte(randKey)[0:24], openssl.PKCS7_PADDING)
|
||||
CheckErr(err)
|
||||
encryptedToken64 := base64.StdEncoding.EncodeToString(encryptedToken)
|
||||
queryStr, err := url.QueryUnescape(string(decryptedBody))
|
||||
CheckErr(err)
|
||||
|
||||
params, err := url.ParseQuery(queryStr)
|
||||
CheckErr(err)
|
||||
|
||||
phone, password := params.Get("phone"), params.Get("password")
|
||||
if phone == "" || password == "" {
|
||||
ctx.String(http.StatusForbidden, ErrorMsg)
|
||||
return
|
||||
}
|
||||
|
||||
// sql := `CREATE TABLE "users" (
|
||||
// "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
||||
// "phone" TEXT,
|
||||
// "password" TEXT,
|
||||
// "autokey" TEXT,
|
||||
// "ticket" TEXT,
|
||||
// "userid" INTEGER,
|
||||
// "last_login_time" INTEGER
|
||||
// );
|
||||
// CREATE TABLE "user_key" (
|
||||
// "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
||||
// "userid" INTEGER,
|
||||
// "key" INTEGER
|
||||
// );`
|
||||
db, err := sql.Open("sqlite3", "assets/account.db")
|
||||
CheckErr(err)
|
||||
defer db.Close()
|
||||
|
||||
stmt, err := db.Prepare("SELECT password,autokey,ticket,userid FROM users WHERE phone = ?")
|
||||
CheckErr(err)
|
||||
rows, err := stmt.Query(phone)
|
||||
CheckErr(err)
|
||||
var pass, autokey, ticket, userid string
|
||||
for rows.Next() {
|
||||
err = rows.Scan(&pass, &autokey, &ticket, &userid)
|
||||
CheckErr(err)
|
||||
}
|
||||
loginResp := LoginResp{}
|
||||
loginCode := 0
|
||||
loginMsg := "ok"
|
||||
loginTime := time.Now().Unix()
|
||||
if pass == "" {
|
||||
// 未注册 - 自动注册
|
||||
trans, err := db.Begin()
|
||||
if err != nil {
|
||||
trans.Rollback()
|
||||
panic(err)
|
||||
}
|
||||
pass = openssl.Md5ToString(password)
|
||||
autokey = "AUTO" + strings.ToUpper(utils.RandomStr(32))
|
||||
userid = strconv.Itoa(int(loginTime))
|
||||
ticket = "9999999" + userid + userid
|
||||
stmt, err = trans.Prepare("INSERT INTO users(phone,password,autokey,ticket,userid,last_login_time) VALUES (?,?,?,?,?,?)")
|
||||
if err != nil {
|
||||
trans.Rollback()
|
||||
panic(err)
|
||||
}
|
||||
_, err = stmt.Exec(phone, pass, autokey, ticket, userid, loginTime)
|
||||
if err != nil {
|
||||
trans.Rollback()
|
||||
panic(err)
|
||||
}
|
||||
// id, _ := res.LastInsertId()
|
||||
// fmt.Println("LastInsertId:", id)
|
||||
|
||||
stmt, err = trans.Prepare("INSERT INTO user_key(userid,key) VALUES(?,?)")
|
||||
if err != nil {
|
||||
trans.Rollback()
|
||||
panic(err)
|
||||
}
|
||||
// 方便起见初始化 userid 和 key 一样
|
||||
// 注意:user_key 表中的 key 是上文生成的用于登录的 userid,而 userid 则是用于 Authorize Token 生成用的
|
||||
_, err = stmt.Exec(userid, userid)
|
||||
if err != nil {
|
||||
trans.Rollback()
|
||||
panic(err)
|
||||
}
|
||||
|
||||
if err = trans.Commit(); err != nil {
|
||||
trans.Rollback()
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// Login Response
|
||||
loginResp.Autokey = autokey
|
||||
loginResp.HasRealInfo = 1
|
||||
loginResp.Message = "ok"
|
||||
loginResp.RealInfoForce = 1
|
||||
loginResp.Ticket = ticket
|
||||
loginResp.UserAttribute = "0"
|
||||
loginResp.Userid = userid
|
||||
} else {
|
||||
// 已注册
|
||||
if openssl.Md5ToString(password) == pass {
|
||||
// 密码正确
|
||||
// Login Response
|
||||
loginResp.Autokey = autokey // 注意:更换设备(deviceId 发生变化)应重新生成 autokey
|
||||
loginResp.HasRealInfo = 1
|
||||
loginResp.Message = "ok"
|
||||
loginResp.RealInfoForce = 1
|
||||
loginResp.Ticket = "9999999" + userid + strconv.Itoa(int(loginTime)) // 实际登录用的密码(每次登录都会重新生成新的)
|
||||
loginResp.UserAttribute = "0"
|
||||
loginResp.Userid = userid // 实际登录用的账号
|
||||
|
||||
// 更新信息
|
||||
stmt, err = db.Prepare("UPDATE users SET autokey=?,ticket=?,last_login_time=? WHERE userid=?")
|
||||
CheckErr(err)
|
||||
_, err := stmt.Exec(autokey, ticket, loginTime, userid)
|
||||
CheckErr(err)
|
||||
// aff, _ := res.RowsAffected()
|
||||
// fmt.Println("RowsAffected:", aff)
|
||||
} else {
|
||||
// 密码错误
|
||||
loginCode = 31
|
||||
loginMsg = "账号不存在或者密码有误!"
|
||||
}
|
||||
}
|
||||
|
||||
data, err := json.Marshal(loginResp)
|
||||
CheckErr(err)
|
||||
// fmt.Println(string(data))
|
||||
encryptedData, err := openssl.Des3ECBEncrypt(data, []byte(randKey)[0:24], openssl.PKCS7_PADDING)
|
||||
CheckErr(err)
|
||||
encryptedData64 := base64.StdEncoding.EncodeToString(encryptedData)
|
||||
// fmt.Println(encryptedToken64)
|
||||
|
||||
resp := fmt.Sprintf(`{ "code": 0, "msg": "ok", "data": "%s" }`, encryptedToken64)
|
||||
resp := fmt.Sprintf(`{ "code": %d, "msg": %s, "data": "%s" }`, loginCode, loginMsg, encryptedData64)
|
||||
|
||||
ctx.Header("Content-Type", "text/html;charset=utf-8")
|
||||
ctx.String(http.StatusOK, resp)
|
||||
|
||||
Reference in New Issue
Block a user