114 lines
2.9 KiB
Go
114 lines
2.9 KiB
Go
package authser
|
||
|
||
import (
|
||
"encoding/json"
|
||
"fmt"
|
||
"net/http"
|
||
"net/url"
|
||
"strings"
|
||
"time"
|
||
"videoweb/app/service/upstream"
|
||
"videoweb/pub/common/useragent"
|
||
|
||
"github.com/gin-gonic/gin"
|
||
)
|
||
|
||
const (
|
||
guestPath = "/api/app/auth/guest"
|
||
cookieMaxAge = 7 * 24 * 3600
|
||
)
|
||
|
||
// GuestLogin 调用上游游客登录,站点不提供注册/登录,上游内容接口依赖游客会话。
|
||
func GuestLogin(c *gin.Context, req GuestLoginReq) (*APIEnvelope, *LoginResp, error) {
|
||
var env APIEnvelope
|
||
if _, err := upstream.PostJSON(c, guestPath, req, &env); err != nil {
|
||
return nil, nil, err
|
||
}
|
||
if env.Code != 200 {
|
||
return &env, nil, nil
|
||
}
|
||
user, err := decodeLoginData(env.Data)
|
||
if err != nil {
|
||
return &env, nil, err
|
||
}
|
||
return &env, user, nil
|
||
}
|
||
|
||
func decodeLoginData(raw json.RawMessage) (*LoginResp, error) {
|
||
if len(raw) == 0 || string(raw) == "null" || string(raw) == `""` {
|
||
return nil, fmt.Errorf("empty login data")
|
||
}
|
||
var user LoginResp
|
||
if err := json.Unmarshal(raw, &user); err != nil {
|
||
return nil, err
|
||
}
|
||
return &user, nil
|
||
}
|
||
|
||
// SetAuthCookies 写入游客会话 cookie。
|
||
func SetAuthCookies(c *gin.Context, user *LoginResp) {
|
||
if c == nil || user == nil {
|
||
return
|
||
}
|
||
secure := c.Request != nil && c.Request.TLS != nil
|
||
if strings.TrimSpace(user.Token) != "" {
|
||
setCookie(c, "token", user.Token, secure)
|
||
}
|
||
if sid := useragent.SIDFromRequest(c.Request); sid != "" {
|
||
setCookie(c, "sid", sid, secure)
|
||
}
|
||
}
|
||
|
||
func setCookie(c *gin.Context, name, value string, secure bool) {
|
||
// Cookie Value 仅允许 ASCII;使用 PathEscape(空格→%20),与前端 encodeURIComponent 一致。
|
||
http.SetCookie(c.Writer, &http.Cookie{
|
||
Name: name,
|
||
Value: url.PathEscape(value),
|
||
Path: "/",
|
||
MaxAge: cookieMaxAge,
|
||
HttpOnly: false,
|
||
Secure: secure,
|
||
SameSite: http.SameSiteLaxMode,
|
||
Expires: time.Now().Add(7 * 24 * time.Hour),
|
||
})
|
||
}
|
||
|
||
func cookieValue(c *gin.Context, name string) string {
|
||
ck, err := c.Request.Cookie(name)
|
||
if err != nil || ck == nil {
|
||
return ""
|
||
}
|
||
raw := strings.TrimSpace(ck.Value)
|
||
if raw == "" {
|
||
return ""
|
||
}
|
||
// QueryUnescape 同时兼容历史 QueryEscape(+)与 PathEscape(%20)
|
||
if decoded, err := url.QueryUnescape(raw); err == nil {
|
||
return strings.TrimSpace(decoded)
|
||
}
|
||
return raw
|
||
}
|
||
|
||
// ClearAuthCookies 清除会话 cookie,同时清理旧版账号体系遗留的用户信息 cookie。
|
||
func ClearAuthCookies(c *gin.Context) {
|
||
for _, name := range authCookieNames() {
|
||
http.SetCookie(c.Writer, &http.Cookie{
|
||
Name: name,
|
||
Value: "",
|
||
Path: "/",
|
||
MaxAge: -1,
|
||
HttpOnly: false,
|
||
SameSite: http.SameSiteLaxMode,
|
||
})
|
||
}
|
||
}
|
||
|
||
func authCookieNames() []string {
|
||
return []string{
|
||
"token", "_token_", "sid", "_s_token_",
|
||
"userId", "accountNo", "nickName", "introduction", "avatar",
|
||
"email", "inviteCode", "recharge", "vipType", "currentVipExpire", "showCardId", "showCardName",
|
||
"userType", "isRegister", "guest_skip_auto",
|
||
}
|
||
}
|