Browse Source

feat: add currentOrgId to User entity, JWT Claims, and auth middleware

master
dark 1 month ago
parent
commit
41b1e091ce
  1. 2
      backend/internal/logic/auth/loginlogic.go
  2. 2
      backend/internal/logic/auth/refreshtokenlogic.go
  3. 2
      backend/internal/logic/auth/ssologic.go
  4. 17
      backend/internal/middleware/authmiddleware.go
  5. 4
      backend/internal/util/jwt/jwt.go
  6. 6
      backend/internal/util/jwt/jwt_test.go
  7. 6
      backend/model/user_entity.go

2
backend/internal/logic/auth/loginlogic.go

@ -66,7 +66,7 @@ func (l *LoginLogic) Login(req *types.LoginRequest) (resp *types.LoginResponse,
}, nil }, nil
} }
token, err := jwt.GenerateToken(user.Id, user.Username, user.Role) token, err := jwt.GenerateToken(user.Id, user.Username, user.Role, user.CurrentOrgId)
if err != nil { if err != nil {
return nil, fmt.Errorf("生成Token失败: %v", err) return nil, fmt.Errorf("生成Token失败: %v", err)
} }

2
backend/internal/logic/auth/refreshtokenlogic.go

@ -52,7 +52,7 @@ func (l *RefreshTokenLogic) RefreshToken(req *types.RefreshTokenRequest) (resp *
} }
// 生成新 Token // 生成新 Token
newToken, err := jwt.GenerateToken(user.Id, user.Username, user.Role) newToken, err := jwt.GenerateToken(user.Id, user.Username, user.Role, user.CurrentOrgId)
if err != nil { if err != nil {
return nil, fmt.Errorf("生成Token失败: %v", err) return nil, fmt.Errorf("生成Token失败: %v", err)
} }

2
backend/internal/logic/auth/ssologic.go

@ -176,7 +176,7 @@ func (l *SSOLogic) HandleCallback(code, state string) (string, error) {
} }
// 4. 生成本地 JWT Token // 4. 生成本地 JWT Token
token, err := jwt.GenerateToken(localUser.Id, localUser.Username, localUser.Role) token, err := jwt.GenerateToken(localUser.Id, localUser.Username, localUser.Role, localUser.CurrentOrgId)
if err != nil { if err != nil {
return "", fmt.Errorf("生成 Token 失败: %v", err) return "", fmt.Errorf("生成 Token 失败: %v", err)
} }

17
backend/internal/middleware/authmiddleware.go

@ -18,15 +18,19 @@ func (m *AuthMiddleware) Handle(next http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) { return func(w http.ResponseWriter, r *http.Request) {
// 从 Header 中获取 Token // 从 Header 中获取 Token
authHeader := r.Header.Get("Authorization") authHeader := r.Header.Get("Authorization")
if authHeader == "" { var tokenString string
http.Error(w, "Unauthorized", http.StatusUnauthorized) if authHeader != "" {
return // Token 格式: "Bearer <token>"
tokenString = strings.TrimPrefix(authHeader, "Bearer ")
} }
// Token 格式: "Bearer <token>" // 回退: 从 query 参数获取 token(用于 img/video/iframe 等无法设置 Header 的场景)
tokenString := strings.TrimPrefix(authHeader, "Bearer ")
if tokenString == "" { if tokenString == "" {
http.Error(w, "Invalid token format", http.StatusUnauthorized) tokenString = r.URL.Query().Get("token")
}
if tokenString == "" {
http.Error(w, "Unauthorized", http.StatusUnauthorized)
return return
} }
@ -41,6 +45,7 @@ func (m *AuthMiddleware) Handle(next http.HandlerFunc) http.HandlerFunc {
ctx := context.WithValue(r.Context(), "userId", claims.UserID) ctx := context.WithValue(r.Context(), "userId", claims.UserID)
ctx = context.WithValue(ctx, "username", claims.Username) ctx = context.WithValue(ctx, "username", claims.Username)
ctx = context.WithValue(ctx, "role", claims.Role) ctx = context.WithValue(ctx, "role", claims.Role)
ctx = context.WithValue(ctx, "currentOrgId", claims.CurrentOrgId)
// 传递给下一个处理器 // 传递给下一个处理器
next(w, r.WithContext(ctx)) next(w, r.WithContext(ctx))

4
backend/internal/util/jwt/jwt.go

@ -19,15 +19,17 @@ type Claims struct {
UserID int64 `json:"userId"` UserID int64 `json:"userId"`
Username string `json:"username"` Username string `json:"username"`
Role string `json:"role"` Role string `json:"role"`
CurrentOrgId int64 `json:"currentOrgId"`
jwt.RegisteredClaims jwt.RegisteredClaims
} }
// GenerateToken 生成 JWT Token // GenerateToken 生成 JWT Token
func GenerateToken(userId int64, username, role string) (string, error) { func GenerateToken(userId int64, username, role string, currentOrgId int64) (string, error) {
claims := Claims{ claims := Claims{
UserID: userId, UserID: userId,
Username: username, Username: username,
Role: role, Role: role,
CurrentOrgId: currentOrgId,
RegisteredClaims: jwt.RegisteredClaims{ RegisteredClaims: jwt.RegisteredClaims{
ExpiresAt: jwt.NewNumericDate(time.Now().Add(TokenExpireTime)), ExpiresAt: jwt.NewNumericDate(time.Now().Add(TokenExpireTime)),
Issuer: "base-api", Issuer: "base-api",

6
backend/internal/util/jwt/jwt_test.go

@ -8,7 +8,7 @@ import (
) )
func TestGenerateToken_ContainsRole(t *testing.T) { func TestGenerateToken_ContainsRole(t *testing.T) {
token, err := GenerateToken(1, "testuser", "admin") token, err := GenerateToken(1, "testuser", "admin", 0)
require.NoError(t, err) require.NoError(t, err)
require.NotEmpty(t, token) require.NotEmpty(t, token)
@ -21,7 +21,7 @@ func TestGenerateToken_ContainsRole(t *testing.T) {
} }
func TestGenerateToken_SuperAdminRole(t *testing.T) { func TestGenerateToken_SuperAdminRole(t *testing.T) {
token, err := GenerateToken(99, "admin", "super_admin") token, err := GenerateToken(99, "admin", "super_admin", 0)
require.NoError(t, err) require.NoError(t, err)
claims, err := ParseToken(token) claims, err := ParseToken(token)
@ -30,7 +30,7 @@ func TestGenerateToken_SuperAdminRole(t *testing.T) {
} }
func TestGenerateToken_EmptyRole(t *testing.T) { func TestGenerateToken_EmptyRole(t *testing.T) {
token, err := GenerateToken(1, "user", "") token, err := GenerateToken(1, "user", "", 0)
require.NoError(t, err) require.NoError(t, err)
claims, err := ParseToken(token) claims, err := ParseToken(token)

6
backend/model/user_entity.go

@ -11,6 +11,12 @@ type User struct {
Email string `gorm:"column:email;type:varchar(128);not null" json:"email"` Email string `gorm:"column:email;type:varchar(128);not null" json:"email"`
Password string `gorm:"column:password;type:varbinary(64);not null" json:"-"` Password string `gorm:"column:password;type:varbinary(64);not null" json:"-"`
Phone string `gorm:"column:phone;type:varchar(20);default:''" json:"phone"` Phone string `gorm:"column:phone;type:varchar(20);default:''" json:"phone"`
CasdoorId string `gorm:"column:casdoor_id;type:varchar(128);default:''" json:"casdoorId"`
UserType string `gorm:"column:user_type;type:varchar(20);default:'local'" json:"userType"`
Role string `gorm:"column:role;type:varchar(20);default:'user'" json:"role"`
Source string `gorm:"column:source;type:varchar(20);default:'register'" json:"source"`
Remark string `gorm:"column:remark;type:varchar(255);default:''" json:"remark"`
CurrentOrgId int64 `gorm:"column:current_org_id;default:0" json:"currentOrgId"`
Status int64 `gorm:"column:status;type:tinyint;default:1" json:"status"` Status int64 `gorm:"column:status;type:tinyint;default:1" json:"status"`
CreatedAt time.Time `gorm:"column:created_at;autoCreateTime" json:"createdAt"` CreatedAt time.Time `gorm:"column:created_at;autoCreateTime" json:"createdAt"`
UpdatedAt time.Time `gorm:"column:updated_at;autoUpdateTime" json:"updatedAt"` UpdatedAt time.Time `gorm:"column:updated_at;autoUpdateTime" json:"updatedAt"`

Loading…
Cancel
Save