修改token过期时间,添加新token问题,添加未完成的qq登录方式

This commit is contained in:
junleea 2025-04-24 20:07:44 +08:00
parent dacdd35706
commit 8fee587a94
7 changed files with 211 additions and 7 deletions

View File

@ -22,6 +22,8 @@ type User struct {
CIDFunc bool `gorm:"column:cid_func"` //持续集成功能 CIDFunc bool `gorm:"column:cid_func"` //持续集成功能
Avatar string `gorm:"column:avatar"` Avatar string `gorm:"column:avatar"`
CreateTime string `gorm:"column:create_time"` CreateTime string `gorm:"column:create_time"`
QQ int64 `gorm:"column:qq"`
QQOpenID string `gorm:"column:qq_openid"`
UpdateTime string `gorm:"column:update_time"` UpdateTime string `gorm:"column:update_time"`
} }
@ -98,6 +100,7 @@ func UpdateUserByID2(id int, req proto.UpdateUserInfoReq) error {
updateData["CIDFunc"] = req.CIDFunc updateData["CIDFunc"] = req.CIDFunc
updateData["Avatar"] = req.Avatar updateData["Avatar"] = req.Avatar
updateData["Gender"] = req.Gender updateData["Gender"] = req.Gender
updateData["QQ"] = req.QQ
res := DB.Model(&User{}).Where("id =?", id).Updates(updateData) res := DB.Model(&User{}).Where("id =?", id).Updates(updateData)
if res.Error != nil { if res.Error != nil {
return res.Error return res.Error
@ -107,7 +110,7 @@ func UpdateUserByID2(id int, req proto.UpdateUserInfoReq) error {
// 用户修改自己的信息 // 用户修改自己的信息
func UpdateUserByID3(id int, req proto.UpdateUserInfoReq) error { func UpdateUserByID3(id int, req proto.UpdateUserInfoReq) error {
res := DB.Model(&User{}).Where("id = ?", id).Updates(User{Name: req.Username, Age: req.Age, Avatar: req.Avatar, Gender: req.Gender}) res := DB.Model(&User{}).Where("id = ?", id).Updates(User{Name: req.Username, Age: req.Age, Avatar: req.Avatar, Gender: req.Gender, QQ: req.QQ})
return res.Error return res.Error
} }

View File

@ -12,6 +12,7 @@ import (
"io" "io"
"log" "log"
"net/http" "net/http"
"net/url"
"os" "os"
"strconv" "strconv"
"time" "time"
@ -54,6 +55,8 @@ func SetUpToolGroup(router *gin.Engine) {
toolGroup.POST("/file_del", DelFile) toolGroup.POST("/file_del", DelFile)
//服务器、设备状态接口 //服务器、设备状态接口
toolGroup.POST("/monitor", SetDeviceStatusV2) toolGroup.POST("/monitor", SetDeviceStatusV2)
toolGroup.POST("/qq_callback", handleQQCallback)
toolGroup.POST("/qq_auth", GetAuthCode)
//发送邮件 //发送邮件
toolGroup.POST("/send_mail", SendMailTool) toolGroup.POST("/send_mail", SendMailTool)
toolGroup.POST("/dashboard", DashBoardStatistics) toolGroup.POST("/dashboard", DashBoardStatistics)
@ -102,6 +105,47 @@ func SetDeviceStatusV2(c *gin.Context) {
} }
type QQCallbackReq struct {
Code string `json:"code" form:"code"`
State string `json:"state" form:"state"`
}
func GetAuthCode(c *gin.Context) {
//query
uuid := c.Query("uuid")
if uuid == "" {
var resp proto.GenerateResp
resp.Code = proto.ParameterError
resp.Message = "uuid is empty"
c.JSON(http.StatusOK, resp)
return
}
params := url.Values{}
params.Add("response_type", "code")
params.Add("client_id", worker.AppId)
params.Add("state", "saw_"+uuid)
str := fmt.Sprintf("%s&redirect_uri=%s", params.Encode(), worker.RedirectURI)
loginURL := fmt.Sprintf("%s?%s", "https://graph.qq.com/oauth2.0/authorize", str)
c.Redirect(http.StatusFound, loginURL) //重定向到QQ登录页面
}
func handleQQCallback(c *gin.Context) {
var resp proto.GenerateResp
resp.Code = 0
var req QQCallbackReq
//query参数
if err := c.ShouldBindQuery(&req); err != nil {
resp.Code = 1
resp.Message = "参数错误"
c.JSON(http.StatusOK, resp)
return
} else {
}
c.JSON(http.StatusOK, resp)
}
func GetFileList(c *gin.Context) { func GetFileList(c *gin.Context) {
//解析请求参数 //解析请求参数
var req GetFileListReq var req GetFileListReq

View File

@ -402,7 +402,7 @@ func loginHandler(c *gin.Context) {
token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{ token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
"username": user.Name, "username": user.Name,
"id": user.ID, "id": user.ID,
"exp": time.Now().Add(time.Hour * 10).Unix(), // 令牌过期时间, 10小时后过期 "exp": time.Now().Add(time.Hour * 24).Unix(), // 令牌过期时间, 24小时后过期
}) })
tokenString, err = token.SignedString(proto.SigningKey) tokenString, err = token.SignedString(proto.SigningKey)
if err != nil { if err != nil {
@ -410,8 +410,8 @@ func loginHandler(c *gin.Context) {
return return
} }
worker.SetRedisWithExpire("user_"+user.Name, tokenString, time.Hour*10) // 将用户信息存入 worker.SetRedisWithExpire("user_"+user.Name, tokenString, time.Hour*24) // 将用户信息存入
worker.SetRedisWithExpire(tokenString, tokenString, time.Hour*10) // 设置过期时间为10分钟 worker.SetRedisWithExpire(tokenString, tokenString, time.Hour*24) // 设置过期时间为24h
data := make(map[string]interface{}) data := make(map[string]interface{})
data["id"] = user.ID data["id"] = user.ID
data["username"] = user.Name data["username"] = user.Name
@ -459,7 +459,7 @@ func registerHandler(c *gin.Context) {
token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{ token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
"username": req_data.User, "username": req_data.User,
"id": id, "id": id,
"exp": time.Now().Add(time.Hour * 10).Unix(), // 令牌过期时间, 1分钟后过期 "exp": time.Now().Add(time.Hour * 24).Unix(), // 令牌过期时间, 1分钟后过期
}) })
tokenString, err = token.SignedString(proto.SigningKey) tokenString, err = token.SignedString(proto.SigningKey)
if err != nil { if err != nil {
@ -471,7 +471,7 @@ func registerHandler(c *gin.Context) {
return return
} }
fmt.Println(req_data) fmt.Println(req_data)
res := worker.SetRedisWithExpire(tokenString, tokenString, time.Hour*10) // 设置过期时间为10分钟 res := worker.SetRedisWithExpire(tokenString, tokenString, time.Hour*24) // 设置过期时间为24h
if !res { if !res {
c.JSON(200, gin.H{"error": "set token error", "code": proto.RedisSetError, "message": "error"}) c.JSON(200, gin.H{"error": "set token error", "code": proto.RedisSetError, "message": "error"})
return return

View File

@ -9,7 +9,7 @@ import (
var Config ConfigStruct var Config ConfigStruct
var SigningKey = []byte{} var SigningKey = []byte{}
var Url_map = map[string]bool{"/login": true, "/register": true, "/uuid": true, "/gqr": true, "/cid/callback": true, "/tool/monitor": true, "/user/sync": true, "/tool/file/": true, "/user/reset": true} // 不需要token验证的url var Url_map = map[string]bool{"/login": true, "/register": true, "/uuid": true, "/gqr": true, "/cid/callback": true, "/tool/monitor": true, "/user/sync": true, "/tool/file/": true, "/user/reset": true, "/tool/qq_auth": true, "/tool/qq_callback": true} // 不需要token验证的url
var Per_menu_map = map[string]int{"/video/": 1, "/device/": 2, "/cid/": 3} var Per_menu_map = map[string]int{"/video/": 1, "/device/": 2, "/cid/": 3}
var File_Type = map[string]int{"im": 1, "avatar": 2, "file": 3, "config": 4} // 文件类型 var File_Type = map[string]int{"im": 1, "avatar": 2, "file": 3, "config": 4} // 文件类型
const ( const (

View File

@ -16,6 +16,7 @@ type UpdateUserInfoReq struct {
DeviceFunc bool `json:"device_func" form:"device_func"` //设备功能 DeviceFunc bool `json:"device_func" form:"device_func"` //设备功能
CIDFunc bool `json:"cid_func" form:"cid_func"` //持续集成功能 CIDFunc bool `json:"cid_func" form:"cid_func"` //持续集成功能
Run bool `json:"run" form:"run"` //是否运行 Run bool `json:"run" form:"run"` //是否运行
QQ int64 `json:"qq" form:"qq"` //QQ
Avatar string `json:"avatar" form:"avatar"` //头像 Avatar string `json:"avatar" form:"avatar"` //头像
} }

View File

@ -421,3 +421,18 @@ func CreateTokenAndSave(user dao.User) (string, error) {
func GetUserStatistics(userID int) dao.UserStatistics { func GetUserStatistics(userID int) dao.UserStatistics {
return dao.UserStatisticsData(userID) return dao.UserStatisticsData(userID)
} }
func CalculateUserTokenAndSetCache(user dao.User) (string, error) {
// 生成 JWT 令牌
token := jwt.NewWithClaims(jwt.SigningMethodHS512, jwt.MapClaims{
"username": user.Name,
"id": user.ID,
"exp": time.Now().Add(time.Hour * 24).Unix(), // 令牌过期时间, 24小时后过期
})
tokenString, err := token.SignedString(proto.SigningKey)
//设置缓存
worker.SetRedisWithExpire("user_"+user.Name, tokenString, time.Hour*24) // 将用户信息存入
worker.SetRedisWithExpire(tokenString, tokenString, time.Hour*24) // 设置过期时间为24小时
return tokenString, err
}

141
worker/qq.go Normal file
View File

@ -0,0 +1,141 @@
package worker
import (
"fmt"
"io/ioutil"
"net/http"
"net/url"
"strings"
)
const (
AppId = "101827468"
AppKey = "0d2d856e48e0ebf6b98e0d0c879fe74d"
RedirectURI = "https://www.ljsea.top/qq_callback.php"
)
type PrivateInfo struct {
AccessToken string `json:"access_token"`
ExpiresIn string `json:"expires_in"`
RefreshToken string `json:"refresh_token"`
OpenId string `json:"openid"`
}
//func main() {
// http.HandleFunc("/toLogin", GetAuthCode)
// http.HandleFunc("/qqLogin", GetToken)
//
// fmt.Println("started...")
// err := http.ListenAndServe(":9090", nil)
// if err != nil {
// panic(err)
// }
//}
type GetCodeResponse struct {
}
type GetCodeRequest struct {
ResponseType string `json:"response_type"`
ClientID string `json:"client_id"`
RedirectURI string `json:"redirect_uri"`
State string `json:"state"`
Scope string `json:"scope,omitempty"`
Display string `json:"display,omitempty"`
}
type QQAccessTokenRequest struct {
GrantType string `json:"grant_type"`
ClientID string `json:"client_id"`
ClientSecret string `json:"client_secret"`
Code string `json:"code"`
RedirectURI string `json:"redirect_uri"`
Fmt string `json:"fmt,omitempty"`
NeedOpenID string `json:"need_openid,omitempty"`
}
type QQAccessTokenResponse struct {
AccessToken string `json:"access_token"`
ExpiresIn int `json:"expires_in"`
RefreshToken string `json:"refresh_token"`
}
type QQRefreshTokenRequest struct {
GrantType string `json:"grant_type"`
ClientID string `json:"client_id"`
ClientSecret string `json:"client_secret"`
RefreshToken string `json:"refresh_token"`
Fmt string `json:"fmt,omitempty"`
}
// 2. Get Access Token
func GetToken(w http.ResponseWriter, r *http.Request) {
code := r.FormValue("code")
params := url.Values{}
params.Add("grant_type", "authorization_code")
params.Add("client_id", AppId)
params.Add("client_secret", AppKey)
params.Add("code", code)
str := fmt.Sprintf("%s&redirect_uri=%s", params.Encode(), RedirectURI)
loginURL := fmt.Sprintf("%s?%s", "https://graph.qq.com/oauth2.0/token", str)
response, err := http.Get(loginURL)
if err != nil {
w.Write([]byte(err.Error()))
}
defer response.Body.Close()
bs, _ := ioutil.ReadAll(response.Body)
body := string(bs)
resultMap := convertToMap(body)
info := &PrivateInfo{}
info.AccessToken = resultMap["access_token"]
info.RefreshToken = resultMap["refresh_token"]
info.ExpiresIn = resultMap["expires_in"]
GetOpenId(info, w)
}
// 3. Get OpenId
func GetOpenId(info *PrivateInfo, w http.ResponseWriter) {
resp, err := http.Get(fmt.Sprintf("%s?access_token=%s", "https://graph.qq.com/oauth2.0/me", info.AccessToken))
if err != nil {
w.Write([]byte(err.Error()))
}
defer resp.Body.Close()
bs, _ := ioutil.ReadAll(resp.Body)
body := string(bs)
info.OpenId = body[45:77]
GetUserInfo(info, w)
}
// 4. Get User info
func GetUserInfo(info *PrivateInfo, w http.ResponseWriter) {
params := url.Values{}
params.Add("access_token", info.AccessToken)
params.Add("openid", info.OpenId)
params.Add("oauth_consumer_key", AppId)
uri := fmt.Sprintf("https://graph.qq.com/user/get_user_info?%s", params.Encode())
resp, err := http.Get(uri)
if err != nil {
w.Write([]byte(err.Error()))
}
defer resp.Body.Close()
bs, _ := ioutil.ReadAll(resp.Body)
w.Write(bs)
}
func convertToMap(str string) map[string]string {
var resultMap = make(map[string]string)
values := strings.Split(str, "&")
for _, value := range values {
vs := strings.Split(value, "=")
resultMap[vs[0]] = vs[1]
}
return resultMap
}