♻️ reconstruct the authentication mode
This commit is contained in:
96
.idea/GOHCache.xml
generated
96
.idea/GOHCache.xml
generated
@@ -17,6 +17,13 @@
|
|||||||
</set>
|
</set>
|
||||||
</value>
|
</value>
|
||||||
</entry>
|
</entry>
|
||||||
|
<entry key="AccessToken">
|
||||||
|
<value>
|
||||||
|
<set>
|
||||||
|
<option value="file://$PROJECT_DIR$/app/core/api/internal/logic/token/refresh_token_logic.go" />
|
||||||
|
</set>
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
<entry key="AccountLoginLogic">
|
<entry key="AccountLoginLogic">
|
||||||
<value>
|
<value>
|
||||||
<set>
|
<set>
|
||||||
@@ -313,6 +320,13 @@
|
|||||||
</set>
|
</set>
|
||||||
</value>
|
</value>
|
||||||
</entry>
|
</entry>
|
||||||
|
<entry key="NonceMiddleware">
|
||||||
|
<value>
|
||||||
|
<set>
|
||||||
|
<option value="file://$PROJECT_DIR$/app/core/api/internal/middleware/nonce_middleware.go" />
|
||||||
|
</set>
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
<entry key="OAuthCallbackRequest">
|
<entry key="OAuthCallbackRequest">
|
||||||
<value>
|
<value>
|
||||||
<set>
|
<set>
|
||||||
@@ -740,6 +754,13 @@
|
|||||||
</set>
|
</set>
|
||||||
</value>
|
</value>
|
||||||
</entry>
|
</entry>
|
||||||
|
<entry key="WechatOffiaccountLoginRequest">
|
||||||
|
<value>
|
||||||
|
<set>
|
||||||
|
<option value="file://$PROJECT_DIR$/app/core/api/internal/types/types.go" />
|
||||||
|
</set>
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
<entry key="baseXmlResponse">
|
<entry key="baseXmlResponse">
|
||||||
<value>
|
<value>
|
||||||
<set>
|
<set>
|
||||||
@@ -1076,7 +1097,14 @@
|
|||||||
<entry key="file://$PROJECT_DIR$/app/core/api/common/constant/redis_prefix.go">
|
<entry key="file://$PROJECT_DIR$/app/core/api/common/constant/redis_prefix.go">
|
||||||
<value>
|
<value>
|
||||||
<ScannedPath>
|
<ScannedPath>
|
||||||
<option name="lastModified" value="1731581334503" />
|
<option name="lastModified" value="1734750443057" />
|
||||||
|
</ScannedPath>
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
|
<entry key="file://$PROJECT_DIR$/app/core/api/common/constant/time.go">
|
||||||
|
<value>
|
||||||
|
<ScannedPath>
|
||||||
|
<option name="lastModified" value="1734753572318" />
|
||||||
</ScannedPath>
|
</ScannedPath>
|
||||||
</value>
|
</value>
|
||||||
</entry>
|
</entry>
|
||||||
@@ -1094,6 +1122,13 @@
|
|||||||
</ScannedPath>
|
</ScannedPath>
|
||||||
</value>
|
</value>
|
||||||
</entry>
|
</entry>
|
||||||
|
<entry key="file://$PROJECT_DIR$/app/core/api/common/encrypt/aes.go">
|
||||||
|
<value>
|
||||||
|
<ScannedPath>
|
||||||
|
<option name="lastModified" value="1734746896453" />
|
||||||
|
</ScannedPath>
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
<entry key="file://$PROJECT_DIR$/app/core/api/common/errors/errors.go">
|
<entry key="file://$PROJECT_DIR$/app/core/api/common/errors/errors.go">
|
||||||
<value>
|
<value>
|
||||||
<ScannedPath>
|
<ScannedPath>
|
||||||
@@ -1195,7 +1230,7 @@
|
|||||||
<entry key="file://$PROJECT_DIR$/app/core/api/common/jwt/access_token.go">
|
<entry key="file://$PROJECT_DIR$/app/core/api/common/jwt/access_token.go">
|
||||||
<value>
|
<value>
|
||||||
<ScannedPath>
|
<ScannedPath>
|
||||||
<option name="lastModified" value="1734682778489" />
|
<option name="lastModified" value="1734756247281" />
|
||||||
<option name="schema">
|
<option name="schema">
|
||||||
<list>
|
<list>
|
||||||
<option value="AccessJWTPayload" />
|
<option value="AccessJWTPayload" />
|
||||||
@@ -1221,7 +1256,7 @@
|
|||||||
<entry key="file://$PROJECT_DIR$/app/core/api/common/jwt/websocket_token.go">
|
<entry key="file://$PROJECT_DIR$/app/core/api/common/jwt/websocket_token.go">
|
||||||
<value>
|
<value>
|
||||||
<ScannedPath>
|
<ScannedPath>
|
||||||
<option name="lastModified" value="1734685303630" />
|
<option name="lastModified" value="1734757072652" />
|
||||||
<option name="schema">
|
<option name="schema">
|
||||||
<list>
|
<list>
|
||||||
<option value="WebsocketJWTPayload" />
|
<option value="WebsocketJWTPayload" />
|
||||||
@@ -1234,7 +1269,7 @@
|
|||||||
<entry key="file://$PROJECT_DIR$/app/core/api/common/middleware/cors_middleware.go">
|
<entry key="file://$PROJECT_DIR$/app/core/api/common/middleware/cors_middleware.go">
|
||||||
<value>
|
<value>
|
||||||
<ScannedPath>
|
<ScannedPath>
|
||||||
<option name="lastModified" value="1734682151710" />
|
<option name="lastModified" value="1734755743115" />
|
||||||
</ScannedPath>
|
</ScannedPath>
|
||||||
</value>
|
</value>
|
||||||
</entry>
|
</entry>
|
||||||
@@ -1259,6 +1294,13 @@
|
|||||||
</ScannedPath>
|
</ScannedPath>
|
||||||
</value>
|
</value>
|
||||||
</entry>
|
</entry>
|
||||||
|
<entry key="file://$PROJECT_DIR$/app/core/api/common/middleware/unsigned_callback_middleware.go">
|
||||||
|
<value>
|
||||||
|
<ScannedPath>
|
||||||
|
<option name="lastModified" value="1734716219341" />
|
||||||
|
</ScannedPath>
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
<entry key="file://$PROJECT_DIR$/app/core/api/common/random_name/actsomething.go">
|
<entry key="file://$PROJECT_DIR$/app/core/api/common/random_name/actsomething.go">
|
||||||
<value>
|
<value>
|
||||||
<ScannedPath>
|
<ScannedPath>
|
||||||
@@ -1365,7 +1407,7 @@
|
|||||||
<entry key="file://$PROJECT_DIR$/app/core/api/core.go">
|
<entry key="file://$PROJECT_DIR$/app/core/api/core.go">
|
||||||
<value>
|
<value>
|
||||||
<ScannedPath>
|
<ScannedPath>
|
||||||
<option name="lastModified" value="1734693433014" />
|
<option name="lastModified" value="1734716174504" />
|
||||||
</ScannedPath>
|
</ScannedPath>
|
||||||
</value>
|
</value>
|
||||||
</entry>
|
</entry>
|
||||||
@@ -1379,7 +1421,7 @@
|
|||||||
<entry key="file://$PROJECT_DIR$/app/core/api/internal/config/config.go">
|
<entry key="file://$PROJECT_DIR$/app/core/api/internal/config/config.go">
|
||||||
<value>
|
<value>
|
||||||
<ScannedPath>
|
<ScannedPath>
|
||||||
<option name="lastModified" value="1732080315861" />
|
<option name="lastModified" value="1734714088072" />
|
||||||
<option name="schema">
|
<option name="schema">
|
||||||
<list>
|
<list>
|
||||||
<option value="Config" />
|
<option value="Config" />
|
||||||
@@ -1545,7 +1587,7 @@
|
|||||||
<entry key="file://$PROJECT_DIR$/app/core/api/internal/handler/routes.go">
|
<entry key="file://$PROJECT_DIR$/app/core/api/internal/handler/routes.go">
|
||||||
<value>
|
<value>
|
||||||
<ScannedPath>
|
<ScannedPath>
|
||||||
<option name="lastModified" value="1734712935626" />
|
<option name="lastModified" value="1734715543981" />
|
||||||
</ScannedPath>
|
</ScannedPath>
|
||||||
</value>
|
</value>
|
||||||
</entry>
|
</entry>
|
||||||
@@ -1698,7 +1740,7 @@
|
|||||||
<entry key="file://$PROJECT_DIR$/app/core/api/internal/logic/comment/get_comment_list_logic.go">
|
<entry key="file://$PROJECT_DIR$/app/core/api/internal/logic/comment/get_comment_list_logic.go">
|
||||||
<value>
|
<value>
|
||||||
<ScannedPath>
|
<ScannedPath>
|
||||||
<option name="lastModified" value="1732187874238" />
|
<option name="lastModified" value="1734752546625" />
|
||||||
<option name="schema">
|
<option name="schema">
|
||||||
<list>
|
<list>
|
||||||
<option value="GetCommentListLogic" />
|
<option value="GetCommentListLogic" />
|
||||||
@@ -1897,7 +1939,7 @@
|
|||||||
<entry key="file://$PROJECT_DIR$/app/core/api/internal/logic/oauth/wechat_offiaccount_callback_logic.go">
|
<entry key="file://$PROJECT_DIR$/app/core/api/internal/logic/oauth/wechat_offiaccount_callback_logic.go">
|
||||||
<value>
|
<value>
|
||||||
<ScannedPath>
|
<ScannedPath>
|
||||||
<option name="lastModified" value="1734712747630" />
|
<option name="lastModified" value="1734747356974" />
|
||||||
<option name="schema">
|
<option name="schema">
|
||||||
<list>
|
<list>
|
||||||
<option value="WechatOffiaccountCallbackLogic" />
|
<option value="WechatOffiaccountCallbackLogic" />
|
||||||
@@ -1958,10 +2000,11 @@
|
|||||||
<entry key="file://$PROJECT_DIR$/app/core/api/internal/logic/token/refresh_token_logic.go">
|
<entry key="file://$PROJECT_DIR$/app/core/api/internal/logic/token/refresh_token_logic.go">
|
||||||
<value>
|
<value>
|
||||||
<ScannedPath>
|
<ScannedPath>
|
||||||
<option name="lastModified" value="1734692914876" />
|
<option name="lastModified" value="1734755189078" />
|
||||||
<option name="schema">
|
<option name="schema">
|
||||||
<list>
|
<list>
|
||||||
<option value="RefreshTokenLogic" />
|
<option value="RefreshTokenLogic" />
|
||||||
|
<option value="AccessToken" />
|
||||||
</list>
|
</list>
|
||||||
</option>
|
</option>
|
||||||
</ScannedPath>
|
</ScannedPath>
|
||||||
@@ -1982,7 +2025,7 @@
|
|||||||
<entry key="file://$PROJECT_DIR$/app/core/api/internal/logic/user/account_login_logic.go">
|
<entry key="file://$PROJECT_DIR$/app/core/api/internal/logic/user/account_login_logic.go">
|
||||||
<value>
|
<value>
|
||||||
<ScannedPath>
|
<ScannedPath>
|
||||||
<option name="lastModified" value="1734709587740" />
|
<option name="lastModified" value="1734756271140" />
|
||||||
<option name="schema">
|
<option name="schema">
|
||||||
<list>
|
<list>
|
||||||
<option value="AccountLoginLogic" />
|
<option value="AccountLoginLogic" />
|
||||||
@@ -2006,7 +2049,7 @@
|
|||||||
<entry key="file://$PROJECT_DIR$/app/core/api/internal/logic/user/get_wechat_offiaccount_qrcode_logic.go">
|
<entry key="file://$PROJECT_DIR$/app/core/api/internal/logic/user/get_wechat_offiaccount_qrcode_logic.go">
|
||||||
<value>
|
<value>
|
||||||
<ScannedPath>
|
<ScannedPath>
|
||||||
<option name="lastModified" value="1734712935637" />
|
<option name="lastModified" value="1734754660785" />
|
||||||
<option name="schema">
|
<option name="schema">
|
||||||
<list>
|
<list>
|
||||||
<option value="GetWechatOffiaccountQrcodeLogic" />
|
<option value="GetWechatOffiaccountQrcodeLogic" />
|
||||||
@@ -2042,7 +2085,7 @@
|
|||||||
<entry key="file://$PROJECT_DIR$/app/core/api/internal/logic/user/wechat_offiaccount_login_logic.go">
|
<entry key="file://$PROJECT_DIR$/app/core/api/internal/logic/user/wechat_offiaccount_login_logic.go">
|
||||||
<value>
|
<value>
|
||||||
<ScannedPath>
|
<ScannedPath>
|
||||||
<option name="lastModified" value="1734711022532" />
|
<option name="lastModified" value="1734747514069" />
|
||||||
<option name="schema">
|
<option name="schema">
|
||||||
<list>
|
<list>
|
||||||
<option value="WechatOffiaccountLoginLogic" />
|
<option value="WechatOffiaccountLoginLogic" />
|
||||||
@@ -2093,7 +2136,7 @@
|
|||||||
<entry key="file://$PROJECT_DIR$/app/core/api/internal/middleware/authorization_middleware.go">
|
<entry key="file://$PROJECT_DIR$/app/core/api/internal/middleware/authorization_middleware.go">
|
||||||
<value>
|
<value>
|
||||||
<ScannedPath>
|
<ScannedPath>
|
||||||
<option name="lastModified" value="1734692269196" />
|
<option name="lastModified" value="1734756193052" />
|
||||||
<option name="schema">
|
<option name="schema">
|
||||||
<list>
|
<list>
|
||||||
<option value="AuthorizationMiddleware" />
|
<option value="AuthorizationMiddleware" />
|
||||||
@@ -2114,6 +2157,18 @@
|
|||||||
</ScannedPath>
|
</ScannedPath>
|
||||||
</value>
|
</value>
|
||||||
</entry>
|
</entry>
|
||||||
|
<entry key="file://$PROJECT_DIR$/app/core/api/internal/middleware/nonce_middleware.go">
|
||||||
|
<value>
|
||||||
|
<ScannedPath>
|
||||||
|
<option name="lastModified" value="1734751419592" />
|
||||||
|
<option name="schema">
|
||||||
|
<list>
|
||||||
|
<option value="NonceMiddleware" />
|
||||||
|
</list>
|
||||||
|
</option>
|
||||||
|
</ScannedPath>
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
<entry key="file://$PROJECT_DIR$/app/core/api/internal/middleware/securityheaders_middleware.go">
|
<entry key="file://$PROJECT_DIR$/app/core/api/internal/middleware/securityheaders_middleware.go">
|
||||||
<value>
|
<value>
|
||||||
<ScannedPath>
|
<ScannedPath>
|
||||||
@@ -2129,7 +2184,7 @@
|
|||||||
<entry key="file://$PROJECT_DIR$/app/core/api/internal/svc/service_context.go">
|
<entry key="file://$PROJECT_DIR$/app/core/api/internal/svc/service_context.go">
|
||||||
<value>
|
<value>
|
||||||
<ScannedPath>
|
<ScannedPath>
|
||||||
<option name="lastModified" value="1734702591918" />
|
<option name="lastModified" value="1734756131198" />
|
||||||
<option name="schema">
|
<option name="schema">
|
||||||
<list>
|
<list>
|
||||||
<option value="ServiceContext" />
|
<option value="ServiceContext" />
|
||||||
@@ -2158,7 +2213,7 @@
|
|||||||
<entry key="file://$PROJECT_DIR$/app/core/api/internal/types/token.go">
|
<entry key="file://$PROJECT_DIR$/app/core/api/internal/types/token.go">
|
||||||
<value>
|
<value>
|
||||||
<ScannedPath>
|
<ScannedPath>
|
||||||
<option name="lastModified" value="1734692829235" />
|
<option name="lastModified" value="1734753611313" />
|
||||||
<option name="schema">
|
<option name="schema">
|
||||||
<list>
|
<list>
|
||||||
<option value="RedisToken" />
|
<option value="RedisToken" />
|
||||||
@@ -2170,7 +2225,7 @@
|
|||||||
<entry key="file://$PROJECT_DIR$/app/core/api/internal/types/types.go">
|
<entry key="file://$PROJECT_DIR$/app/core/api/internal/types/types.go">
|
||||||
<value>
|
<value>
|
||||||
<ScannedPath>
|
<ScannedPath>
|
||||||
<option name="lastModified" value="1734692204790" />
|
<option name="lastModified" value="1734715543979" />
|
||||||
<option name="schema">
|
<option name="schema">
|
||||||
<list>
|
<list>
|
||||||
<option value="AccountLoginRequest" />
|
<option value="AccountLoginRequest" />
|
||||||
@@ -2190,7 +2245,7 @@
|
|||||||
<option value="Response" />
|
<option value="Response" />
|
||||||
<option value="SmsSendRequest" />
|
<option value="SmsSendRequest" />
|
||||||
<option value="UploadRequest" />
|
<option value="UploadRequest" />
|
||||||
<option value="UserDeviceRequest" />
|
<option value="WechatOffiaccountLoginRequest" />
|
||||||
</list>
|
</list>
|
||||||
</option>
|
</option>
|
||||||
</ScannedPath>
|
</ScannedPath>
|
||||||
@@ -2711,7 +2766,7 @@
|
|||||||
<entry key="file://$PROJECT_DIR$/app/core/api/repository/wechat_official/wechat_official.go">
|
<entry key="file://$PROJECT_DIR$/app/core/api/repository/wechat_official/wechat_official.go">
|
||||||
<value>
|
<value>
|
||||||
<ScannedPath>
|
<ScannedPath>
|
||||||
<option name="lastModified" value="1734534902624" />
|
<option name="lastModified" value="1734752607655" />
|
||||||
</ScannedPath>
|
</ScannedPath>
|
||||||
</value>
|
</value>
|
||||||
</entry>
|
</entry>
|
||||||
@@ -2721,6 +2776,7 @@
|
|||||||
<map>
|
<map>
|
||||||
<entry key="access_jwt_claims" value="AccessJWTClaims" />
|
<entry key="access_jwt_claims" value="AccessJWTClaims" />
|
||||||
<entry key="access_jwt_payload" value="AccessJWTPayload" />
|
<entry key="access_jwt_payload" value="AccessJWTPayload" />
|
||||||
|
<entry key="access_token" value="AccessToken" />
|
||||||
<entry key="account_login_logic" value="AccountLoginLogic" />
|
<entry key="account_login_logic" value="AccountLoginLogic" />
|
||||||
<entry key="account_login_request" value="AccountLoginRequest" />
|
<entry key="account_login_request" value="AccountLoginRequest" />
|
||||||
<entry key="auth_q_qme" value="AuthQQme" />
|
<entry key="auth_q_qme" value="AuthQQme" />
|
||||||
@@ -2764,6 +2820,7 @@
|
|||||||
<entry key="message_data" value="MessageData" />
|
<entry key="message_data" value="MessageData" />
|
||||||
<entry key="message_web_socket" value="MessageWebSocket" />
|
<entry key="message_web_socket" value="MessageWebSocket" />
|
||||||
<entry key="message_websocket_logic" value="MessageWebsocketLogic" />
|
<entry key="message_websocket_logic" value="MessageWebsocketLogic" />
|
||||||
|
<entry key="nonce_middleware" value="NonceMiddleware" />
|
||||||
<entry key="o_auth_callback_request" value="OAuthCallbackRequest" />
|
<entry key="o_auth_callback_request" value="OAuthCallbackRequest" />
|
||||||
<entry key="o_auth_request" value="OAuthRequest" />
|
<entry key="o_auth_request" value="OAuthRequest" />
|
||||||
<entry key="o_auth_wechat_request" value="OAuthWechatRequest" />
|
<entry key="o_auth_wechat_request" value="OAuthWechatRequest" />
|
||||||
@@ -2842,6 +2899,7 @@
|
|||||||
<entry key="wechat_offiaccount_callback_logic" value="WechatOffiaccountCallbackLogic" />
|
<entry key="wechat_offiaccount_callback_logic" value="WechatOffiaccountCallbackLogic" />
|
||||||
<entry key="wechat_offiaccount_callback_verify_logic" value="WechatOffiaccountCallbackVerifyLogic" />
|
<entry key="wechat_offiaccount_callback_verify_logic" value="WechatOffiaccountCallbackVerifyLogic" />
|
||||||
<entry key="wechat_offiaccount_login_logic" value="WechatOffiaccountLoginLogic" />
|
<entry key="wechat_offiaccount_login_logic" value="WechatOffiaccountLoginLogic" />
|
||||||
|
<entry key="wechat_offiaccount_login_request" value="WechatOffiaccountLoginRequest" />
|
||||||
</map>
|
</map>
|
||||||
</option>
|
</option>
|
||||||
<option name="lastTimeChecked" value="1734699497598" />
|
<option name="lastTimeChecked" value="1734699497598" />
|
||||||
|
|||||||
@@ -22,5 +22,5 @@ const (
|
|||||||
|
|
||||||
// 系统相关的redis key
|
// 系统相关的redis key
|
||||||
const (
|
const (
|
||||||
SystemApiNonceRedisKey = "system:controller:nonce:"
|
SystemApiNoncePrefix = "system:nonce:"
|
||||||
)
|
)
|
||||||
|
|||||||
3
app/core/api/common/constant/time.go
Normal file
3
app/core/api/common/constant/time.go
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
package constant
|
||||||
|
|
||||||
|
const TimeFormat = "2006-01-02 15:04:05"
|
||||||
99
app/core/api/common/encrypt/aes.go
Normal file
99
app/core/api/common/encrypt/aes.go
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
package encrypt
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"crypto/aes"
|
||||||
|
"crypto/cipher"
|
||||||
|
"encoding/base64"
|
||||||
|
)
|
||||||
|
|
||||||
|
// AEC/CBC/PKCS7Padding 加密解密
|
||||||
|
|
||||||
|
// Encrypt 加密
|
||||||
|
//
|
||||||
|
// plainText: 加密目标字符串
|
||||||
|
// key: 加密Key
|
||||||
|
// iv: 加密iv(AES时固定为16位)
|
||||||
|
func Encrypt(plainText string, key string, iv string) (string, error) {
|
||||||
|
data, err := aesCBCEncrypt([]byte(plainText), []byte(key), []byte(iv))
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
return base64.StdEncoding.EncodeToString(data), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decrypt 解密
|
||||||
|
//
|
||||||
|
// cipherText: 解密目标字符串
|
||||||
|
// key: 加密Key
|
||||||
|
// iv: 加密iv(AES时固定为16位)
|
||||||
|
func Decrypt(cipherText string, key string, iv string) (string, error) {
|
||||||
|
data, err := base64.StdEncoding.DecodeString(cipherText)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
dnData, err := aesCBCDecrypt(data, []byte(key), []byte(iv))
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
return string(dnData), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// aesCBCEncrypt AES/CBC/PKCS7Padding 加密
|
||||||
|
func aesCBCEncrypt(plaintext []byte, key []byte, iv []byte) ([]byte, error) {
|
||||||
|
// AES
|
||||||
|
block, err := aes.NewCipher(key)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// PKCS7 填充
|
||||||
|
plaintext = paddingPKCS7(plaintext, aes.BlockSize)
|
||||||
|
|
||||||
|
// CBC 加密
|
||||||
|
mode := cipher.NewCBCEncrypter(block, iv)
|
||||||
|
mode.CryptBlocks(plaintext, plaintext)
|
||||||
|
|
||||||
|
return plaintext, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// aesCBCDecrypt AES/CBC/PKCS7Padding 解密
|
||||||
|
func aesCBCDecrypt(ciphertext []byte, key []byte, iv []byte) ([]byte, error) {
|
||||||
|
// AES
|
||||||
|
block, err := aes.NewCipher(key)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(ciphertext)%aes.BlockSize != 0 {
|
||||||
|
panic("ciphertext is not a multiple of the block size")
|
||||||
|
}
|
||||||
|
|
||||||
|
// CBC 解密
|
||||||
|
mode := cipher.NewCBCDecrypter(block, iv)
|
||||||
|
mode.CryptBlocks(ciphertext, ciphertext)
|
||||||
|
|
||||||
|
// PKCS7 反填充
|
||||||
|
result := unPaddingPKCS7(ciphertext)
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// PKCS7 填充
|
||||||
|
func paddingPKCS7(plaintext []byte, blockSize int) []byte {
|
||||||
|
paddingSize := blockSize - len(plaintext)%blockSize
|
||||||
|
paddingText := bytes.Repeat([]byte{byte(paddingSize)}, paddingSize)
|
||||||
|
return append(plaintext, paddingText...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// PKCS7 反填充
|
||||||
|
func unPaddingPKCS7(s []byte) []byte {
|
||||||
|
length := len(s)
|
||||||
|
if length == 0 {
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
unPadding := int(s[length-1])
|
||||||
|
return s[:(length - unPadding)]
|
||||||
|
}
|
||||||
@@ -15,11 +15,11 @@ type AccessJWTClaims struct {
|
|||||||
jwt.RegisteredClaims
|
jwt.RegisteredClaims
|
||||||
}
|
}
|
||||||
|
|
||||||
func GenerateAccessToken(secret string, payload AccessJWTPayload) string {
|
func GenerateAccessToken(secret string, payload AccessJWTPayload) (string, int64) {
|
||||||
claims := AccessJWTClaims{
|
claims := AccessJWTClaims{
|
||||||
AccessJWTPayload: payload,
|
AccessJWTPayload: payload,
|
||||||
RegisteredClaims: jwt.RegisteredClaims{
|
RegisteredClaims: jwt.RegisteredClaims{
|
||||||
ExpiresAt: jwt.NewNumericDate(time.Now().Add(time.Minute * 15)),
|
ExpiresAt: jwt.NewNumericDate(time.Now().Add(time.Minute * 30)),
|
||||||
IssuedAt: jwt.NewNumericDate(time.Now()),
|
IssuedAt: jwt.NewNumericDate(time.Now()),
|
||||||
NotBefore: jwt.NewNumericDate(time.Now()),
|
NotBefore: jwt.NewNumericDate(time.Now()),
|
||||||
},
|
},
|
||||||
@@ -27,9 +27,10 @@ func GenerateAccessToken(secret string, payload AccessJWTPayload) string {
|
|||||||
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
|
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
|
||||||
accessToken, err := token.SignedString([]byte(secret))
|
accessToken, err := token.SignedString([]byte(secret))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ""
|
return "", 0
|
||||||
}
|
}
|
||||||
return accessToken
|
expiresAt := claims.ExpiresAt.Unix()
|
||||||
|
return accessToken, expiresAt
|
||||||
}
|
}
|
||||||
|
|
||||||
// ParseAccessToken parses a JWT token and returns the payload
|
// ParseAccessToken parses a JWT token and returns the payload
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ func GenerateWebsocketToken(secret string, payload AccessJWTPayload) string {
|
|||||||
claims := AccessJWTClaims{
|
claims := AccessJWTClaims{
|
||||||
AccessJWTPayload: payload,
|
AccessJWTPayload: payload,
|
||||||
RegisteredClaims: jwt.RegisteredClaims{
|
RegisteredClaims: jwt.RegisteredClaims{
|
||||||
ExpiresAt: jwt.NewNumericDate(time.Now().Add(time.Minute * 15)),
|
ExpiresAt: jwt.NewNumericDate(time.Now().Add(time.Minute * 30)),
|
||||||
IssuedAt: jwt.NewNumericDate(time.Now()),
|
IssuedAt: jwt.NewNumericDate(time.Now()),
|
||||||
NotBefore: jwt.NewNumericDate(time.Now()),
|
NotBefore: jwt.NewNumericDate(time.Now()),
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ func CORSMiddleware() func(http.Header) {
|
|||||||
header.Set("Access-Control-Allow-Origin", "*")
|
header.Set("Access-Control-Allow-Origin", "*")
|
||||||
header.Set("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS, PATCH")
|
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-Expose-Headers", "Content-Length, Content-Type")
|
||||||
header.Set("Access-Control-Allow-Headers", "Content-Type,Authorization,Accept-Language,Origin,X-Content-Security,X-UID")
|
header.Set("Access-Control-Allow-Headers", "Content-Type,Authorization,Accept-Language,Origin,X-Content-Security,X-UID,X-Nonce,X-Expire-At")
|
||||||
header.Set("Access-Control-Allow-Credentials", "true")
|
header.Set("Access-Control-Allow-Credentials", "true")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
package middleware
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/zeromicro/go-zero/rest/httpx"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
func UnsignedCallbackMiddleware() func(w http.ResponseWriter, r *http.Request, next http.Handler, strict bool, code int) {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request, next http.Handler, strict bool, code int) {
|
||||||
|
httpx.WriteJsonCtx(r.Context(), w, http.StatusForbidden, "forbidden")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -38,6 +38,7 @@ type (
|
|||||||
// 登录响应参数
|
// 登录响应参数
|
||||||
LoginResponse {
|
LoginResponse {
|
||||||
AccessToken string `json:"access_token"`
|
AccessToken string `json:"access_token"`
|
||||||
|
ExpireAt int64 `json:"expire_at"`
|
||||||
UID string `json:"uid"`
|
UID string `json:"uid"`
|
||||||
Username string `json:"username,omitempty"`
|
Username string `json:"username,omitempty"`
|
||||||
Nickname string `json:"nickname"`
|
Nickname string `json:"nickname"`
|
||||||
@@ -57,7 +58,7 @@ type (
|
|||||||
Code string `form:"code"`
|
Code string `form:"code"`
|
||||||
}
|
}
|
||||||
OAuthWechatRequest {
|
OAuthWechatRequest {
|
||||||
client_id string `form:"client_id"`
|
clientId string `json:"client_id"`
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -154,7 +155,7 @@ type (
|
|||||||
timeout: 10s // 超时时间
|
timeout: 10s // 超时时间
|
||||||
maxBytes: 1048576 // 最大请求大小
|
maxBytes: 1048576 // 最大请求大小
|
||||||
signature: true // 是否开启签名验证
|
signature: true // 是否开启签名验证
|
||||||
middleware: SecurityHeadersMiddleware // 注册中间件
|
middleware: SecurityHeadersMiddleware,NonceMiddleware // 注册中间件
|
||||||
MaxConns: true // 是否开启最大连接数限制
|
MaxConns: true // 是否开启最大连接数限制
|
||||||
Recover: true // 是否开启自动恢复
|
Recover: true // 是否开启自动恢复
|
||||||
)
|
)
|
||||||
@@ -186,7 +187,7 @@ service core {
|
|||||||
timeout: 10s // 超时时间
|
timeout: 10s // 超时时间
|
||||||
maxBytes: 1048576 // 最大请求大小
|
maxBytes: 1048576 // 最大请求大小
|
||||||
signature: true // 是否开启签名验证
|
signature: true // 是否开启签名验证
|
||||||
middleware: SecurityHeadersMiddleware,CasbinVerifyMiddleware // 注册中间件
|
middleware: SecurityHeadersMiddleware,CasbinVerifyMiddleware,NonceMiddleware // 注册中间件
|
||||||
MaxConns: true // 是否开启最大连接数限制
|
MaxConns: true // 是否开启最大连接数限制
|
||||||
Recover: true // 是否开启自动恢复
|
Recover: true // 是否开启自动恢复
|
||||||
)
|
)
|
||||||
@@ -202,7 +203,7 @@ service core {
|
|||||||
timeout: 10s // 超时时间
|
timeout: 10s // 超时时间
|
||||||
maxBytes: 1048576 // 最大请求大小
|
maxBytes: 1048576 // 最大请求大小
|
||||||
signature: false // 是否开启签名验证
|
signature: false // 是否开启签名验证
|
||||||
middleware: SecurityHeadersMiddleware // 注册中间件
|
middleware: SecurityHeadersMiddleware,NonceMiddleware // 注册中间件
|
||||||
MaxConns: true // 是否开启最大连接数限制
|
MaxConns: true // 是否开启最大连接数限制
|
||||||
Recover: true // 是否开启自动恢复
|
Recover: true // 是否开启自动恢复
|
||||||
)
|
)
|
||||||
@@ -232,7 +233,7 @@ service core {
|
|||||||
timeout: 10s // 超时时间
|
timeout: 10s // 超时时间
|
||||||
maxBytes: 1048576 // 最大请求大小
|
maxBytes: 1048576 // 最大请求大小
|
||||||
signature: false // 是否开启签名验证
|
signature: false // 是否开启签名验证
|
||||||
middleware: SecurityHeadersMiddleware // 注册中间件
|
middleware: SecurityHeadersMiddleware,NonceMiddleware // 注册中间件
|
||||||
MaxConns: true // 是否开启最大连接数限制
|
MaxConns: true // 是否开启最大连接数限制
|
||||||
Recover: true // 是否开启自动恢复
|
Recover: true // 是否开启自动恢复
|
||||||
)
|
)
|
||||||
@@ -269,7 +270,7 @@ service core {
|
|||||||
timeout: 10s // 超时时间
|
timeout: 10s // 超时时间
|
||||||
maxBytes: 1048576 // 最大请求大小
|
maxBytes: 1048576 // 最大请求大小
|
||||||
signature: false // 是否开启签名验证
|
signature: false // 是否开启签名验证
|
||||||
middleware: SecurityHeadersMiddleware // 注册中间件
|
middleware: SecurityHeadersMiddleware,NonceMiddleware // 注册中间件
|
||||||
MaxConns: true // 是否开启最大连接数限制
|
MaxConns: true // 是否开启最大连接数限制
|
||||||
Recover: true // 是否开启自动恢复
|
Recover: true // 是否开启自动恢复
|
||||||
)
|
)
|
||||||
@@ -290,7 +291,7 @@ service core {
|
|||||||
timeout: 10s // 超时时间
|
timeout: 10s // 超时时间
|
||||||
maxBytes: 1048576 // 最大请求大小
|
maxBytes: 1048576 // 最大请求大小
|
||||||
signature: false // 是否开启签名验证
|
signature: false // 是否开启签名验证
|
||||||
middleware: SecurityHeadersMiddleware // 注册中间件
|
middleware: SecurityHeadersMiddleware,NonceMiddleware // 注册中间件
|
||||||
MaxConns: true // 是否开启最大连接数限制
|
MaxConns: true // 是否开启最大连接数限制
|
||||||
Recover: true // 是否开启自动恢复
|
Recover: true // 是否开启自动恢复
|
||||||
)
|
)
|
||||||
@@ -308,7 +309,7 @@ service core {
|
|||||||
timeout: 10s // 超时时间
|
timeout: 10s // 超时时间
|
||||||
maxBytes: 1048576 // 最大请求大小
|
maxBytes: 1048576 // 最大请求大小
|
||||||
signature: false // 是否开启签名验证
|
signature: false // 是否开启签名验证
|
||||||
middleware: SecurityHeadersMiddleware,CasbinVerifyMiddleware,AuthorizationMiddleware // 注册中间件
|
middleware: SecurityHeadersMiddleware,CasbinVerifyMiddleware,AuthorizationMiddleware,NonceMiddleware // 注册中间件
|
||||||
MaxConns: true // 是否开启最大连接数限制
|
MaxConns: true // 是否开启最大连接数限制
|
||||||
Recover: true // 是否开启自动恢复
|
Recover: true // 是否开启自动恢复
|
||||||
jwt: Auth // 是否开启jwt验证
|
jwt: Auth // 是否开启jwt验证
|
||||||
@@ -342,7 +343,7 @@ service core {
|
|||||||
timeout: 10s // 超时时间
|
timeout: 10s // 超时时间
|
||||||
maxBytes: 10485760 // 最大请求大小
|
maxBytes: 10485760 // 最大请求大小
|
||||||
signature: false // 是否开启签名验证
|
signature: false // 是否开启签名验证
|
||||||
middleware: SecurityHeadersMiddleware // 注册中间件
|
middleware: SecurityHeadersMiddleware,NonceMiddleware // 注册中间件
|
||||||
MaxConns: true // 是否开启最大连接数限制
|
MaxConns: true // 是否开启最大连接数限制
|
||||||
Recover: true // 是否开启自动恢复
|
Recover: true // 是否开启自动恢复
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -25,7 +25,8 @@ func main() {
|
|||||||
server := rest.MustNewServer(
|
server := rest.MustNewServer(
|
||||||
c.RestConf,
|
c.RestConf,
|
||||||
rest.WithCustomCors(middleware.CORSMiddleware(), nil),
|
rest.WithCustomCors(middleware.CORSMiddleware(), nil),
|
||||||
rest.WithUnauthorizedCallback(middleware.UnauthorizedCallbackMiddleware()))
|
rest.WithUnauthorizedCallback(middleware.UnauthorizedCallbackMiddleware()),
|
||||||
|
rest.WithUnsignedCallback(middleware.UnsignedCallbackMiddleware()))
|
||||||
defer server.Stop()
|
defer server.Stop()
|
||||||
// i18n middleware
|
// i18n middleware
|
||||||
server.Use(middleware.I18nMiddleware)
|
server.Use(middleware.I18nMiddleware)
|
||||||
|
|||||||
@@ -78,6 +78,12 @@ Signature:
|
|||||||
PrivateKeys:
|
PrivateKeys:
|
||||||
- Fingerprint: idm0jdoau38lwourb4pbjk4dxkat0kcx
|
- Fingerprint: idm0jdoau38lwourb4pbjk4dxkat0kcx
|
||||||
KeyFile: etc/rsa_private_key.pem
|
KeyFile: etc/rsa_private_key.pem
|
||||||
|
# 加密配置
|
||||||
|
Encrypt:
|
||||||
|
# 密钥(32)
|
||||||
|
Key: p3380puliiep184buh8d5dvujeerqtem
|
||||||
|
# 向量 (16)
|
||||||
|
IV: spb7er04k2vz3dtk
|
||||||
# Redis 配置
|
# Redis 配置
|
||||||
Redis:
|
Redis:
|
||||||
# Redis 地址
|
# Redis 地址
|
||||||
|
|||||||
@@ -10,6 +10,11 @@ type Config struct {
|
|||||||
Auth struct {
|
Auth struct {
|
||||||
AccessSecret string
|
AccessSecret string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Encrypt struct {
|
||||||
|
Key string
|
||||||
|
IV string
|
||||||
|
}
|
||||||
Mysql struct {
|
Mysql struct {
|
||||||
DataSource string
|
DataSource string
|
||||||
MaxOpenConn int
|
MaxOpenConn int
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ import (
|
|||||||
func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
|
func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
|
||||||
server.AddRoutes(
|
server.AddRoutes(
|
||||||
rest.WithMiddlewares(
|
rest.WithMiddlewares(
|
||||||
[]rest.Middleware{serverCtx.SecurityHeadersMiddleware},
|
[]rest.Middleware{serverCtx.SecurityHeadersMiddleware, serverCtx.NonceMiddleware},
|
||||||
[]rest.Route{
|
[]rest.Route{
|
||||||
{
|
{
|
||||||
Method: http.MethodGet,
|
Method: http.MethodGet,
|
||||||
@@ -45,7 +45,7 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
|
|||||||
|
|
||||||
server.AddRoutes(
|
server.AddRoutes(
|
||||||
rest.WithMiddlewares(
|
rest.WithMiddlewares(
|
||||||
[]rest.Middleware{serverCtx.SecurityHeadersMiddleware},
|
[]rest.Middleware{serverCtx.SecurityHeadersMiddleware, serverCtx.NonceMiddleware},
|
||||||
[]rest.Route{
|
[]rest.Route{
|
||||||
{
|
{
|
||||||
Method: http.MethodGet,
|
Method: http.MethodGet,
|
||||||
@@ -61,7 +61,7 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
|
|||||||
|
|
||||||
server.AddRoutes(
|
server.AddRoutes(
|
||||||
rest.WithMiddlewares(
|
rest.WithMiddlewares(
|
||||||
[]rest.Middleware{serverCtx.SecurityHeadersMiddleware, serverCtx.CasbinVerifyMiddleware, serverCtx.AuthorizationMiddleware},
|
[]rest.Middleware{serverCtx.SecurityHeadersMiddleware, serverCtx.CasbinVerifyMiddleware, serverCtx.AuthorizationMiddleware, serverCtx.NonceMiddleware},
|
||||||
[]rest.Route{
|
[]rest.Route{
|
||||||
{
|
{
|
||||||
Method: http.MethodPost,
|
Method: http.MethodPost,
|
||||||
@@ -108,7 +108,7 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
|
|||||||
|
|
||||||
server.AddRoutes(
|
server.AddRoutes(
|
||||||
rest.WithMiddlewares(
|
rest.WithMiddlewares(
|
||||||
[]rest.Middleware{serverCtx.SecurityHeadersMiddleware},
|
[]rest.Middleware{serverCtx.SecurityHeadersMiddleware, serverCtx.NonceMiddleware},
|
||||||
[]rest.Route{
|
[]rest.Route{
|
||||||
{
|
{
|
||||||
Method: http.MethodGet,
|
Method: http.MethodGet,
|
||||||
@@ -159,7 +159,7 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
|
|||||||
|
|
||||||
server.AddRoutes(
|
server.AddRoutes(
|
||||||
rest.WithMiddlewares(
|
rest.WithMiddlewares(
|
||||||
[]rest.Middleware{serverCtx.SecurityHeadersMiddleware},
|
[]rest.Middleware{serverCtx.SecurityHeadersMiddleware, serverCtx.NonceMiddleware},
|
||||||
[]rest.Route{
|
[]rest.Route{
|
||||||
{
|
{
|
||||||
Method: http.MethodPost,
|
Method: http.MethodPost,
|
||||||
@@ -185,7 +185,7 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
|
|||||||
|
|
||||||
server.AddRoutes(
|
server.AddRoutes(
|
||||||
rest.WithMiddlewares(
|
rest.WithMiddlewares(
|
||||||
[]rest.Middleware{serverCtx.SecurityHeadersMiddleware, serverCtx.CasbinVerifyMiddleware},
|
[]rest.Middleware{serverCtx.SecurityHeadersMiddleware, serverCtx.CasbinVerifyMiddleware, serverCtx.NonceMiddleware},
|
||||||
[]rest.Route{
|
[]rest.Route{
|
||||||
{
|
{
|
||||||
Method: http.MethodPost,
|
Method: http.MethodPost,
|
||||||
@@ -202,7 +202,7 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
|
|||||||
|
|
||||||
server.AddRoutes(
|
server.AddRoutes(
|
||||||
rest.WithMiddlewares(
|
rest.WithMiddlewares(
|
||||||
[]rest.Middleware{serverCtx.SecurityHeadersMiddleware},
|
[]rest.Middleware{serverCtx.SecurityHeadersMiddleware, serverCtx.NonceMiddleware},
|
||||||
[]rest.Route{
|
[]rest.Route{
|
||||||
{
|
{
|
||||||
Method: http.MethodPost,
|
Method: http.MethodPost,
|
||||||
@@ -218,7 +218,7 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
|
|||||||
|
|
||||||
server.AddRoutes(
|
server.AddRoutes(
|
||||||
rest.WithMiddlewares(
|
rest.WithMiddlewares(
|
||||||
[]rest.Middleware{serverCtx.SecurityHeadersMiddleware},
|
[]rest.Middleware{serverCtx.SecurityHeadersMiddleware, serverCtx.NonceMiddleware},
|
||||||
[]rest.Route{
|
[]rest.Route{
|
||||||
{
|
{
|
||||||
Method: http.MethodPost,
|
Method: http.MethodPost,
|
||||||
|
|||||||
@@ -73,9 +73,10 @@ func (l *GetCommentListLogic) GetCommentList(req *types.CommentListRequest) (res
|
|||||||
}
|
}
|
||||||
if count == 0 || len(commentQueryList) == 0 {
|
if count == 0 || len(commentQueryList) == 0 {
|
||||||
return response.SuccessWithData(types.CommentListPageResponse{
|
return response.SuccessWithData(types.CommentListPageResponse{
|
||||||
Total: count,
|
Total: count,
|
||||||
Size: req.Size,
|
Size: req.Size,
|
||||||
Current: req.Page,
|
Current: req.Page,
|
||||||
|
Comments: []types.CommentContent{},
|
||||||
}), nil
|
}), nil
|
||||||
}
|
}
|
||||||
// **************** 获取评论Id和用户Id ************
|
// **************** 获取评论Id和用户Id ************
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import (
|
|||||||
models2 "github.com/ArtisanCloud/PowerWeChat/v3/src/kernel/models"
|
models2 "github.com/ArtisanCloud/PowerWeChat/v3/src/kernel/models"
|
||||||
"github.com/ArtisanCloud/PowerWeChat/v3/src/officialAccount/server/handlers/models"
|
"github.com/ArtisanCloud/PowerWeChat/v3/src/officialAccount/server/handlers/models"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"schisandra-album-cloud-microservices/app/core/api/common/encrypt"
|
||||||
"schisandra-album-cloud-microservices/app/core/api/common/i18n"
|
"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/common/response"
|
||||||
"schisandra-album-cloud-microservices/app/core/api/internal/logic/websocket"
|
"schisandra-album-cloud-microservices/app/core/api/internal/logic/websocket"
|
||||||
@@ -96,9 +97,17 @@ func (l *WechatOffiaccountCallbackLogic) WechatOffiaccountCallback(r *http.Reque
|
|||||||
|
|
||||||
// SendMessage 发送消息到客户端
|
// SendMessage 发送消息到客户端
|
||||||
func (l *WechatOffiaccountCallbackLogic) SendMessage(openId string, clientId string) error {
|
func (l *WechatOffiaccountCallbackLogic) SendMessage(openId string, clientId string) error {
|
||||||
|
encryptClientId, err := encrypt.Encrypt(clientId, l.svcCtx.Config.Encrypt.Key, l.svcCtx.Config.Encrypt.IV)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
encryptOpenId, err := encrypt.Encrypt(openId, l.svcCtx.Config.Encrypt.Key, l.svcCtx.Config.Encrypt.IV)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
messageData := MessageData{
|
messageData := MessageData{
|
||||||
Openid: openId,
|
Openid: encryptOpenId,
|
||||||
ClientId: clientId,
|
ClientId: encryptClientId,
|
||||||
}
|
}
|
||||||
jsonData, err := json.Marshal(response.SuccessWithData(messageData))
|
jsonData, err := json.Marshal(response.SuccessWithData(messageData))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -20,6 +20,10 @@ type RefreshTokenLogic struct {
|
|||||||
ctx context.Context
|
ctx context.Context
|
||||||
svcCtx *svc.ServiceContext
|
svcCtx *svc.ServiceContext
|
||||||
}
|
}
|
||||||
|
type AccessToken struct {
|
||||||
|
AccessToken string `json:"access_token"`
|
||||||
|
ExpireAt int64 `json:"expire_at"`
|
||||||
|
}
|
||||||
|
|
||||||
func NewRefreshTokenLogic(ctx context.Context, svcCtx *svc.ServiceContext) *RefreshTokenLogic {
|
func NewRefreshTokenLogic(ctx context.Context, svcCtx *svc.ServiceContext) *RefreshTokenLogic {
|
||||||
return &RefreshTokenLogic{
|
return &RefreshTokenLogic{
|
||||||
@@ -34,6 +38,7 @@ func (l *RefreshTokenLogic) RefreshToken(r *http.Request) (resp *types.Response,
|
|||||||
if userId == "" {
|
if userId == "" {
|
||||||
return response.ErrorWithCode(403), nil
|
return response.ErrorWithCode(403), nil
|
||||||
}
|
}
|
||||||
|
// 从redis中获取refresh token
|
||||||
tokenData := l.svcCtx.RedisClient.Get(l.ctx, constant.UserTokenPrefix+userId).Val()
|
tokenData := l.svcCtx.RedisClient.Get(l.ctx, constant.UserTokenPrefix+userId).Val()
|
||||||
if tokenData == "" {
|
if tokenData == "" {
|
||||||
return response.ErrorWithCode(403), nil
|
return response.ErrorWithCode(403), nil
|
||||||
@@ -43,30 +48,42 @@ func (l *RefreshTokenLogic) RefreshToken(r *http.Request) (resp *types.Response,
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
// 判断是否已经被吊销
|
||||||
if redisTokenData.Revoked {
|
if redisTokenData.Revoked {
|
||||||
return response.ErrorWithCode(403), nil
|
return response.ErrorWithCode(403), nil
|
||||||
}
|
}
|
||||||
|
// 判断是否是同一个设备
|
||||||
|
if redisTokenData.AllowAgent != r.UserAgent() {
|
||||||
|
return response.ErrorWithCode(403), nil
|
||||||
|
}
|
||||||
|
// 判断refresh token是否在有效期内
|
||||||
refreshToken, result := jwt.ParseRefreshToken(l.svcCtx.Config.Auth.AccessSecret, redisTokenData.RefreshToken)
|
refreshToken, result := jwt.ParseRefreshToken(l.svcCtx.Config.Auth.AccessSecret, redisTokenData.RefreshToken)
|
||||||
if !result {
|
if !result {
|
||||||
return response.ErrorWithCode(403), nil
|
return response.ErrorWithCode(403), nil
|
||||||
}
|
}
|
||||||
accessToken := jwt.GenerateAccessToken(l.svcCtx.Config.Auth.AccessSecret, jwt.AccessJWTPayload{
|
// 生成新的access token
|
||||||
|
accessToken, expireAt := jwt.GenerateAccessToken(l.svcCtx.Config.Auth.AccessSecret, jwt.AccessJWTPayload{
|
||||||
UserID: refreshToken.UserID,
|
UserID: refreshToken.UserID,
|
||||||
Type: constant.JWT_TYPE_ACCESS,
|
Type: constant.JWT_TYPE_ACCESS,
|
||||||
})
|
})
|
||||||
if accessToken == "" {
|
// 更新redis中的access token
|
||||||
return response.ErrorWithCode(403), nil
|
|
||||||
}
|
|
||||||
redisToken := types.RedisToken{
|
redisToken := types.RedisToken{
|
||||||
AccessToken: accessToken,
|
AccessToken: accessToken,
|
||||||
RefreshToken: redisTokenData.RefreshToken,
|
RefreshToken: redisTokenData.RefreshToken,
|
||||||
UID: refreshToken.UserID,
|
UID: refreshToken.UserID,
|
||||||
Revoked: false,
|
Revoked: false,
|
||||||
|
GeneratedAt: redisTokenData.GeneratedAt,
|
||||||
|
AllowAgent: redisTokenData.AllowAgent,
|
||||||
|
GeneratedIP: redisTokenData.GeneratedIP,
|
||||||
|
UpdatedAt: time.Now().Format(constant.TimeFormat),
|
||||||
}
|
}
|
||||||
err = l.svcCtx.RedisClient.Set(l.ctx, constant.UserTokenPrefix+refreshToken.UserID, redisToken, time.Hour*24*7).Err()
|
err = l.svcCtx.RedisClient.Set(l.ctx, constant.UserTokenPrefix+refreshToken.UserID, redisToken, time.Hour*24*7).Err()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
token := AccessToken{
|
||||||
return response.SuccessWithData(accessToken), nil
|
AccessToken: accessToken,
|
||||||
|
ExpireAt: expireAt,
|
||||||
|
}
|
||||||
|
return response.SuccessWithData(token), nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -81,15 +81,15 @@ func HandleLoginJWT(user *model.ScaAuthUser, svcCtx *svc.ServiceContext, autoLog
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
// 生成jwt token
|
// 生成jwt token
|
||||||
accessToken := jwt.GenerateAccessToken(svcCtx.Config.Auth.AccessSecret, jwt.AccessJWTPayload{
|
accessToken, expireAt := jwt.GenerateAccessToken(svcCtx.Config.Auth.AccessSecret, jwt.AccessJWTPayload{
|
||||||
UserID: user.UID,
|
UserID: user.UID,
|
||||||
Type: constant.JWT_TYPE_ACCESS,
|
Type: constant.JWT_TYPE_ACCESS,
|
||||||
})
|
})
|
||||||
var days time.Duration
|
var days time.Duration
|
||||||
if autoLogin {
|
if autoLogin {
|
||||||
days = 24 * time.Hour
|
days = 3 * 24 * time.Hour
|
||||||
} else {
|
} else {
|
||||||
days = time.Hour * 1
|
days = time.Hour * 24
|
||||||
}
|
}
|
||||||
refreshToken := jwt.GenerateRefreshToken(svcCtx.Config.Auth.AccessSecret, jwt.RefreshJWTPayload{
|
refreshToken := jwt.GenerateRefreshToken(svcCtx.Config.Auth.AccessSecret, jwt.RefreshJWTPayload{
|
||||||
UserID: user.UID,
|
UserID: user.UID,
|
||||||
@@ -97,6 +97,7 @@ func HandleLoginJWT(user *model.ScaAuthUser, svcCtx *svc.ServiceContext, autoLog
|
|||||||
}, days)
|
}, days)
|
||||||
data := types.LoginResponse{
|
data := types.LoginResponse{
|
||||||
AccessToken: accessToken,
|
AccessToken: accessToken,
|
||||||
|
ExpireAt: expireAt,
|
||||||
UID: user.UID,
|
UID: user.UID,
|
||||||
Username: user.Username,
|
Username: user.Username,
|
||||||
Nickname: user.Nickname,
|
Nickname: user.Nickname,
|
||||||
@@ -109,6 +110,10 @@ func HandleLoginJWT(user *model.ScaAuthUser, svcCtx *svc.ServiceContext, autoLog
|
|||||||
RefreshToken: refreshToken,
|
RefreshToken: refreshToken,
|
||||||
UID: user.UID,
|
UID: user.UID,
|
||||||
Revoked: false,
|
Revoked: false,
|
||||||
|
GeneratedAt: time.Now().Format(constant.TimeFormat),
|
||||||
|
AllowAgent: r.UserAgent(),
|
||||||
|
GeneratedIP: utils.GetClientIP(r),
|
||||||
|
UpdatedAt: time.Now().Format(constant.TimeFormat),
|
||||||
}
|
}
|
||||||
err = svcCtx.RedisClient.Set(ctx, constant.UserTokenPrefix+user.UID, redisToken, days).Err()
|
err = svcCtx.RedisClient.Set(ctx, constant.UserTokenPrefix+user.UID, redisToken, days).Err()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ func NewGetWechatOffiaccountQrcodeLogic(ctx context.Context, svcCtx *svc.Service
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (l *GetWechatOffiaccountQrcodeLogic) GetWechatOffiaccountQrcode(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
|
ip := utils.GetClientIP(r)
|
||||||
key := constant.UserQrcodePrefix + ip
|
key := constant.UserQrcodePrefix + ip
|
||||||
|
|
||||||
// 从Redis获取二维码数据
|
// 从Redis获取二维码数据
|
||||||
@@ -45,7 +45,7 @@ func (l *GetWechatOffiaccountQrcodeLogic) GetWechatOffiaccountQrcode(r *http.Req
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 生成临时二维码
|
// 生成临时二维码
|
||||||
data, err := l.svcCtx.WechatOfficial.QRCode.Temporary(l.ctx, req.Client_id, 7*24*3600)
|
data, err := l.svcCtx.WechatOfficial.QRCode.Temporary(l.ctx, req.ClientId, 7*24*3600)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import (
|
|||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
"net/http"
|
"net/http"
|
||||||
"schisandra-album-cloud-microservices/app/core/api/common/constant"
|
"schisandra-album-cloud-microservices/app/core/api/common/constant"
|
||||||
|
"schisandra-album-cloud-microservices/app/core/api/common/encrypt"
|
||||||
randomname "schisandra-album-cloud-microservices/app/core/api/common/random_name"
|
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/response"
|
||||||
"schisandra-album-cloud-microservices/app/core/api/common/utils"
|
"schisandra-album-cloud-microservices/app/core/api/common/utils"
|
||||||
@@ -34,9 +35,21 @@ func NewWechatOffiaccountLoginLogic(ctx context.Context, svcCtx *svc.ServiceCont
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (l *WechatOffiaccountLoginLogic) WechatOffiaccountLogin(r *http.Request, req *types.WechatOffiaccountLoginRequest) (resp *types.Response, err error) {
|
func (l *WechatOffiaccountLoginLogic) WechatOffiaccountLogin(r *http.Request, req *types.WechatOffiaccountLoginRequest) (resp *types.Response, err error) {
|
||||||
|
decryptedClientId, err := encrypt.Decrypt(req.ClientId, l.svcCtx.Config.Encrypt.Key, l.svcCtx.Config.Encrypt.IV)
|
||||||
|
if err != nil {
|
||||||
|
return response.ErrorWithI18n(l.ctx, "login.loginFailed"), nil
|
||||||
|
}
|
||||||
|
clientId := l.svcCtx.RedisClient.Get(r.Context(), constant.UserClientPrefix+decryptedClientId).Val()
|
||||||
|
if clientId == "" {
|
||||||
|
return response.ErrorWithI18n(l.ctx, "login.loginFailed"), nil
|
||||||
|
}
|
||||||
|
Openid, err := encrypt.Decrypt(req.Openid, l.svcCtx.Config.Encrypt.Key, l.svcCtx.Config.Encrypt.IV)
|
||||||
|
if err != nil {
|
||||||
|
return response.ErrorWithI18n(l.ctx, "login.loginFailed"), nil
|
||||||
|
}
|
||||||
tx := l.svcCtx.DB.Begin()
|
tx := l.svcCtx.DB.Begin()
|
||||||
userSocial := l.svcCtx.DB.ScaAuthUserSocial
|
userSocial := l.svcCtx.DB.ScaAuthUserSocial
|
||||||
socialUser, err := tx.ScaAuthUserSocial.Where(userSocial.OpenID.Eq(req.Openid), userSocial.Source.Eq(constant.OAuthSourceWechat)).First()
|
socialUser, err := tx.ScaAuthUserSocial.Where(userSocial.OpenID.Eq(Openid), userSocial.Source.Eq(constant.OAuthSourceWechat)).First()
|
||||||
if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
|
if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -50,7 +63,7 @@ func (l *WechatOffiaccountLoginLogic) WechatOffiaccountLogin(r *http.Request, re
|
|||||||
addUser := &model.ScaAuthUser{
|
addUser := &model.ScaAuthUser{
|
||||||
UID: uidStr,
|
UID: uidStr,
|
||||||
Avatar: avatar,
|
Avatar: avatar,
|
||||||
Username: req.Openid,
|
Username: Openid,
|
||||||
Nickname: name,
|
Nickname: name,
|
||||||
Gender: constant.Male,
|
Gender: constant.Male,
|
||||||
}
|
}
|
||||||
@@ -62,7 +75,7 @@ func (l *WechatOffiaccountLoginLogic) WechatOffiaccountLogin(r *http.Request, re
|
|||||||
|
|
||||||
newSocialUser := &model.ScaAuthUserSocial{
|
newSocialUser := &model.ScaAuthUserSocial{
|
||||||
UserID: uidStr,
|
UserID: uidStr,
|
||||||
OpenID: req.Openid,
|
OpenID: Openid,
|
||||||
Source: constant.OAuthSourceWechat,
|
Source: constant.OAuthSourceWechat,
|
||||||
}
|
}
|
||||||
err = tx.ScaAuthUserSocial.Create(newSocialUser)
|
err = tx.ScaAuthUserSocial.Create(newSocialUser)
|
||||||
|
|||||||
@@ -1,29 +1,40 @@
|
|||||||
package middleware
|
package middleware
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/redis/go-redis/v9"
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
"github.com/zeromicro/go-zero/rest/httpx"
|
"github.com/zeromicro/go-zero/rest/httpx"
|
||||||
"net/http"
|
"net/http"
|
||||||
"schisandra-album-cloud-microservices/app/core/api/common/constant"
|
|
||||||
"schisandra-album-cloud-microservices/app/core/api/common/response"
|
"schisandra-album-cloud-microservices/app/core/api/common/response"
|
||||||
|
"strconv"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
type AuthorizationMiddleware struct {
|
type AuthorizationMiddleware struct {
|
||||||
Redis *redis.Client
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewAuthorizationMiddleware(redis *redis.Client) *AuthorizationMiddleware {
|
func NewAuthorizationMiddleware() *AuthorizationMiddleware {
|
||||||
return &AuthorizationMiddleware{
|
return &AuthorizationMiddleware{}
|
||||||
Redis: redis,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *AuthorizationMiddleware) Handle(next http.HandlerFunc) http.HandlerFunc {
|
func (m *AuthorizationMiddleware) Handle(next http.HandlerFunc) http.HandlerFunc {
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
userId := r.Context().Value("user_id").(string)
|
expireAtStr := r.Header.Get("X-Expire-At")
|
||||||
redisToken := m.Redis.Get(r.Context(), constant.UserTokenPrefix+userId).Val()
|
if expireAtStr == "" {
|
||||||
if redisToken == "" {
|
httpx.OkJson(w, response.ErrorWithCodeMessage(http.StatusForbidden, "unauthorized"))
|
||||||
httpx.OkJson(w, response.ErrorWithCodeMessage(403, "unauthorized"))
|
return
|
||||||
|
}
|
||||||
|
expireAtInt, err := strconv.ParseInt(expireAtStr, 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
logx.Errorf("Failed to parse X-Expire-At: %v", err)
|
||||||
|
httpx.OkJson(w, response.ErrorWithCodeMessage(http.StatusForbidden, "unauthorized"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
expireAt := time.Unix(expireAtInt, 0)
|
||||||
|
currentTime := time.Now()
|
||||||
|
|
||||||
|
remainingTime := expireAt.Sub(currentTime)
|
||||||
|
if remainingTime < time.Minute*5 {
|
||||||
|
httpx.OkJson(w, response.ErrorWithCodeMessage(http.StatusUnauthorized, "token about to expire, refresh"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
next(w, r)
|
next(w, r)
|
||||||
|
|||||||
44
app/core/api/internal/middleware/nonce_middleware.go
Normal file
44
app/core/api/internal/middleware/nonce_middleware.go
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
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"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type NonceMiddleware struct {
|
||||||
|
RedisClient *redis.Client
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewNonceMiddleware(redisClient *redis.Client) *NonceMiddleware {
|
||||||
|
return &NonceMiddleware{
|
||||||
|
RedisClient: redisClient,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *NonceMiddleware) Handle(next http.HandlerFunc) http.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
nonce := r.Header.Get("X-Nonce")
|
||||||
|
if nonce == "" {
|
||||||
|
httpx.WriteJsonCtx(r.Context(), w, http.StatusBadRequest, "bad request!")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if len(nonce) != 32 {
|
||||||
|
httpx.WriteJsonCtx(r.Context(), w, http.StatusBadRequest, "bad request!")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
result := m.RedisClient.Get(r.Context(), constant.SystemApiNoncePrefix+nonce).Val()
|
||||||
|
if result != "" {
|
||||||
|
httpx.WriteJsonCtx(r.Context(), w, http.StatusBadRequest, "bad request!")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err := m.RedisClient.Set(r.Context(), constant.SystemApiNoncePrefix+nonce, nonce, time.Minute*1).Err()
|
||||||
|
if err != nil {
|
||||||
|
httpx.WriteJsonCtx(r.Context(), w, http.StatusInternalServerError, "internal server error!")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
next(w, r)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -29,6 +29,7 @@ type ServiceContext struct {
|
|||||||
SecurityHeadersMiddleware rest.Middleware
|
SecurityHeadersMiddleware rest.Middleware
|
||||||
CasbinVerifyMiddleware rest.Middleware
|
CasbinVerifyMiddleware rest.Middleware
|
||||||
AuthorizationMiddleware rest.Middleware
|
AuthorizationMiddleware rest.Middleware
|
||||||
|
NonceMiddleware rest.Middleware
|
||||||
DB *query.Query
|
DB *query.Query
|
||||||
RedisClient *redis.Client
|
RedisClient *redis.Client
|
||||||
MongoClient *mongo.Database
|
MongoClient *mongo.Database
|
||||||
@@ -48,7 +49,8 @@ func NewServiceContext(c config.Config) *ServiceContext {
|
|||||||
Config: c,
|
Config: c,
|
||||||
SecurityHeadersMiddleware: middleware.NewSecurityHeadersMiddleware().Handle,
|
SecurityHeadersMiddleware: middleware.NewSecurityHeadersMiddleware().Handle,
|
||||||
CasbinVerifyMiddleware: middleware.NewCasbinVerifyMiddleware(casbinEnforcer).Handle,
|
CasbinVerifyMiddleware: middleware.NewCasbinVerifyMiddleware(casbinEnforcer).Handle,
|
||||||
AuthorizationMiddleware: middleware.NewAuthorizationMiddleware(redisClient).Handle,
|
AuthorizationMiddleware: middleware.NewAuthorizationMiddleware().Handle,
|
||||||
|
NonceMiddleware: middleware.NewNonceMiddleware(redisClient).Handle,
|
||||||
DB: queryDB,
|
DB: queryDB,
|
||||||
RedisClient: redisClient,
|
RedisClient: redisClient,
|
||||||
MongoClient: mongodb.NewMongoDB(c.Mongo.Uri, c.Mongo.Username, c.Mongo.Password, c.Mongo.AuthSource, c.Mongo.Database),
|
MongoClient: mongodb.NewMongoDB(c.Mongo.Uri, c.Mongo.Username, c.Mongo.Password, c.Mongo.AuthSource, c.Mongo.Database),
|
||||||
|
|||||||
@@ -7,6 +7,10 @@ type RedisToken struct {
|
|||||||
RefreshToken string `json:"refresh_token"`
|
RefreshToken string `json:"refresh_token"`
|
||||||
UID string `json:"uid"`
|
UID string `json:"uid"`
|
||||||
Revoked bool `json:"revoked" default:"false"`
|
Revoked bool `json:"revoked" default:"false"`
|
||||||
|
AllowAgent string `json:"allow_agent"`
|
||||||
|
GeneratedAt string `json:"generated_at"`
|
||||||
|
UpdatedAt string `json:"updated_at"`
|
||||||
|
GeneratedIP string `json:"generated_ip"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (res RedisToken) MarshalBinary() ([]byte, error) {
|
func (res RedisToken) MarshalBinary() ([]byte, error) {
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ type CommentRequest struct {
|
|||||||
|
|
||||||
type LoginResponse struct {
|
type LoginResponse struct {
|
||||||
AccessToken string `json:"access_token"`
|
AccessToken string `json:"access_token"`
|
||||||
|
ExpireAt int64 `json:"expire_at"`
|
||||||
UID string `json:"uid"`
|
UID string `json:"uid"`
|
||||||
Username string `json:"username,omitempty"`
|
Username string `json:"username,omitempty"`
|
||||||
Nickname string `json:"nickname"`
|
Nickname string `json:"nickname"`
|
||||||
@@ -55,7 +56,7 @@ type OAuthRequest struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type OAuthWechatRequest struct {
|
type OAuthWechatRequest struct {
|
||||||
Client_id string `form:"client_id"`
|
ClientId string `json:"client_id"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type PhoneLoginRequest struct {
|
type PhoneLoginRequest struct {
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ func NewWechatPublic(appId, appSecret, token, aesKey, addr, pass string, db int)
|
|||||||
AESKey: aesKey,
|
AESKey: aesKey,
|
||||||
Log: officialAccount.Log{
|
Log: officialAccount.Log{
|
||||||
Level: "error",
|
Level: "error",
|
||||||
File: "/logs/wechat/wechat_official.log",
|
File: "./logs/wechat/wechat_official.log",
|
||||||
Stdout: false,
|
Stdout: false,
|
||||||
},
|
},
|
||||||
ResponseType: os.Getenv("response_type"),
|
ResponseType: os.Getenv("response_type"),
|
||||||
|
|||||||
Reference in New Issue
Block a user