Add register, login
This commit is contained in:
parent
d00e579458
commit
8d460c8e2e
58
database/admindb.sql
Normal file
58
database/admindb.sql
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
drop table if exists t_users;
|
||||||
|
CREATE TABLE t_users (
|
||||||
|
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
username VARCHAR(255) NOT NULL UNIQUE,
|
||||||
|
password VARCHAR(255) NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
drop table if exists t_roles;
|
||||||
|
CREATE TABLE t_roles (
|
||||||
|
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
name VARCHAR(255) NOT NULL UNIQUE
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE permissions (
|
||||||
|
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
name VARCHAR(255) NOT NULL UNIQUE
|
||||||
|
);
|
||||||
|
|
||||||
|
drop table if exists t_permissions;
|
||||||
|
CREATE TABLE t_permissions (
|
||||||
|
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
name VARCHAR(255) NOT NULL UNIQUE
|
||||||
|
);
|
||||||
|
|
||||||
|
drop table if exists t_user_roles;
|
||||||
|
CREATE TABLE t_user_roles (
|
||||||
|
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
user_id INT,
|
||||||
|
role_id INT
|
||||||
|
);
|
||||||
|
|
||||||
|
drop table if exists t_role_permissions;
|
||||||
|
CREATE TABLE t_role_permissions (
|
||||||
|
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
role_id INT,
|
||||||
|
permission_id INT
|
||||||
|
);
|
||||||
|
|
||||||
|
drop table if exists t_actions;
|
||||||
|
create table t_actions
|
||||||
|
(
|
||||||
|
id int AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
name VARCHAR(255) NOT NULL UNIQUE
|
||||||
|
);
|
||||||
|
|
||||||
|
drop table if exists t_sessions;
|
||||||
|
create table if not exists t_sessions (
|
||||||
|
id bigint,
|
||||||
|
username varchar(255) not null default "",
|
||||||
|
refresh_token varchar(255) not null default "",
|
||||||
|
client_ip varchar(255) not null default "",
|
||||||
|
user_agent varchar(255) NOT NULL default "",
|
||||||
|
is_blocked tinyint not null default "0",
|
||||||
|
expires_at int not null default "0",
|
||||||
|
created_at int not null default "0",
|
||||||
|
primary key id(id),
|
||||||
|
unique key username(username)
|
||||||
|
);
|
@ -12,8 +12,8 @@ import (
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
authorizationHeaderKey = "authorization"
|
authorizationHeaderKey = "authorization"
|
||||||
authorizationTypeBearer = "bearer"
|
|
||||||
authorizationTypeBasic = "basic"
|
authorizationTypeBasic = "basic"
|
||||||
|
authorizationTypeBearer = "bearer"
|
||||||
authorizationPayloadKey = "authorization_payload"
|
authorizationPayloadKey = "authorization_payload"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -33,11 +33,11 @@ func authMiddleware(tokenMaker token.Maker) gin.HandlerFunc {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Use http basic
|
||||||
// Headers key: Authorization
|
// Headers key: Authorization
|
||||||
// Headers value: Basic cm9vdDoxMjM0NTY=
|
// Headers value: Basic cm9vdDoxMjM0NTY=
|
||||||
authorizationType := strings.ToLower(fields[0])
|
authorizationType := strings.ToLower(fields[0])
|
||||||
if authorizationType == authorizationTypeBasic {
|
if authorizationType == authorizationTypeBasic {
|
||||||
|
|
||||||
user, password, hasAuth := ctx.Request.BasicAuth()
|
user, password, hasAuth := ctx.Request.BasicAuth()
|
||||||
if hasAuth && user == "root" && password == "123456" {
|
if hasAuth && user == "root" && password == "123456" {
|
||||||
ctx.Next()
|
ctx.Next()
|
||||||
@ -45,6 +45,7 @@ func authMiddleware(tokenMaker token.Maker) gin.HandlerFunc {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Use accounts from db
|
||||||
if authorizationType != authorizationTypeBearer {
|
if authorizationType != authorizationTypeBearer {
|
||||||
err := fmt.Errorf("unsupported authorization type %s", authorizationType)
|
err := fmt.Errorf("unsupported authorization type %s", authorizationType)
|
||||||
ctx.AbortWithStatusJSON(http.StatusUnauthorized, errorResponse(err))
|
ctx.AbortWithStatusJSON(http.StatusUnauthorized, errorResponse(err))
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package api
|
package api
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/jmoiron/sqlx"
|
"github.com/jmoiron/sqlx"
|
||||||
"main/token"
|
"main/token"
|
||||||
@ -13,9 +14,26 @@ type Server struct {
|
|||||||
router *gin.Engine
|
router *gin.Engine
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
Install
|
||||||
|
go get github.com/jmoiron/sqlx
|
||||||
|
go get -u github.com/golang-jwt/jwt/v5
|
||||||
|
go get -u github.com/o1egl/paseto
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
var TokenSymmetricKey = "12345678901234567890123456789012"
|
||||||
|
|
||||||
func NewServer(store *sqlx.DB) (*Server, error) {
|
func NewServer(store *sqlx.DB) (*Server, error) {
|
||||||
|
tokenMaker, err := token.NewPasetoMaker(TokenSymmetricKey)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("cannot create token maker: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
server := &Server{
|
server := &Server{
|
||||||
store: store,
|
store: store,
|
||||||
|
tokenMaker: tokenMaker,
|
||||||
}
|
}
|
||||||
|
|
||||||
server.setupRouter()
|
server.setupRouter()
|
||||||
@ -26,12 +44,13 @@ func (server *Server) setupRouter() {
|
|||||||
router := gin.Default()
|
router := gin.Default()
|
||||||
// Default routers
|
// Default routers
|
||||||
router.GET("/welcome", server.welcome)
|
router.GET("/welcome", server.welcome)
|
||||||
|
router.POST("/create_user", server.createUser)
|
||||||
router.POST("/login", server.loginUser)
|
router.POST("/login", server.loginUser)
|
||||||
|
|
||||||
// Authentication routers
|
// Authentication routers
|
||||||
authRoutes := router.Group("/").Use(authMiddleware(server.tokenMaker))
|
authRoutes := router.Group("/").Use(authMiddleware(server.tokenMaker))
|
||||||
authRoutes.GET("/accounts", server.listAccounts)
|
authRoutes.GET("/users", server.listUsers)
|
||||||
authRoutes.GET("/guilds", server.listGuilds)
|
authRoutes.GET("/users/:user_id", server.getUser)
|
||||||
authRoutes.GET("/guilds/:guild_id", server.getGuild)
|
authRoutes.GET("/guilds/:guild_id", server.getGuild)
|
||||||
authRoutes.POST("/guilds", server.createGuild)
|
authRoutes.POST("/guilds", server.createGuild)
|
||||||
authRoutes.DELETE("/guilds/:guild_id", server.deleteGuild)
|
authRoutes.DELETE("/guilds/:guild_id", server.deleteGuild)
|
||||||
|
@ -8,18 +8,126 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type createUserRequest struct {
|
type createUserRequest struct {
|
||||||
Username string `json:"username" binding:"required,alphanum"`
|
Username string `json:"username" binding:"required"`
|
||||||
Password string `json:"password" binding:"required,min=6"`
|
Password string `json:"password" binding:"required,min=6"`
|
||||||
FullName string `json:"full_name" binding:"required"`
|
}
|
||||||
Email string `json:"email" binding:"required,email"`
|
type loginUserRequest struct {
|
||||||
|
Username string `json:"username" binding:"required"`
|
||||||
|
Password string `json:"password" binding:"required,min=6"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type loginUserResponse struct {
|
||||||
|
SessionID int64 `json:"session_id"`
|
||||||
|
AccessToken string `json:"access_token"`
|
||||||
|
AccessTokenExpiresAt time.Time `json:"access_token_expires_at"`
|
||||||
|
RefreshToken string `json:"refresh_token"`
|
||||||
|
RefreshTokenExpiresAt time.Time `json:"refresh_token_expires_at"`
|
||||||
|
User userResponse `json:"user"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type userResponse struct {
|
type userResponse struct {
|
||||||
Username string `json:"username"`
|
Username string `json:"username"`
|
||||||
FullName string `json:"full_name"`
|
}
|
||||||
Email string `json:"email"`
|
|
||||||
PasswordChangedAt time.Time `json:"password_changed_at"`
|
func newUserResponse(user *model.User) userResponse {
|
||||||
CreatedAt time.Time `json:"created_at"`
|
return userResponse{
|
||||||
|
Username: user.Username,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type CreateUserParams struct {
|
||||||
|
Username string `json:"username"`
|
||||||
|
Password string `json:"password"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (server *Server) welcome(ctx *gin.Context) {
|
||||||
|
ctx.JSON(http.StatusOK, "welcome")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (server *Server) createUser(ctx *gin.Context) {
|
||||||
|
var req createUserRequest
|
||||||
|
if err := ctx.ShouldBindJSON(&req); err != nil {
|
||||||
|
ctx.JSON(http.StatusBadRequest, errorResponse(err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var createUserParams model.User
|
||||||
|
createUserParams.Username = req.Username
|
||||||
|
createUserParams.Password = req.Password
|
||||||
|
|
||||||
|
userId, err := model.CreateUser(&createUserParams)
|
||||||
|
if err != nil {
|
||||||
|
ctx.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to create user"})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.JSON(http.StatusCreated, gin.H{"userId": userId, "userName": createUserParams.Username})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (server *Server) loginUser(ctx *gin.Context) {
|
||||||
|
var req loginUserRequest
|
||||||
|
if err := ctx.ShouldBindJSON(&req); err != nil {
|
||||||
|
ctx.JSON(http.StatusBadRequest, errorResponse(err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
user, err := model.GetUserByUsername(req.Username)
|
||||||
|
if err != nil {
|
||||||
|
ctx.JSON(http.StatusInternalServerError, errorResponse(err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !CheckPassword(req.Password, user.Password) {
|
||||||
|
ctx.JSON(http.StatusUnauthorized, errorResponse(err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
accessTokenDuration, _ := time.ParseDuration("15m")
|
||||||
|
accessToken, accessPayload, err := server.tokenMaker.CreateToken(
|
||||||
|
user.Username,
|
||||||
|
accessTokenDuration,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
ctx.JSON(http.StatusInternalServerError, errorResponse(err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
refreshTokenDuration, _ := time.ParseDuration("24h")
|
||||||
|
refreshToken, refreshPayload, err := server.tokenMaker.CreateToken(
|
||||||
|
user.Username,
|
||||||
|
refreshTokenDuration,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
ctx.JSON(http.StatusInternalServerError, errorResponse(err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var createSessionParams model.Session
|
||||||
|
createSessionParams.Id = refreshPayload.ID
|
||||||
|
createSessionParams.Username = req.Username
|
||||||
|
createSessionParams.RefreshToken = refreshToken
|
||||||
|
createSessionParams.UserAgent = ctx.Request.UserAgent()
|
||||||
|
createSessionParams.ClientIp = ctx.ClientIP()
|
||||||
|
createSessionParams.ExpiresAt = refreshPayload.ExpiredAt
|
||||||
|
|
||||||
|
session, err := model.CreateSession(&createSessionParams)
|
||||||
|
if err != nil {
|
||||||
|
ctx.JSON(http.StatusInternalServerError, errorResponse(err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
rsp := loginUserResponse{
|
||||||
|
SessionID: session.Id,
|
||||||
|
AccessToken: accessToken,
|
||||||
|
AccessTokenExpiresAt: accessPayload.ExpiredAt,
|
||||||
|
RefreshToken: refreshToken,
|
||||||
|
RefreshTokenExpiresAt: refreshPayload.ExpiredAt,
|
||||||
|
User: newUserResponse(user),
|
||||||
|
}
|
||||||
|
ctx.JSON(http.StatusOK, rsp)
|
||||||
|
}
|
||||||
|
|
||||||
|
func CheckPassword(password, hasPassword string) bool {
|
||||||
|
return password == hasPassword
|
||||||
}
|
}
|
||||||
|
|
||||||
func (server *Server) listUsers(ctx *gin.Context) {
|
func (server *Server) listUsers(ctx *gin.Context) {
|
||||||
@ -31,70 +139,6 @@ func (server *Server) listUsers(ctx *gin.Context) {
|
|||||||
ctx.JSON(http.StatusOK, users)
|
ctx.JSON(http.StatusOK, users)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (server *Server) createUser(ctx *gin.Context) {
|
func (server *Server) getUser(ctx *gin.Context) {
|
||||||
var req createUserRequest
|
|
||||||
if err := ctx.ShouldBindJSON(&req); err != nil {
|
|
||||||
ctx.JSON(http.StatusBadRequest, errorResponse(err))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
rsp := ""
|
|
||||||
ctx.JSON(http.StatusOK, rsp)
|
|
||||||
}
|
|
||||||
|
|
||||||
type loginUserRequest struct {
|
|
||||||
Username string `json:"username" binding:"required,alphanum"`
|
|
||||||
Password string `json:"password" binding:"required,min=6"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type loginUserResponse struct {
|
|
||||||
SessionID string `json:"session_id"`
|
|
||||||
AccessToken string `json:"access_token"`
|
|
||||||
AccessTokenExpiresAt time.Time `json:"access_token_expires_at"`
|
|
||||||
RefreshToken string `json:"refresh_token"`
|
|
||||||
RefreshTokenExpiresAt time.Time `json:"refresh_token_expires_at"`
|
|
||||||
User userResponse `json:"user"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type Account struct {
|
|
||||||
ID int64 `json:"id"`
|
|
||||||
Owner string `json:"owner"`
|
|
||||||
Balance int64 `json:"balance"`
|
|
||||||
Currency string `json:"currency"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (server *Server) welcome(ctx *gin.Context) {
|
|
||||||
ctx.JSON(http.StatusOK, "welcome")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (server *Server) loginUser(ctx *gin.Context) {
|
|
||||||
ctx.JSON(http.StatusOK, "loginUser")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (server *Server) createAccount(ctx *gin.Context) {
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (server *Server) getAccount(ctx *gin.Context) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func (server *Server) listAccounts(ctx *gin.Context) {
|
|
||||||
account1 := &Account{
|
|
||||||
1,
|
|
||||||
"2",
|
|
||||||
3,
|
|
||||||
"4",
|
|
||||||
}
|
|
||||||
account2 := &Account{
|
|
||||||
11,
|
|
||||||
"22",
|
|
||||||
33,
|
|
||||||
"44",
|
|
||||||
}
|
|
||||||
var accounts []*Account
|
|
||||||
accounts = append(accounts, account1)
|
|
||||||
accounts = append(accounts, account2)
|
|
||||||
|
|
||||||
ctx.JSON(http.StatusOK, accounts)
|
|
||||||
}
|
|
||||||
|
@ -12,7 +12,7 @@ var db *sqlx.DB
|
|||||||
|
|
||||||
func InitDB() {
|
func InitDB() {
|
||||||
var err error
|
var err error
|
||||||
dsn := "root:keji178@tcp(login-test.kingsome.cn:3306)/frienddb_dev_1?charset=utf8mb4&parseTime=True"
|
dsn := "root:keji178@tcp(login-test.kingsome.cn:3306)/admindb_dev?charset=utf8mb4&parseTime=True"
|
||||||
db, err = sqlx.Connect("mysql", dsn)
|
db, err = sqlx.Connect("mysql", dsn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
f5.GetSysLog().Info("Failed to connect to the database err:%v \n", err)
|
f5.GetSysLog().Info("Failed to connect to the database err:%v \n", err)
|
||||||
|
@ -18,6 +18,9 @@ require (
|
|||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da // indirect
|
||||||
|
github.com/aead/chacha20poly1305 v0.0.0-20201124145622-1a5aba2a8b29 // indirect
|
||||||
|
github.com/aead/poly1305 v0.0.0-20180717145839-3fee0db0b635 // indirect
|
||||||
github.com/bytedance/sonic v1.10.0 // indirect
|
github.com/bytedance/sonic v1.10.0 // indirect
|
||||||
github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d // indirect
|
github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d // indirect
|
||||||
github.com/chenzhuoyu/iasm v0.9.0 // indirect
|
github.com/chenzhuoyu/iasm v0.9.0 // indirect
|
||||||
@ -28,6 +31,7 @@ require (
|
|||||||
github.com/go-playground/validator/v10 v10.15.3 // indirect
|
github.com/go-playground/validator/v10 v10.15.3 // indirect
|
||||||
github.com/go-sql-driver/mysql v1.6.0 // indirect
|
github.com/go-sql-driver/mysql v1.6.0 // indirect
|
||||||
github.com/goccy/go-json v0.10.2 // indirect
|
github.com/goccy/go-json v0.10.2 // indirect
|
||||||
|
github.com/golang-jwt/jwt/v5 v5.0.0 // indirect
|
||||||
github.com/gomodule/redigo v1.8.3 // indirect
|
github.com/gomodule/redigo v1.8.3 // indirect
|
||||||
github.com/jmoiron/sqlx v1.3.5 // indirect
|
github.com/jmoiron/sqlx v1.3.5 // indirect
|
||||||
github.com/json-iterator/go v1.1.12 // indirect
|
github.com/json-iterator/go v1.1.12 // indirect
|
||||||
@ -36,11 +40,13 @@ require (
|
|||||||
github.com/mattn/go-isatty v0.0.19 // indirect
|
github.com/mattn/go-isatty v0.0.19 // indirect
|
||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||||
|
github.com/o1egl/paseto v1.0.0 // indirect
|
||||||
github.com/pelletier/go-toml/v2 v2.1.0 // indirect
|
github.com/pelletier/go-toml/v2 v2.1.0 // indirect
|
||||||
|
github.com/pkg/errors v0.9.1 // indirect
|
||||||
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
||||||
github.com/ugorji/go/codec v1.2.11 // indirect
|
github.com/ugorji/go/codec v1.2.11 // indirect
|
||||||
golang.org/x/arch v0.5.0 // indirect
|
golang.org/x/arch v0.5.0 // indirect
|
||||||
golang.org/x/crypto v0.12.0 // indirect
|
golang.org/x/crypto v0.13.0 // indirect
|
||||||
golang.org/x/net v0.14.0 // indirect
|
golang.org/x/net v0.14.0 // indirect
|
||||||
golang.org/x/sys v0.12.0 // indirect
|
golang.org/x/sys v0.12.0 // indirect
|
||||||
golang.org/x/text v0.13.0 // indirect
|
golang.org/x/text v0.13.0 // indirect
|
||||||
|
@ -1,3 +1,10 @@
|
|||||||
|
github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da h1:KjTM2ks9d14ZYCvmHS9iAKVt9AyzRSqNU1qabPih5BY=
|
||||||
|
github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da/go.mod h1:eHEWzANqSiWQsof+nXEI9bUVUyV6F53Fp89EuCh2EAA=
|
||||||
|
github.com/aead/chacha20poly1305 v0.0.0-20170617001512-233f39982aeb/go.mod h1:UzH9IX1MMqOcwhoNOIjmTQeAxrFgzs50j4golQtXXxU=
|
||||||
|
github.com/aead/chacha20poly1305 v0.0.0-20201124145622-1a5aba2a8b29 h1:1DcvRPZOdbQRg5nAHt2jrc5QbV0AGuhDdfQI6gXjiFE=
|
||||||
|
github.com/aead/chacha20poly1305 v0.0.0-20201124145622-1a5aba2a8b29/go.mod h1:UzH9IX1MMqOcwhoNOIjmTQeAxrFgzs50j4golQtXXxU=
|
||||||
|
github.com/aead/poly1305 v0.0.0-20180717145839-3fee0db0b635 h1:52m0LGchQBBVqJRyYYufQuIbVqRawmubW3OFGqK1ekw=
|
||||||
|
github.com/aead/poly1305 v0.0.0-20180717145839-3fee0db0b635/go.mod h1:lmLxL+FV291OopO93Bwf9fQLQeLyt33VJRUg5VJ30us=
|
||||||
github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM=
|
github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM=
|
||||||
github.com/bytedance/sonic v1.10.0-rc/go.mod h1:ElCzW+ufi8qKqNW0FY314xriJhyJhuoJ3gFZdAHF7NM=
|
github.com/bytedance/sonic v1.10.0-rc/go.mod h1:ElCzW+ufi8qKqNW0FY314xriJhyJhuoJ3gFZdAHF7NM=
|
||||||
github.com/bytedance/sonic v1.10.0 h1:qtNZduETEIWJVIyDl01BeNxur2rW9OwTQ/yBqFRkKEk=
|
github.com/bytedance/sonic v1.10.0 h1:qtNZduETEIWJVIyDl01BeNxur2rW9OwTQ/yBqFRkKEk=
|
||||||
@ -30,6 +37,8 @@ github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfC
|
|||||||
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
|
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
|
||||||
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
|
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
|
||||||
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
||||||
|
github.com/golang-jwt/jwt/v5 v5.0.0 h1:1n1XNM9hk7O9mnQoNBGolZvzebBQ7p93ULHRc28XJUE=
|
||||||
|
github.com/golang-jwt/jwt/v5 v5.0.0/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
|
||||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||||
github.com/gomodule/redigo v1.8.3 h1:HR0kYDX2RJZvAup8CsiJwxB4dTCSC0AaUq6S4SiLwUc=
|
github.com/gomodule/redigo v1.8.3 h1:HR0kYDX2RJZvAup8CsiJwxB4dTCSC0AaUq6S4SiLwUc=
|
||||||
github.com/gomodule/redigo v1.8.3/go.mod h1:P9dn9mFrCBvWhGE1wpxx6fgq7BAeLBk+UUUzlpkBYO0=
|
github.com/gomodule/redigo v1.8.3/go.mod h1:P9dn9mFrCBvWhGE1wpxx6fgq7BAeLBk+UUUzlpkBYO0=
|
||||||
@ -55,13 +64,19 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w
|
|||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||||
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
|
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
|
||||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||||
|
github.com/o1egl/paseto v1.0.0 h1:bwpvPu2au176w4IBlhbyUv/S5VPptERIA99Oap5qUd0=
|
||||||
|
github.com/o1egl/paseto v1.0.0/go.mod h1:5HxsZPmw/3RI2pAwGo1HhOOwSdvBpcuVzO7uDkm+CLU=
|
||||||
github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4=
|
github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4=
|
||||||
github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc=
|
github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc=
|
||||||
|
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
|
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||||
|
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||||
|
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
@ -78,12 +93,16 @@ github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZ
|
|||||||
golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
|
golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
|
||||||
golang.org/x/arch v0.5.0 h1:jpGode6huXQxcskEIpOCvrU+tzo81b6+oFLUYXWtH/Y=
|
golang.org/x/arch v0.5.0 h1:jpGode6huXQxcskEIpOCvrU+tzo81b6+oFLUYXWtH/Y=
|
||||||
golang.org/x/arch v0.5.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
|
golang.org/x/arch v0.5.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
|
||||||
|
golang.org/x/crypto v0.0.0-20181025213731-e84da0312774/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||||
golang.org/x/crypto v0.12.0 h1:tFM/ta59kqch6LlvYnPa0yx5a83cL2nHflFhYKvv9Yk=
|
golang.org/x/crypto v0.12.0 h1:tFM/ta59kqch6LlvYnPa0yx5a83cL2nHflFhYKvv9Yk=
|
||||||
golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw=
|
golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw=
|
||||||
|
golang.org/x/crypto v0.13.0 h1:mvySKfSWJ+UKUii46M40LOvyWfN0s2U+46/jDd0e6Ck=
|
||||||
|
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
|
||||||
golang.org/x/net v0.14.0 h1:BONx9s002vGdD9umnlX1Po8vOZmrgH34qlHcD1MfK14=
|
golang.org/x/net v0.14.0 h1:BONx9s002vGdD9umnlX1Po8vOZmrgH34qlHcD1MfK14=
|
||||||
golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI=
|
golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI=
|
||||||
golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E=
|
golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E=
|
||||||
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
|
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
|
||||||
|
golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o=
|
golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o=
|
||||||
|
31
server/adminserver/model/session.go
Normal file
31
server/adminserver/model/session.go
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
package model
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
"main/db"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Session struct {
|
||||||
|
Id int64 `db:"id"`
|
||||||
|
Username string `db:"username"`
|
||||||
|
RefreshToken string `db:"refresh_token"`
|
||||||
|
UserAgent string `db:"user_agent"`
|
||||||
|
ClientIp string `db:"client_ip"`
|
||||||
|
ExpiresAt time.Time `db:"expires_at"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func CreateSession(session *Session) (*Session, error) {
|
||||||
|
query := "INSERT INTO t_sessions (id, username, refresh_token, client_ip, user_agent, expires_at) VALUES (?, ?, ?, ?, ?, ?)"
|
||||||
|
result, err := db.GetDB().Exec(query, session.Id, session.Username, session.RefreshToken, session.UserAgent, session.ClientIp, session.ExpiresAt)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Error creating session: %v", err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, err = result.LastInsertId()
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Error getting last insert ID: %v", err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return session, nil
|
||||||
|
}
|
@ -6,17 +6,16 @@ import (
|
|||||||
"main/db"
|
"main/db"
|
||||||
)
|
)
|
||||||
|
|
||||||
// User 结构体表示用户
|
|
||||||
type User struct {
|
type User struct {
|
||||||
AccountId string `db:"account_id"`
|
Id string `db:"id"`
|
||||||
Username string `db:"name"`
|
Username string `db:"username"`
|
||||||
Level int32 `db:"level"`
|
Password string `db:"password"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateUser 创建新用户
|
// CreateUser 创建新用户
|
||||||
func CreateUser(user *User) (int64, error) {
|
func CreateUser(user *User) (int64, error) {
|
||||||
query := "INSERT INTO users (username, email) VALUES (?, ?)"
|
query := "INSERT INTO t_users (username, password) VALUES (?, ?)"
|
||||||
result, err := db.GetDB().Exec(query, user.Username, user.Level)
|
result, err := db.GetDB().Exec(query, user.Username, user.Password)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Error creating user: %v", err)
|
log.Printf("Error creating user: %v", err)
|
||||||
return 0, err
|
return 0, err
|
||||||
@ -29,11 +28,10 @@ func CreateUser(user *User) (int64, error) {
|
|||||||
return userID, nil
|
return userID, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetUserByID 根据用户ID获取用户信息
|
func GetUserByUsername(username string) (*User, error) {
|
||||||
func GetUserByID(userID int64) (*User, error) {
|
query := "SELECT id, username, password FROM t_users WHERE username = ?"
|
||||||
query := "SELECT id, username, email FROM users WHERE id = ?"
|
|
||||||
var user User
|
var user User
|
||||||
err := db.GetDB().Get(&user, query, userID)
|
err := db.GetDB().Get(&user, query, username)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err == sql.ErrNoRows {
|
if err == sql.ErrNoRows {
|
||||||
return nil, nil // 用户不存在
|
return nil, nil // 用户不存在
|
||||||
@ -46,8 +44,8 @@ func GetUserByID(userID int64) (*User, error) {
|
|||||||
|
|
||||||
// UpdateUser 更新用户信息
|
// UpdateUser 更新用户信息
|
||||||
func UpdateUser(user *User) error {
|
func UpdateUser(user *User) error {
|
||||||
query := "UPDATE users SET username = ?, level = ? WHERE id = ?"
|
query := "UPDATE users SET username WHERE id = ?"
|
||||||
_, err := db.GetDB().Exec(query, user.Username, user.Level, user.AccountId)
|
_, err := db.GetDB().Exec(query, user.Username, user.Id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Error updating user: %v", err)
|
log.Printf("Error updating user: %v", err)
|
||||||
return err
|
return err
|
||||||
@ -68,7 +66,7 @@ func DeleteUser(userID int64) error {
|
|||||||
|
|
||||||
// ListUsers 获取所有用户列表
|
// ListUsers 获取所有用户列表
|
||||||
func ListUsers() ([]User, error) {
|
func ListUsers() ([]User, error) {
|
||||||
query := "SELECT account_id, name, level FROM t_user"
|
query := "SELECT id, username, password FROM t_users"
|
||||||
var users []User
|
var users []User
|
||||||
err := db.GetDB().Select(&users, query)
|
err := db.GetDB().Select(&users, query)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
54
server/adminserver/token/jwt_maker.go
Normal file
54
server/adminserver/token/jwt_maker.go
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
package token
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/golang-jwt/jwt/v5"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
const minSecretKeySize = 32
|
||||||
|
|
||||||
|
type JWTMaker struct {
|
||||||
|
secretKey string
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewJWTMaker(secretKey string) (Maker, error) {
|
||||||
|
if len(secretKey) < minSecretKeySize {
|
||||||
|
return nil, fmt.Errorf("invalid key size: must be at least %d characters", minSecretKeySize)
|
||||||
|
}
|
||||||
|
return &JWTMaker{secretKey}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (maker *JWTMaker) CreateToken(username string, duration time.Duration) (string, *Payload, error) {
|
||||||
|
payload, err := NewPayload(username, duration)
|
||||||
|
if err != nil {
|
||||||
|
return "", payload, err
|
||||||
|
}
|
||||||
|
|
||||||
|
jwtToken := jwt.NewWithClaims(jwt.SigningMethodHS256, payload)
|
||||||
|
token, err := jwtToken.SignedString([]byte(maker.secretKey))
|
||||||
|
return token, payload, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// VerifyToken checks if the token is valid or not
|
||||||
|
func (maker *JWTMaker) VerifyToken(token string) (*Payload, error) {
|
||||||
|
keyFunc := func(token *jwt.Token) (interface{}, error) {
|
||||||
|
_, ok := token.Method.(*jwt.SigningMethodHMAC)
|
||||||
|
if !ok {
|
||||||
|
return nil, ErrInvalidToken
|
||||||
|
}
|
||||||
|
return []byte(maker.secretKey), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
jwtToken, err := jwt.ParseWithClaims(token, &Payload{}, keyFunc)
|
||||||
|
if err != nil {
|
||||||
|
return nil, ErrInvalidToken
|
||||||
|
}
|
||||||
|
|
||||||
|
payload, ok := jwtToken.Claims.(*Payload)
|
||||||
|
if !ok {
|
||||||
|
return nil, ErrInvalidToken
|
||||||
|
}
|
||||||
|
|
||||||
|
return payload, nil
|
||||||
|
}
|
57
server/adminserver/token/paseto_maker.go
Normal file
57
server/adminserver/token/paseto_maker.go
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
package token
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/aead/chacha20poly1305"
|
||||||
|
"github.com/o1egl/paseto"
|
||||||
|
)
|
||||||
|
|
||||||
|
// PasetoMaker is a PASETO token maker
|
||||||
|
type PasetoMaker struct {
|
||||||
|
paseto *paseto.V2
|
||||||
|
symmetricKey []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewPasetoMaker creates a new PasetoMaker
|
||||||
|
func NewPasetoMaker(symmetricKey string) (Maker, error) {
|
||||||
|
if len(symmetricKey) != chacha20poly1305.KeySize {
|
||||||
|
return nil, fmt.Errorf("invalid key size: must be exactly %d characters", chacha20poly1305.KeySize)
|
||||||
|
}
|
||||||
|
|
||||||
|
maker := &PasetoMaker{
|
||||||
|
paseto: paseto.NewV2(),
|
||||||
|
symmetricKey: []byte(symmetricKey),
|
||||||
|
}
|
||||||
|
|
||||||
|
return maker, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateToken creates a new token for a specific username and duration
|
||||||
|
func (maker *PasetoMaker) CreateToken(username string, duration time.Duration) (string, *Payload, error) {
|
||||||
|
payload, err := NewPayload(username, duration)
|
||||||
|
if err != nil {
|
||||||
|
return "", payload, err
|
||||||
|
}
|
||||||
|
|
||||||
|
token, err := maker.paseto.Encrypt(maker.symmetricKey, payload, nil)
|
||||||
|
return token, payload, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// VerifyToken checks if the token is valid or not
|
||||||
|
func (maker *PasetoMaker) VerifyToken(token string) (*Payload, error) {
|
||||||
|
payload := &Payload{}
|
||||||
|
|
||||||
|
err := maker.paseto.Decrypt(token, maker.symmetricKey, payload, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, ErrInvalidToken
|
||||||
|
}
|
||||||
|
|
||||||
|
err = payload.Valid()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return payload, nil
|
||||||
|
}
|
@ -3,6 +3,7 @@ package token
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"f5"
|
"f5"
|
||||||
|
"github.com/golang-jwt/jwt/v5"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -18,6 +19,13 @@ type Payload struct {
|
|||||||
ExpiredAt time.Time `json:"expired_at"`
|
ExpiredAt time.Time `json:"expired_at"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//type Payload struct {
|
||||||
|
// ID int64 `json:"id"`
|
||||||
|
// Username string `json:"username"`
|
||||||
|
// IssuedAt int64 `json:"issued_at"`
|
||||||
|
// ExpiredAt int64 `json:"expired_at"`
|
||||||
|
//}
|
||||||
|
|
||||||
func NewPayload(username string, duration time.Duration) (*Payload, error) {
|
func NewPayload(username string, duration time.Duration) (*Payload, error) {
|
||||||
tokenID := f5.GetApp().NewUuid()
|
tokenID := f5.GetApp().NewUuid()
|
||||||
payload := &Payload{
|
payload := &Payload{
|
||||||
@ -35,3 +43,33 @@ func (payload *Payload) Valid() error {
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *Payload) GetExpirationTime() (*jwt.NumericDate, error) {
|
||||||
|
expirationTime := jwt.NewNumericDate(p.ExpiredAt)
|
||||||
|
return expirationTime, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Payload) GetIssuedAt() (*jwt.NumericDate, error) {
|
||||||
|
issuedAt := jwt.NewNumericDate(p.IssuedAt)
|
||||||
|
return issuedAt, nil
|
||||||
|
//return p.IssuedAt
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Payload) GetNotBefore() (*jwt.NumericDate, error) {
|
||||||
|
now := jwt.NewNumericDate(time.Time{})
|
||||||
|
return now, nil
|
||||||
|
//return time.Time{} // 默认返回零值,或根据需求设置合适的值
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Payload) GetIssuer() (string, error) {
|
||||||
|
return "your_issuer", nil // 可根据需求返回合适的签发者(Issuer)信息
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Payload) GetSubject() (string, error) {
|
||||||
|
return p.Username, nil // 使用用户名作为主题(Subject)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Payload) GetAudience() (jwt.ClaimStrings, error) {
|
||||||
|
audience := "your_audience" // 根据需求设置合适的受众(Audience)信息
|
||||||
|
return jwt.ClaimStrings{audience}, nil
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user