♻️ refactored login-related code

This commit is contained in:
2024-12-21 00:51:59 +08:00
parent 40d073db0f
commit f213644aa9
33 changed files with 802 additions and 535 deletions

View File

@@ -1,3 +0,0 @@
package constant
const SESSION_KEY = "SESSION"

View File

@@ -0,0 +1,3 @@
package constant
const UID_HEADER_KEY = "X-UID"

View File

@@ -19,7 +19,7 @@ func GenerateAccessToken(secret string, payload AccessJWTPayload) string {
claims := AccessJWTClaims{
AccessJWTPayload: payload,
RegisteredClaims: jwt.RegisteredClaims{
ExpiresAt: jwt.NewNumericDate(time.Now().Add(time.Minute * 30)),
ExpiresAt: jwt.NewNumericDate(time.Now().Add(time.Minute * 15)),
IssuedAt: jwt.NewNumericDate(time.Now()),
NotBefore: jwt.NewNumericDate(time.Now()),
},

View File

@@ -0,0 +1,48 @@
package jwt
import (
"time"
"github.com/golang-jwt/jwt/v5"
)
type WebsocketJWTPayload struct {
UserID string `json:"user_id"`
Type string `json:"type"`
Expr string `json:"expr"`
}
type WebsocketJWTClaims struct {
AccessJWTPayload
jwt.RegisteredClaims
}
func GenerateWebsocketToken(secret string, payload AccessJWTPayload) string {
claims := AccessJWTClaims{
AccessJWTPayload: payload,
RegisteredClaims: jwt.RegisteredClaims{
ExpiresAt: jwt.NewNumericDate(time.Now().Add(time.Minute * 15)),
IssuedAt: jwt.NewNumericDate(time.Now()),
NotBefore: jwt.NewNumericDate(time.Now()),
},
}
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
accessToken, err := token.SignedString([]byte(secret))
if err != nil {
return ""
}
return accessToken
}
// ParseWebsocketToken parses a JWT token and returns the payload
func ParseWebsocketToken(secret string, tokenString string) (*AccessJWTPayload, bool) {
token, err := jwt.ParseWithClaims(tokenString, &AccessJWTClaims{}, func(token *jwt.Token) (interface{}, error) {
return []byte(secret), nil
})
if err != nil {
return nil, false
}
if claims, ok := token.Claims.(*AccessJWTClaims); ok && token.Valid {
return &claims.AccessJWTPayload, true
}
return nil, false
}

View File

@@ -7,7 +7,7 @@ func CORSMiddleware() func(http.Header) {
header.Set("Access-Control-Allow-Origin", "*")
header.Set("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS, PATCH")
header.Set("Access-Control-Expose-Headers", "Content-Length, Content-Type")
header.Set("Access-Control-Allow-Headers", "Content-Type,Authorization,Accept-Language,Origin,X-Content-Security")
header.Set("Access-Control-Allow-Headers", "Content-Type,Authorization,Accept-Language,Origin,X-Content-Security,X-UID")
header.Set("Access-Control-Allow-Credentials", "true")
}
}

View File

@@ -10,7 +10,7 @@ import (
func UnauthorizedCallbackMiddleware() func(w http.ResponseWriter, r *http.Request, err error) {
return func(w http.ResponseWriter, r *http.Request, err error) {
// httpx.WriteJson(w, http.StatusUnauthorized, response.ErrorWithCodeMessage(http.StatusUnauthorized, "Unauthorized"))
httpx.OkJsonCtx(r.Context(), w, response.ErrorWithCodeMessage(http.StatusUnauthorized, "Unauthorized"))
httpx.OkJsonCtx(r.Context(), w, response.ErrorWithCodeMessage(http.StatusUnauthorized, err.Error()))
return
}
}

View File

@@ -31,8 +31,9 @@ type (
Password string `json:"password"`
Repassword string `json:"repassword"`
}
UserDeviceRequest {
AccessToken string `json:"access_token"`
WechatOffiaccountLoginRequest {
Openid string `json:"openid"`
ClientId string `json:"client_id"`
}
// 登录响应参数
LoginResponse {
@@ -170,8 +171,13 @@ service core {
@handler resetPassword
post /reset/password (ResetPasswordRequest) returns (Response)
@handler getUserDevice
post /device (UserDeviceRequest) returns (Response)
// 微信公众号登录
@handler wechatOffiaccountLogin
post /wechat/offiaccount/login (WechatOffiaccountLoginRequest) returns (Response)
// 获取微信公众号二维码
@handler getWechatOffiaccountQrcode
post /wechat/offiaccount/qrcode (OAuthWechatRequest) returns (Response)
}
@server (
@@ -249,11 +255,12 @@ service core {
@handler qqCallback
get /qq/callback (OAuthCallbackRequest) returns (string)
@handler wechatCallback
get /wechat/callback
@handler wechatOffiaccountCallback
post /wechat/offiaccount/callback
@handler getWechatQrcode
get /wechat/qrcode (OAuthWechatRequest) returns (Response)
// important!
@handler wechatOffiaccountCallbackVerify
get /wechat/offiaccount/callback
}
@server (
@@ -301,7 +308,7 @@ service core {
timeout: 10s // 超时时间
maxBytes: 1048576 // 最大请求大小
signature: false // 是否开启签名验证
middleware: SecurityHeadersMiddleware,CasbinVerifyMiddleware // 注册中间件
middleware: SecurityHeadersMiddleware,CasbinVerifyMiddleware,AuthorizationMiddleware // 注册中间件
MaxConns: true // 是否开启最大连接数限制
Recover: true // 是否开启自动恢复
jwt: Auth // 是否开启jwt验证

View File

@@ -1,20 +1,20 @@
package oauth
import (
"github.com/ArtisanCloud/PowerLibs/v3/http/helper"
"github.com/zeromicro/go-zero/core/logx"
"net/http"
"github.com/zeromicro/go-zero/core/logx"
"github.com/zeromicro/go-zero/rest/httpx"
"schisandra-album-cloud-microservices/app/core/api/common/response"
"schisandra-album-cloud-microservices/app/core/api/internal/logic/oauth"
"schisandra-album-cloud-microservices/app/core/api/internal/svc"
)
func WechatCallbackHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
func WechatOffiaccountCallbackHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
l := oauth.NewWechatCallbackLogic(r.Context(), svcCtx)
err := l.WechatCallback(w, r)
l := oauth.NewWechatOffiaccountCallbackLogic(r.Context(), svcCtx)
res, err := l.WechatOffiaccountCallback(r)
if err != nil {
logx.Error(err)
httpx.WriteJsonCtx(
@@ -23,7 +23,7 @@ func WechatCallbackHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
http.StatusInternalServerError,
response.ErrorWithI18n(r.Context(), "system.error"))
} else {
httpx.Ok(w)
_ = helper.HttpResponseSend(res, w)
}
}
}

View File

@@ -0,0 +1,29 @@
package oauth
import (
"github.com/ArtisanCloud/PowerLibs/v3/http/helper"
"github.com/zeromicro/go-zero/core/logx"
"net/http"
"github.com/zeromicro/go-zero/rest/httpx"
"schisandra-album-cloud-microservices/app/core/api/common/response"
"schisandra-album-cloud-microservices/app/core/api/internal/logic/oauth"
"schisandra-album-cloud-microservices/app/core/api/internal/svc"
)
func WechatOffiaccountCallbackVerifyHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
l := oauth.NewWechatOffiaccountCallbackVerifyLogic(r.Context(), svcCtx)
res, err := l.WechatOffiaccountCallbackVerify(r)
if err != nil {
logx.Error(err)
httpx.WriteJsonCtx(
r.Context(),
w,
http.StatusInternalServerError,
response.ErrorWithI18n(r.Context(), "system.error"))
} else {
_ = helper.HttpResponseSend(res, w)
}
}
}

View File

@@ -61,7 +61,7 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
server.AddRoutes(
rest.WithMiddlewares(
[]rest.Middleware{serverCtx.SecurityHeadersMiddleware, serverCtx.CasbinVerifyMiddleware},
[]rest.Middleware{serverCtx.SecurityHeadersMiddleware, serverCtx.CasbinVerifyMiddleware, serverCtx.AuthorizationMiddleware},
[]rest.Route{
{
Method: http.MethodPost,
@@ -141,14 +141,14 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
Handler: oauth.GetQqOauthUrlHandler(serverCtx),
},
{
Method: http.MethodGet,
Path: "/wechat/callback",
Handler: oauth.WechatCallbackHandler(serverCtx),
Method: http.MethodPost,
Path: "/wechat/offiaccount/callback",
Handler: oauth.WechatOffiaccountCallbackHandler(serverCtx),
},
{
Method: http.MethodGet,
Path: "/wechat/qrcode",
Handler: oauth.GetWechatQrcodeHandler(serverCtx),
Path: "/wechat/offiaccount/callback",
Handler: oauth.WechatOffiaccountCallbackVerifyHandler(serverCtx),
},
}...,
),
@@ -220,11 +220,6 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
rest.WithMiddlewares(
[]rest.Middleware{serverCtx.SecurityHeadersMiddleware},
[]rest.Route{
{
Method: http.MethodPost,
Path: "/device",
Handler: user.GetUserDeviceHandler(serverCtx),
},
{
Method: http.MethodPost,
Path: "/login",
@@ -240,6 +235,16 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
Path: "/reset/password",
Handler: user.ResetPasswordHandler(serverCtx),
},
{
Method: http.MethodPost,
Path: "/wechat/offiaccount/login",
Handler: user.WechatOffiaccountLoginHandler(serverCtx),
},
{
Method: http.MethodPost,
Path: "/wechat/offiaccount/qrcode",
Handler: user.GetWechatOffiaccountQrcodeHandler(serverCtx),
},
}...,
),
rest.WithSignature(serverCtx.Config.Signature),

View File

@@ -1,18 +1,17 @@
package oauth
package user
import (
"net/http"
"github.com/zeromicro/go-zero/core/logx"
"github.com/zeromicro/go-zero/rest/httpx"
"net/http"
"schisandra-album-cloud-microservices/app/core/api/internal/logic/user"
"github.com/zeromicro/go-zero/rest/httpx"
"schisandra-album-cloud-microservices/app/core/api/common/response"
"schisandra-album-cloud-microservices/app/core/api/internal/logic/oauth"
"schisandra-album-cloud-microservices/app/core/api/internal/svc"
"schisandra-album-cloud-microservices/app/core/api/internal/types"
)
func GetWechatQrcodeHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
func GetWechatOffiaccountQrcodeHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var req types.OAuthWechatRequest
if err := httpx.Parse(r, &req); err != nil {
@@ -20,8 +19,8 @@ func GetWechatQrcodeHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return
}
l := oauth.NewGetWechatQrcodeLogic(r.Context(), svcCtx)
resp, err := l.GetWechatQrcode(r, &req)
l := user.NewGetWechatOffiaccountQrcodeLogic(r.Context(), svcCtx)
resp, err := l.GetWechatOffiaccountQrcode(r, &req)
if err != nil {
logx.Error(err)
httpx.WriteJsonCtx(

View File

@@ -11,16 +11,16 @@ import (
"schisandra-album-cloud-microservices/app/core/api/internal/types"
)
func GetUserDeviceHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
func WechatOffiaccountLoginHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var req types.UserDeviceRequest
var req types.WechatOffiaccountLoginRequest
if err := httpx.Parse(r, &req); err != nil {
httpx.ErrorCtx(r.Context(), w, err)
return
}
l := user.NewGetUserDeviceLogic(r.Context(), svcCtx)
resp, err := l.GetUserDevice(r, w, &req)
l := user.NewWechatOffiaccountLoginLogic(r.Context(), svcCtx)
resp, err := l.WechatOffiaccountLogin(r, &req)
if err != nil {
logx.Error(err)
httpx.WriteJsonCtx(

View File

@@ -149,7 +149,7 @@ func (l *GiteeCallbackLogic) GiteeCallback(w http.ResponseWriter, r *http.Reques
_ = tx.Rollback()
return "", err
}
data, err := HandleOauthLoginResponse(addUser, l.svcCtx, r, w, l.ctx)
data, err := HandleOauthLoginResponse(addUser, l.svcCtx, r, l.ctx)
if err != nil {
_ = tx.Rollback()
return "", err
@@ -167,7 +167,7 @@ func (l *GiteeCallbackLogic) GiteeCallback(w http.ResponseWriter, r *http.Reques
return "", err
}
data, err := HandleOauthLoginResponse(authUserInfo, l.svcCtx, r, w, l.ctx)
data, err := HandleOauthLoginResponse(authUserInfo, l.svcCtx, r, l.ctx)
if err != nil {
_ = tx.Rollback()
return "", err
@@ -180,13 +180,12 @@ func (l *GiteeCallbackLogic) GiteeCallback(w http.ResponseWriter, r *http.Reques
}
// HandleOauthLoginResponse 处理登录响应
func HandleOauthLoginResponse(scaAuthUser *model.ScaAuthUser, svcCtx *svc.ServiceContext, r *http.Request, w http.ResponseWriter, ctx context.Context) (string, error) {
data, err := user.HandleUserLogin(scaAuthUser, svcCtx, true, r, w, ctx)
func HandleOauthLoginResponse(scaAuthUser *model.ScaAuthUser, svcCtx *svc.ServiceContext, r *http.Request, ctx context.Context) (string, error) {
data, err := user.HandleLoginJWT(scaAuthUser, svcCtx, true, r, ctx)
if err != nil {
return "", err
}
responseData := response.SuccessWithData(data)
marshalData, err := json.Marshal(responseData)
marshalData, err := json.Marshal(response.SuccessWithData(data))
if err != nil {
return "", err
}

View File

@@ -149,7 +149,7 @@ func (l *GithubCallbackLogic) GithubCallback(w http.ResponseWriter, r *http.Requ
return "", err
}
data, err := HandleOauthLoginResponse(addUser, l.svcCtx, r, w, l.ctx)
data, err := HandleOauthLoginResponse(addUser, l.svcCtx, r, l.ctx)
if err != nil {
_ = tx.Rollback()
return "", err
@@ -167,7 +167,7 @@ func (l *GithubCallbackLogic) GithubCallback(w http.ResponseWriter, r *http.Requ
return "", err
}
data, err := HandleOauthLoginResponse(authUserInfo, l.svcCtx, r, w, l.ctx)
data, err := HandleOauthLoginResponse(authUserInfo, l.svcCtx, r, l.ctx)
if err != nil {
_ = tx.Rollback()
return "", err

View File

@@ -149,7 +149,7 @@ func (l *QqCallbackLogic) QqCallback(w http.ResponseWriter, r *http.Request, req
return "", err
}
data, err := HandleOauthLoginResponse(addUser, l.svcCtx, r, w, l.ctx)
data, err := HandleOauthLoginResponse(addUser, l.svcCtx, r, l.ctx)
if err != nil {
_ = tx.Rollback()
return "", err
@@ -167,7 +167,7 @@ func (l *QqCallbackLogic) QqCallback(w http.ResponseWriter, r *http.Request, req
return "", err
}
data, err := HandleOauthLoginResponse(authUserInfo, l.svcCtx, r, w, l.ctx)
data, err := HandleOauthLoginResponse(authUserInfo, l.svcCtx, r, l.ctx)
if err != nil {
_ = tx.Rollback()
return "", err

View File

@@ -1,208 +0,0 @@
package oauth
import (
"context"
"encoding/json"
"errors"
"net/http"
"strconv"
"strings"
"github.com/ArtisanCloud/PowerLibs/v3/http/helper"
"github.com/ArtisanCloud/PowerWeChat/v3/src/kernel/contract"
"github.com/ArtisanCloud/PowerWeChat/v3/src/kernel/messages"
models2 "github.com/ArtisanCloud/PowerWeChat/v3/src/kernel/models"
"github.com/ArtisanCloud/PowerWeChat/v3/src/officialAccount/server/handlers/models"
"github.com/yitter/idgenerator-go/idgen"
"github.com/zeromicro/go-zero/core/logx"
"gorm.io/gorm"
"schisandra-album-cloud-microservices/app/core/api/common/constant"
"schisandra-album-cloud-microservices/app/core/api/common/i18n"
randomname "schisandra-album-cloud-microservices/app/core/api/common/random_name"
"schisandra-album-cloud-microservices/app/core/api/common/utils"
"schisandra-album-cloud-microservices/app/core/api/internal/logic/user"
"schisandra-album-cloud-microservices/app/core/api/internal/logic/websocket"
"schisandra-album-cloud-microservices/app/core/api/internal/svc"
"schisandra-album-cloud-microservices/app/core/api/repository/mysql/model"
)
type WechatCallbackLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewWechatCallbackLogic(ctx context.Context, svcCtx *svc.ServiceContext) *WechatCallbackLogic {
return &WechatCallbackLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *WechatCallbackLogic) WechatCallback(w http.ResponseWriter, r *http.Request) error {
_, err := l.svcCtx.WechatPublic.Server.VerifyURL(r)
if err != nil {
return err
}
rs, err := l.svcCtx.WechatPublic.Server.Notify(r, func(event contract.EventInterface) interface{} {
switch event.GetMsgType() {
case models2.CALLBACK_MSG_TYPE_EVENT:
switch event.GetEvent() {
case models.CALLBACK_EVENT_SUBSCRIBE:
msg := models.EventSubscribe{}
err = event.ReadMessage(&msg)
if err != nil {
println(err.Error())
return err
}
key := strings.TrimPrefix(msg.EventKey, "qrscene_")
err = l.HandlerWechatLogin(msg.FromUserName, key, w, r)
if err != nil {
return messages.NewText(i18n.FormatText(l.ctx, "login.loginFailed"))
}
return messages.NewText(i18n.FormatText(l.ctx, "login.loginSuccess"))
case models.CALLBACK_EVENT_UNSUBSCRIBE:
msg := models.EventUnSubscribe{}
err = event.ReadMessage(&msg)
if err != nil {
println(err.Error())
return err
}
return messages.NewText("ok")
case models.CALLBACK_EVENT_SCAN:
msg := models.EventScan{}
err = event.ReadMessage(&msg)
if err != nil {
println(err.Error())
return err
}
err = l.HandlerWechatLogin(msg.FromUserName, msg.EventKey, w, r)
if err != nil {
return messages.NewText(i18n.FormatText(l.ctx, "login.loginFailed"))
}
return messages.NewText(i18n.FormatText(l.ctx, "login.loginSuccess"))
}
case models2.CALLBACK_MSG_TYPE_TEXT:
msg := models.MessageText{}
err = event.ReadMessage(&msg)
if err != nil {
println(err.Error())
return err
}
}
return messages.NewText("ok")
})
if err != nil {
return err
}
err = helper.HttpResponseSend(rs, w)
if err != nil {
return err
}
return nil
}
// HandlerWechatLogin 处理微信登录
func (l *WechatCallbackLogic) HandlerWechatLogin(openId string, clientId string, w http.ResponseWriter, r *http.Request) error {
if openId == "" {
return errors.New("openId is empty")
}
tx := l.svcCtx.DB.Begin()
userSocial := l.svcCtx.DB.ScaAuthUserSocial
socialUser, err := tx.ScaAuthUserSocial.Where(userSocial.OpenID.Eq(openId), userSocial.Source.Eq(constant.OAuthSourceWechat)).First()
if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
return err
}
if socialUser == nil {
// 创建用户
uid := idgen.NextId()
uidStr := strconv.FormatInt(uid, 10)
avatar := utils.GenerateAvatar(uidStr)
name := randomname.GenerateName()
male := constant.Male
addUser := &model.ScaAuthUser{
UID: uidStr,
Avatar: avatar,
Username: openId,
Nickname: name,
Gender: male,
}
err = tx.ScaAuthUser.Create(addUser)
if err != nil {
_ = tx.Rollback()
return err
}
wechatUser := constant.OAuthSourceWechat
newSocialUser := &model.ScaAuthUserSocial{
UserID: uidStr,
OpenID: openId,
Source: wechatUser,
}
err = tx.ScaAuthUserSocial.Create(newSocialUser)
if err != nil {
_ = tx.Rollback()
return err
}
if res, err := l.svcCtx.CasbinEnforcer.AddRoleForUser(uidStr, constant.User); !res || err != nil {
_ = tx.Rollback()
return err
}
data, err := user.HandleUserLogin(addUser, l.svcCtx, true, r, w, l.ctx)
if err != nil {
_ = tx.Rollback()
return err
}
marshal, err := json.Marshal(data)
if err != nil {
_ = tx.Rollback()
return err
}
err = websocket.QrcodeWebSocketHandler.SendMessageToClient(clientId, marshal)
if err != nil {
_ = tx.Rollback()
return err
}
} else {
authUser := l.svcCtx.DB.ScaAuthUser
authUserInfo, err := tx.ScaAuthUser.Where(authUser.UID.Eq(socialUser.UserID)).First()
if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
_ = tx.Rollback()
return err
}
data, err := user.HandleUserLogin(authUserInfo, l.svcCtx, true, r, w, l.ctx)
if err != nil {
_ = tx.Rollback()
return err
}
marshal, err := json.Marshal(data)
if err != nil {
_ = tx.Rollback()
return err
}
err = websocket.QrcodeWebSocketHandler.SendMessageToClient(clientId, marshal)
if err != nil {
_ = tx.Rollback()
return err
}
}
if err = tx.Commit(); err != nil {
return err
}
return nil
}

View File

@@ -0,0 +1,112 @@
package oauth
import (
"context"
"encoding/json"
"github.com/ArtisanCloud/PowerWeChat/v3/src/kernel/contract"
"github.com/ArtisanCloud/PowerWeChat/v3/src/kernel/messages"
models2 "github.com/ArtisanCloud/PowerWeChat/v3/src/kernel/models"
"github.com/ArtisanCloud/PowerWeChat/v3/src/officialAccount/server/handlers/models"
"net/http"
"schisandra-album-cloud-microservices/app/core/api/common/i18n"
"schisandra-album-cloud-microservices/app/core/api/common/response"
"schisandra-album-cloud-microservices/app/core/api/internal/logic/websocket"
"strings"
"github.com/zeromicro/go-zero/core/logx"
"schisandra-album-cloud-microservices/app/core/api/internal/svc"
)
type WechatOffiaccountCallbackLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
type MessageData struct {
Openid string `json:"openid"`
ClientId string `json:"client_id"`
}
func NewWechatOffiaccountCallbackLogic(ctx context.Context, svcCtx *svc.ServiceContext) *WechatOffiaccountCallbackLogic {
return &WechatOffiaccountCallbackLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *WechatOffiaccountCallbackLogic) WechatOffiaccountCallback(r *http.Request) (*http.Response, error) {
rs, err := l.svcCtx.WechatOfficial.Server.Notify(r, func(event contract.EventInterface) interface{} {
switch event.GetMsgType() {
case models2.CALLBACK_MSG_TYPE_EVENT:
switch event.GetEvent() {
case models.CALLBACK_EVENT_SUBSCRIBE:
msg := models.EventSubscribe{}
err := event.ReadMessage(&msg)
if err != nil {
logx.Error(err.Error())
return "error"
}
key := strings.TrimPrefix(msg.EventKey, "qrscene_")
err = l.SendMessage(msg.FromUserName, key)
if err != nil {
return messages.NewText(i18n.FormatText(l.ctx, "login.loginFailed"))
}
return messages.NewText(i18n.FormatText(l.ctx, "login.loginSuccess"))
case models.CALLBACK_EVENT_UNSUBSCRIBE:
msg := models.EventUnSubscribe{}
err := event.ReadMessage(&msg)
if err != nil {
logx.Error(err.Error())
return "error"
}
return messages.NewText("ok")
case models.CALLBACK_EVENT_SCAN:
msg := models.EventScan{}
err := event.ReadMessage(&msg)
if err != nil {
logx.Error(err.Error())
return "error"
}
err = l.SendMessage(msg.FromUserName, msg.EventKey)
if err != nil {
return messages.NewText(i18n.FormatText(l.ctx, "login.loginFailed"))
}
return messages.NewText(i18n.FormatText(l.ctx, "login.loginSuccess"))
}
case models2.CALLBACK_MSG_TYPE_TEXT:
msg := models.MessageText{}
err := event.ReadMessage(&msg)
if err != nil {
logx.Error(err.Error())
return "error"
}
}
return messages.NewText("ok")
})
if err != nil {
return nil, err
}
return rs, nil
}
// SendMessage 发送消息到客户端
func (l *WechatOffiaccountCallbackLogic) SendMessage(openId string, clientId string) error {
messageData := MessageData{
Openid: openId,
ClientId: clientId,
}
jsonData, err := json.Marshal(response.SuccessWithData(messageData))
if err != nil {
return err
}
err = websocket.QrcodeWebSocketHandler.SendMessageToClient(clientId, jsonData)
if err != nil {
return err
}
return nil
}

View File

@@ -0,0 +1,31 @@
package oauth
import (
"context"
"net/http"
"github.com/zeromicro/go-zero/core/logx"
"schisandra-album-cloud-microservices/app/core/api/internal/svc"
)
type WechatOffiaccountCallbackVerifyLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewWechatOffiaccountCallbackVerifyLogic(ctx context.Context, svcCtx *svc.ServiceContext) *WechatOffiaccountCallbackVerifyLogic {
return &WechatOffiaccountCallbackVerifyLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *WechatOffiaccountCallbackVerifyLogic) WechatOffiaccountCallbackVerify(r *http.Request) (*http.Response, error) {
rs, err := l.svcCtx.WechatOfficial.Server.VerifyURL(r)
if err != nil {
return nil, err
}
return rs, nil
}

View File

@@ -30,12 +30,8 @@ func NewRefreshTokenLogic(ctx context.Context, svcCtx *svc.ServiceContext) *Refr
}
func (l *RefreshTokenLogic) RefreshToken(r *http.Request) (resp *types.Response, err error) {
session, err := l.svcCtx.Session.Get(r, constant.SESSION_KEY)
if err != nil {
return nil, err
}
userId, ok := session.Values["user_id"].(string)
if !ok {
userId := r.Header.Get(constant.UID_HEADER_KEY)
if userId == "" {
return response.ErrorWithCode(403), nil
}
tokenData := l.svcCtx.RedisClient.Get(l.ctx, constant.UserTokenPrefix+userId).Val()
@@ -47,6 +43,9 @@ func (l *RefreshTokenLogic) RefreshToken(r *http.Request) (resp *types.Response,
if err != nil {
return nil, err
}
if redisTokenData.Revoked {
return response.ErrorWithCode(403), nil
}
refreshToken, result := jwt.ParseRefreshToken(l.svcCtx.Config.Auth.AccessSecret, redisTokenData.RefreshToken)
if !result {
return response.ErrorWithCode(403), nil
@@ -62,6 +61,7 @@ func (l *RefreshTokenLogic) RefreshToken(r *http.Request) (resp *types.Response,
AccessToken: accessToken,
RefreshToken: redisTokenData.RefreshToken,
UID: refreshToken.UserID,
Revoked: false,
}
err = l.svcCtx.RedisClient.Set(l.ctx, constant.UserTokenPrefix+refreshToken.UserID, redisToken, time.Hour*24*7).Err()
if err != nil {

View File

@@ -3,7 +3,8 @@ package user
import (
"context"
"errors"
"github.com/rbcervilla/redisstore/v9"
"github.com/lionsoul2014/ip2region/binding/golang/xdb"
"github.com/mssola/useragent"
"net/http"
"time"
@@ -65,19 +66,20 @@ func (l *AccountLoginLogic) AccountLogin(w http.ResponseWriter, r *http.Request,
if !utils.Verify(userInfo.Password, req.Password) {
return response.ErrorWithI18n(l.ctx, "login.invalidPassword"), nil
}
data, err := HandleUserLogin(userInfo, l.svcCtx, req.AutoLogin, r, w, l.ctx)
data, err := HandleLoginJWT(userInfo, l.svcCtx, req.AutoLogin, r, l.ctx)
if err != nil {
return nil, err
}
// 记录用户登录设备
if err = GetUserLoginDevice(userInfo.UID, r, l.svcCtx.Ip2Region, l.svcCtx.DB); err != nil {
return nil, err
}
return response.SuccessWithData(data), nil
}
// HandleUserLogin 处理用户登录
func HandleUserLogin(user *model.ScaAuthUser, svcCtx *svc.ServiceContext, autoLogin bool, r *http.Request, w http.ResponseWriter, ctx context.Context) (*types.LoginResponse, error) {
// HandleLoginJWT 处理用户登录
func HandleLoginJWT(user *model.ScaAuthUser, svcCtx *svc.ServiceContext, autoLogin bool, r *http.Request, ctx context.Context) (*types.LoginResponse, error) {
// 获取用户登录设备
err := GetUserLoginDevice(user.UID, r, svcCtx.Ip2Region, svcCtx.DB)
if err != nil {
return nil, err
}
// 生成jwt token
accessToken := jwt.GenerateAccessToken(svcCtx.Config.Auth.AccessSecret, jwt.AccessJWTPayload{
UserID: user.UID,
@@ -85,9 +87,9 @@ func HandleUserLogin(user *model.ScaAuthUser, svcCtx *svc.ServiceContext, autoLo
})
var days time.Duration
if autoLogin {
days = 7 * 24 * time.Hour
days = 24 * time.Hour
} else {
days = time.Hour * 24
days = time.Hour * 1
}
refreshToken := jwt.GenerateRefreshToken(svcCtx.Config.Auth.AccessSecret, jwt.RefreshJWTPayload{
UserID: user.UID,
@@ -106,29 +108,76 @@ func HandleUserLogin(user *model.ScaAuthUser, svcCtx *svc.ServiceContext, autoLo
AccessToken: accessToken,
RefreshToken: refreshToken,
UID: user.UID,
Revoked: false,
}
err := svcCtx.RedisClient.Set(ctx, constant.UserTokenPrefix+user.UID, redisToken, days).Err()
if err != nil {
return nil, err
}
err = HandlerSession(r, w, user.UID, svcCtx.Session)
err = svcCtx.RedisClient.Set(ctx, constant.UserTokenPrefix+user.UID, redisToken, days).Err()
if err != nil {
return nil, err
}
return &data, nil
}
// HandlerSession is a function to set the user_id in the session
func HandlerSession(r *http.Request, w http.ResponseWriter, userID string, redisSession *redisstore.RedisStore) error {
session, err := redisSession.Get(r, constant.SESSION_KEY)
// GetUserLoginDevice 获取用户登录设备
func GetUserLoginDevice(userId string, r *http.Request, ip2location *xdb.Searcher, DB *query.Query) error {
userAgent := r.UserAgent()
if userAgent == "" {
return errors.New("user agent not found")
}
ip := utils.GetClientIP(r)
location, err := ip2location.SearchByStr(ip)
if err != nil {
return err
}
session.Values["user_id"] = userID
err = session.Save(r, w)
if err != nil {
location = utils.RemoveZeroAndAdjust(location)
ua := useragent.New(userAgent)
isBot := ua.Bot()
browser, browserVersion := ua.Browser()
os := ua.OS()
mobile := ua.Mobile()
mozilla := ua.Mozilla()
platform := ua.Platform()
engine, engineVersion := ua.Engine()
var newIsBot int64 = 0
var newIsMobile int64 = 0
if isBot {
newIsBot = 1
}
if mobile {
newIsMobile = 1
}
userDevice := DB.ScaAuthUserDevice
device, err := userDevice.Where(userDevice.UserID.Eq(userId), userDevice.IP.Eq(ip), userDevice.Agent.Eq(userAgent)).First()
if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
return err
}
return nil
newDevice := &model.ScaAuthUserDevice{
UserID: userId,
Bot: newIsBot,
Agent: userAgent,
Browser: browser,
BrowserVersion: browserVersion,
EngineName: engine,
EngineVersion: engineVersion,
IP: ip,
Location: location,
OperatingSystem: os,
Mobile: newIsMobile,
Mozilla: mozilla,
Platform: platform,
}
if device == nil {
// 创建新的设备记录
err = DB.ScaAuthUserDevice.Create(newDevice)
if err != nil {
return err
}
return nil
} else {
resultInfo, err := userDevice.Where(userDevice.ID.Eq(device.ID)).Updates(newDevice)
if err != nil || resultInfo.RowsAffected == 0 {
return errors.New("update device failed")
}
return nil
}
}

View File

@@ -1,115 +0,0 @@
package user
import (
"context"
"errors"
"github.com/lionsoul2014/ip2region/binding/golang/xdb"
"github.com/mssola/useragent"
"gorm.io/gorm"
"net/http"
"schisandra-album-cloud-microservices/app/core/api/common/jwt"
"schisandra-album-cloud-microservices/app/core/api/common/response"
"schisandra-album-cloud-microservices/app/core/api/common/utils"
"schisandra-album-cloud-microservices/app/core/api/repository/mysql/model"
"schisandra-album-cloud-microservices/app/core/api/repository/mysql/query"
"schisandra-album-cloud-microservices/app/core/api/internal/svc"
"schisandra-album-cloud-microservices/app/core/api/internal/types"
"github.com/zeromicro/go-zero/core/logx"
)
type GetUserDeviceLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewGetUserDeviceLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetUserDeviceLogic {
return &GetUserDeviceLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *GetUserDeviceLogic) GetUserDevice(r *http.Request, w http.ResponseWriter, req *types.UserDeviceRequest) (resp *types.Response, err error) {
token, ok := jwt.ParseAccessToken(l.svcCtx.Config.Auth.AccessSecret, req.AccessToken)
if !ok {
return response.Error(), nil
}
err = HandlerSession(r, w, token.UserID, l.svcCtx.Session)
if err != nil {
return nil, err
}
err = GetUserLoginDevice(token.UserID, r, l.svcCtx.Ip2Region, l.svcCtx.DB)
if err != nil {
return nil, err
}
return response.Success(), nil
}
// GetUserLoginDevice 获取用户登录设备
func GetUserLoginDevice(userId string, r *http.Request, ip2location *xdb.Searcher, DB *query.Query) error {
userAgent := r.Header.Get("User-Agent")
if userAgent == "" {
return errors.New("user agent not found")
}
ip := utils.GetClientIP(r)
location, err := ip2location.SearchByStr(ip)
if err != nil {
return err
}
location = utils.RemoveZeroAndAdjust(location)
ua := useragent.New(userAgent)
isBot := ua.Bot()
browser, browserVersion := ua.Browser()
os := ua.OS()
mobile := ua.Mobile()
mozilla := ua.Mozilla()
platform := ua.Platform()
engine, engineVersion := ua.Engine()
var newIsBot int64 = 0
var newIsMobile int64 = 0
if isBot {
newIsBot = 1
}
if mobile {
newIsMobile = 1
}
userDevice := DB.ScaAuthUserDevice
device, err := userDevice.Where(userDevice.UserID.Eq(userId), userDevice.IP.Eq(ip), userDevice.Agent.Eq(userAgent)).First()
if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
return err
}
newDevice := &model.ScaAuthUserDevice{
UserID: userId,
Bot: newIsBot,
Agent: userAgent,
Browser: browser,
BrowserVersion: browserVersion,
EngineName: engine,
EngineVersion: engineVersion,
IP: ip,
Location: location,
OperatingSystem: os,
Mobile: newIsMobile,
Mozilla: mozilla,
Platform: platform,
}
if device == nil {
// 创建新的设备记录
err = DB.ScaAuthUserDevice.Create(newDevice)
if err != nil {
return err
}
return nil
} else {
resultInfo, err := userDevice.Where(userDevice.ID.Eq(device.ID)).Updates(newDevice)
if err != nil || resultInfo.RowsAffected == 0 {
return errors.New("update device failed")
}
return nil
}
}

View File

@@ -1,37 +1,36 @@
package oauth
package user
import (
"context"
"encoding/json"
"net/http"
"time"
"github.com/ArtisanCloud/PowerWeChat/v3/src/basicService/qrCode/response"
"net/http"
"schisandra-album-cloud-microservices/app/core/api/common/constant"
response2 "schisandra-album-cloud-microservices/app/core/api/common/response"
"schisandra-album-cloud-microservices/app/core/api/common/utils"
"time"
"schisandra-album-cloud-microservices/app/core/api/internal/svc"
"schisandra-album-cloud-microservices/app/core/api/internal/types"
"github.com/zeromicro/go-zero/core/logx"
)
type GetWechatQrcodeLogic struct {
type GetWechatOffiaccountQrcodeLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewGetWechatQrcodeLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetWechatQrcodeLogic {
return &GetWechatQrcodeLogic{
func NewGetWechatOffiaccountQrcodeLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetWechatOffiaccountQrcodeLogic {
return &GetWechatOffiaccountQrcodeLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *GetWechatQrcodeLogic) GetWechatQrcode(r *http.Request, req *types.OAuthWechatRequest) (resp *types.Response, err error) {
func (l *GetWechatOffiaccountQrcodeLogic) GetWechatOffiaccountQrcode(r *http.Request, req *types.OAuthWechatRequest) (resp *types.Response, err error) {
ip := utils.GetClientIP(r) // 使用工具函数获取客户端IP
key := constant.UserQrcodePrefix + ip
@@ -46,7 +45,7 @@ func (l *GetWechatQrcodeLogic) GetWechatQrcode(r *http.Request, req *types.OAuth
}
// 生成临时二维码
data, err := l.svcCtx.WechatPublic.QRCode.Temporary(l.ctx, req.Client_id, 7*24*3600)
data, err := l.svcCtx.WechatOfficial.QRCode.Temporary(l.ctx, req.Client_id, 7*24*3600)
if err != nil {
return nil, err
}

View File

@@ -79,32 +79,22 @@ func (l *PhoneLoginLogic) PhoneLogin(r *http.Request, w http.ResponseWriter, req
_ = tx.Rollback()
return nil, err
}
data, err := HandleUserLogin(user, l.svcCtx, req.AutoLogin, r, w, l.ctx)
data, err := HandleLoginJWT(user, l.svcCtx, req.AutoLogin, r, l.ctx)
if err != nil {
_ = tx.Rollback()
return nil, err
}
// 记录用户登录设备
if err = GetUserLoginDevice(user.UID, r, l.svcCtx.Ip2Region, l.svcCtx.DB); err != nil {
_ = tx.Rollback()
return nil, err
}
err = tx.Commit()
if err != nil {
return nil, err
}
return response.SuccessWithData(data), nil
} else {
data, err := HandleUserLogin(userInfo, l.svcCtx, req.AutoLogin, r, w, l.ctx)
data, err := HandleLoginJWT(userInfo, l.svcCtx, req.AutoLogin, r, l.ctx)
if err != nil {
_ = tx.Rollback()
return nil, err
}
// 记录用户登录设备
if err = GetUserLoginDevice(userInfo.UID, r, l.svcCtx.Ip2Region, l.svcCtx.DB); err != nil {
_ = tx.Rollback()
return nil, err
}
err = tx.Commit()
if err != nil {
return nil, err

View File

@@ -0,0 +1,107 @@
package user
import (
"context"
"errors"
"github.com/yitter/idgenerator-go/idgen"
"gorm.io/gorm"
"net/http"
"schisandra-album-cloud-microservices/app/core/api/common/constant"
randomname "schisandra-album-cloud-microservices/app/core/api/common/random_name"
"schisandra-album-cloud-microservices/app/core/api/common/response"
"schisandra-album-cloud-microservices/app/core/api/common/utils"
"schisandra-album-cloud-microservices/app/core/api/repository/mysql/model"
"strconv"
"schisandra-album-cloud-microservices/app/core/api/internal/svc"
"schisandra-album-cloud-microservices/app/core/api/internal/types"
"github.com/zeromicro/go-zero/core/logx"
)
type WechatOffiaccountLoginLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewWechatOffiaccountLoginLogic(ctx context.Context, svcCtx *svc.ServiceContext) *WechatOffiaccountLoginLogic {
return &WechatOffiaccountLoginLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *WechatOffiaccountLoginLogic) WechatOffiaccountLogin(r *http.Request, req *types.WechatOffiaccountLoginRequest) (resp *types.Response, err error) {
tx := l.svcCtx.DB.Begin()
userSocial := l.svcCtx.DB.ScaAuthUserSocial
socialUser, err := tx.ScaAuthUserSocial.Where(userSocial.OpenID.Eq(req.Openid), userSocial.Source.Eq(constant.OAuthSourceWechat)).First()
if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
return nil, err
}
if socialUser == nil {
// 创建用户
uid := idgen.NextId()
uidStr := strconv.FormatInt(uid, 10)
avatar := utils.GenerateAvatar(uidStr)
name := randomname.GenerateName()
addUser := &model.ScaAuthUser{
UID: uidStr,
Avatar: avatar,
Username: req.Openid,
Nickname: name,
Gender: constant.Male,
}
err = tx.ScaAuthUser.Create(addUser)
if err != nil {
_ = tx.Rollback()
return nil, err
}
newSocialUser := &model.ScaAuthUserSocial{
UserID: uidStr,
OpenID: req.Openid,
Source: constant.OAuthSourceWechat,
}
err = tx.ScaAuthUserSocial.Create(newSocialUser)
if err != nil {
_ = tx.Rollback()
return nil, err
}
if res, err := l.svcCtx.CasbinEnforcer.AddRoleForUser(uidStr, constant.User); !res || err != nil {
_ = tx.Rollback()
return nil, err
}
data, err := HandleLoginJWT(addUser, l.svcCtx, true, r, l.ctx)
if err != nil {
_ = tx.Rollback()
return nil, err
}
if err = tx.Commit(); err != nil {
return nil, err
}
return response.SuccessWithData(data), nil
} else {
authUser := l.svcCtx.DB.ScaAuthUser
authUserInfo, err := tx.ScaAuthUser.Where(authUser.UID.Eq(socialUser.UserID)).First()
if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
_ = tx.Rollback()
return nil, err
}
data, err := HandleLoginJWT(authUserInfo, l.svcCtx, true, r, l.ctx)
if err != nil {
_ = tx.Rollback()
return nil, err
}
if err = tx.Commit(); err != nil {
return nil, err
}
return response.SuccessWithData(data), nil
}
}

View File

@@ -0,0 +1,31 @@
package middleware
import (
"github.com/redis/go-redis/v9"
"github.com/zeromicro/go-zero/rest/httpx"
"net/http"
"schisandra-album-cloud-microservices/app/core/api/common/constant"
"schisandra-album-cloud-microservices/app/core/api/common/response"
)
type AuthorizationMiddleware struct {
Redis *redis.Client
}
func NewAuthorizationMiddleware(redis *redis.Client) *AuthorizationMiddleware {
return &AuthorizationMiddleware{
Redis: redis,
}
}
func (m *AuthorizationMiddleware) Handle(next http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
userId := r.Context().Value("user_id").(string)
redisToken := m.Redis.Get(r.Context(), constant.UserTokenPrefix+userId).Val()
if redisToken == "" {
httpx.OkJson(w, response.ErrorWithCodeMessage(403, "unauthorized"))
return
}
next(w, r)
}
}

View File

@@ -1,37 +1,24 @@
package middleware
import (
"github.com/casbin/casbin/v2"
"net/http"
"schisandra-album-cloud-microservices/app/core/api/common/constant"
"github.com/casbin/casbin/v2"
"github.com/rbcervilla/redisstore/v9"
)
type CasbinVerifyMiddleware struct {
casbin *casbin.SyncedCachedEnforcer
session *redisstore.RedisStore
casbin *casbin.SyncedCachedEnforcer
}
func NewCasbinVerifyMiddleware(casbin *casbin.SyncedCachedEnforcer, session *redisstore.RedisStore) *CasbinVerifyMiddleware {
func NewCasbinVerifyMiddleware(casbin *casbin.SyncedCachedEnforcer) *CasbinVerifyMiddleware {
return &CasbinVerifyMiddleware{
casbin: casbin,
session: session,
casbin: casbin,
}
}
func (m *CasbinVerifyMiddleware) Handle(next http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
session, err := m.session.Get(r, constant.SESSION_KEY)
if err != nil {
http.Error(w, http.StatusText(http.StatusForbidden), http.StatusForbidden)
return
}
userId, ok := session.Values["user_id"].(string)
if !ok {
http.Error(w, http.StatusText(http.StatusForbidden), http.StatusForbidden)
return
}
userId := r.Header.Get(constant.UID_HEADER_KEY)
correct, err := m.casbin.Enforce(userId, r.URL.Path, r.Method)
if err != nil || !correct {
http.Error(w, http.StatusText(http.StatusForbidden), http.StatusForbidden)

View File

@@ -4,7 +4,6 @@ import (
"github.com/ArtisanCloud/PowerWeChat/v3/src/officialAccount"
"github.com/casbin/casbin/v2"
"github.com/lionsoul2014/ip2region/binding/golang/xdb"
"github.com/rbcervilla/redisstore/v9"
"github.com/redis/go-redis/v9"
"github.com/wenlng/go-captcha/v2/rotate"
"github.com/wenlng/go-captcha/v2/slide"
@@ -20,7 +19,6 @@ import (
"schisandra-album-cloud-microservices/app/core/api/repository/mongodb"
"schisandra-album-cloud-microservices/app/core/api/repository/mysql"
"schisandra-album-cloud-microservices/app/core/api/repository/mysql/query"
"schisandra-album-cloud-microservices/app/core/api/repository/redis_session"
"schisandra-album-cloud-microservices/app/core/api/repository/redisx"
"schisandra-album-cloud-microservices/app/core/api/repository/sensitivex"
"schisandra-album-cloud-microservices/app/core/api/repository/wechat_official"
@@ -30,13 +28,13 @@ type ServiceContext struct {
Config config.Config
SecurityHeadersMiddleware rest.Middleware
CasbinVerifyMiddleware rest.Middleware
AuthorizationMiddleware rest.Middleware
DB *query.Query
RedisClient *redis.Client
MongoClient *mongo.Database
Session *redisstore.RedisStore
Ip2Region *xdb.Searcher
CasbinEnforcer *casbin.SyncedCachedEnforcer
WechatPublic *officialAccount.OfficialAccount
WechatOfficial *officialAccount.OfficialAccount
Sensitive *sensitive.Manager
RotateCaptcha rotate.Captcha
SlideCaptcha slide.Captcha
@@ -46,18 +44,17 @@ func NewServiceContext(c config.Config) *ServiceContext {
redisClient := redisx.NewRedis(c.Redis.Host, c.Redis.Pass, c.Redis.DB)
db, queryDB := mysql.NewMySQL(c.Mysql.DataSource, c.Mysql.MaxOpenConn, c.Mysql.MaxIdleConn, redisClient)
casbinEnforcer := casbinx.NewCasbin(db)
session := redis_session.NewRedisSession(redisClient)
return &ServiceContext{
Config: c,
SecurityHeadersMiddleware: middleware.NewSecurityHeadersMiddleware().Handle,
CasbinVerifyMiddleware: middleware.NewCasbinVerifyMiddleware(casbinEnforcer, session).Handle,
CasbinVerifyMiddleware: middleware.NewCasbinVerifyMiddleware(casbinEnforcer).Handle,
AuthorizationMiddleware: middleware.NewAuthorizationMiddleware(redisClient).Handle,
DB: queryDB,
RedisClient: redisClient,
MongoClient: mongodb.NewMongoDB(c.Mongo.Uri, c.Mongo.Username, c.Mongo.Password, c.Mongo.AuthSource, c.Mongo.Database),
Session: session,
Ip2Region: ip2region.NewIP2Region(),
CasbinEnforcer: casbinEnforcer,
WechatPublic: wechat_official.NewWechatPublic(c.Wechat.AppID, c.Wechat.AppSecret, c.Wechat.Token, c.Wechat.AESKey, c.Redis.Host, c.Redis.Pass, c.Redis.DB),
WechatOfficial: wechat_official.NewWechatPublic(c.Wechat.AppID, c.Wechat.AppSecret, c.Wechat.Token, c.Wechat.AESKey, c.Redis.Host, c.Redis.Pass, c.Redis.DB),
Sensitive: sensitivex.NewSensitive(),
RotateCaptcha: captcha.NewRotateCaptcha(),
SlideCaptcha: captcha.NewSlideCaptcha(),

View File

@@ -6,6 +6,7 @@ type RedisToken struct {
AccessToken string `json:"access_token"`
RefreshToken string `json:"refresh_token"`
UID string `json:"uid"`
Revoked bool `json:"revoked" default:"false"`
}
func (res RedisToken) MarshalBinary() ([]byte, error) {

View File

@@ -119,6 +119,7 @@ type UploadRequest struct {
UserId string `json:"user_id"`
}
type UserDeviceRequest struct {
AccessToken string `json:"access_token"`
type WechatOffiaccountLoginRequest struct {
Openid string `json:"openid"`
ClientId string `json:"client_id"`
}

View File

@@ -1,28 +0,0 @@
package redis_session
import (
"context"
"net/http"
"github.com/gorilla/sessions"
"github.com/rbcervilla/redisstore/v9"
"github.com/redis/go-redis/v9"
"schisandra-album-cloud-microservices/app/core/api/common/constant"
)
func NewRedisSession(client *redis.Client) *redisstore.RedisStore {
store, err := redisstore.NewRedisStore(context.Background(), client)
if err != nil {
panic(err)
}
store.KeyPrefix(constant.UserSessionPrefix)
store.Options(sessions.Options{
Path: "/",
MaxAge: 86400 * 7,
HttpOnly: true,
Secure: true,
SameSite: http.SameSiteLaxMode,
})
return store
}