auth

package
v1.4.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 8, 2026 License: Apache-2.0 Imports: 20 Imported by: 0

Documentation

Overview

Package auth 提供用户认证相关的 HTTP 处理器

Package auth 提供用户认证相关的中间件

Package auth 提供用户认证相关功能

Index

Constants

View Source
const (
	// DefaultCLITokenTTL 是密码登录未指定有效期时使用的期限。
	// DefaultCLITokenTTL is used when password login does not specify an expiry.
	DefaultCLITokenTTL = 7 * 24 * time.Hour

	// MinCLITokenTTLDays 是自定义有效期允许的最少天数。
	// MinCLITokenTTLDays is the minimum custom lifetime in days.
	MinCLITokenTTLDays = 1
	// MaxCLITokenTTLDays 是自定义有效期允许的最多天数。
	// MaxCLITokenTTLDays is the maximum custom lifetime in days.
	MaxCLITokenTTLDays = 3650

	// CLITokenStatusActive 表示令牌可用。
	// CLITokenStatusActive means the token can still be used.
	CLITokenStatusActive = "active"
	// CLITokenStatusExpired 表示令牌已过期。
	// CLITokenStatusExpired means the token has expired.
	CLITokenStatusExpired = "expired"
	// CLITokenStatusRevoked 表示令牌已吊销。
	// CLITokenStatusRevoked means the token has been revoked.
	CLITokenStatusRevoked = "revoked"
)
View Source
const (
	SessionKeyUserID   = "user_id"
	SessionKeyUsername = "username"
)

会话键常量

View Source
const (
	ErrMsgInvalidCredentials = "用户名或密码错误"
	ErrMsgEmptyCredentials   = "用户名和密码不能为空"
	ErrMsgUserInactive       = "用户账户已禁用"
	ErrMsgSessionError       = "会话错误"
	ErrMsgInternalError      = "内部服务器错误"
	ErrMsgCLIHeaderRequired  = "缺少 CLI 请求标识"
	ErrMsgCLITokenInvalid    = "CLI 令牌无效或已过期"
)

错误消息常量(不暴露具体是用户名还是密码错误)

View Source
const (
	ContextKeyUser     = "auth_user"
	ContextKeyCLIToken = "auth_cli_token"
)

上下文键常量

View Source
const DefaultBcryptCost = 10

DefaultBcryptCost 默认 bcrypt 加密成本

View Source
const DefaultLanguage = "zh"

DefaultLanguage 默认用户语言偏好

Variables

View Source
var (
	// ErrInvalidCLITokenTTL 表示令牌有效期不是 1d-3650d 或 never。
	// ErrInvalidCLITokenTTL means the lifetime is not 1d-3650d or never.
	ErrInvalidCLITokenTTL = errors.New("auth: CLI 令牌有效期必须是 1d 到 3650d,或 never")
	// ErrInvalidCLIToken 表示令牌不存在、已撤销或已过期。
	// ErrInvalidCLIToken means the token is unknown, revoked, or expired.
	ErrInvalidCLIToken = errors.New("auth: CLI 令牌无效")
	// ErrCLITokenRevoked 表示令牌已经撤销。
	// ErrCLITokenRevoked means the token has been revoked.
	ErrCLITokenRevoked = errors.New("auth: CLI 令牌已撤销")
	// ErrCLITokenExpired 表示令牌已经过期。
	// ErrCLITokenExpired means the token has expired.
	ErrCLITokenExpired = errors.New("auth: CLI 令牌已过期")
	// ErrCLITokenNameRequired 表示管理员签发令牌时未填写名称。
	// ErrCLITokenNameRequired means an admin-issued token is missing a name.
	ErrCLITokenNameRequired = errors.New("auth: CLI 令牌名称不能为空")
	// ErrCLITokenNameTooLong 表示令牌名称超过 100 个字符。
	// ErrCLITokenNameTooLong means the token name exceeds 100 characters.
	ErrCLITokenNameTooLong = errors.New("auth: CLI 令牌名称不能超过 100 个字符")
	// ErrCLITokenNotFound 表示按编号找不到令牌。
	// ErrCLITokenNotFound means the token id does not exist.
	ErrCLITokenNotFound = errors.New("auth: CLI 令牌不存在")
)
View Source
var (
	ErrUserNotFound      = errors.New("auth: 用户不存在")
	ErrInvalidPassword   = errors.New("auth: 密码错误")
	ErrUserInactive      = errors.New("auth: 用户已禁用")
	ErrEmptyCredentials  = errors.New("auth: 用户名或密码不能为空")
	ErrPasswordTooShort  = errors.New("auth: 密码长度不能少于6位")
	ErrUserAlreadyExists = errors.New("auth: 用户名已存在")
)

错误定义

View Source
var OnUserBound func(c *gin.Context)

SetUserToContext 将用户信息存入 Gin 上下文。 SetUserToContext stores the user on the Gin context. OnUserBound 在用户写入后调用,用来把同一次请求的操作人挂到后续 Agent 命令上。 OnUserBound runs after the user is stored so later Agent commands share this request.

Functions

func AdminRequired

func AdminRequired() gin.HandlerFunc

AdminRequired 管理员权限验证中间件 验证用户是否为管理员,如果不是则返回 403 错误 注意:此中间件应在 LoginRequired 之后使用

func AuthenticateCLIToken

func AuthenticateCLIToken(database *gorm.DB, plaintext string, now time.Time) (*CLIToken, *User, error)

AuthenticateCLIToken 校验令牌、用户状态,并更新最近使用时间。 AuthenticateCLIToken validates the token and user, then updates last-used time.

func CLIAuthRequired

func CLIAuthRequired() gin.HandlerFunc

CLIAuthRequired 验证 CLI Bearer 令牌并按当前数据库状态加载用户。 CLIAuthRequired validates a CLI Bearer token and loads the current user state.

func CLIClientRequired

func CLIClientRequired() gin.HandlerFunc

CLIClientRequired 只允许带有 CLI 请求标识的调用进入 CLI 接口。 CLIClientRequired allows requests with the CLI marker to enter CLI endpoints.

func CLILogin

func CLILogin(c *gin.Context)

CLILogin 通过用户名密码签发 CLI Bearer 令牌。 CLILogin issues a CLI Bearer token after username/password verification. @Tags auth @Accept json @Produce json @Param request body CLILoginRequest true "CLI 登录请求" @Success 200 {object} CLILoginResponse @Router /api/v1/auth/cli/login [post]

func CLILogout

func CLILogout(c *gin.Context)

CLILogout 撤销当前 CLI Bearer 令牌。 CLILogout revokes the current CLI Bearer token. @Tags auth @Produce json @Success 200 {object} LogoutResponse @Router /api/v1/auth/cli/logout [post]

func CLITokenStatusOf added in v1.2.0

func CLITokenStatusOf(token *CLIToken, now time.Time) string

CLITokenStatusOf 根据吊销和过期时间计算令牌状态。 CLITokenStatusOf computes token status from revocation and expiry.

func CLIWhoAmI

func CLIWhoAmI(c *gin.Context)

CLIWhoAmI 返回当前 CLI 令牌对应的用户和令牌元数据。 CLIWhoAmI returns the user and token metadata associated with the current CLI token. @Tags auth @Produce json @Success 200 {object} CLIWhoAmIResponse @Router /api/v1/auth/cli/whoami [get]

func ContextWithCLITokenForTest added in v1.2.0

func ContextWithCLITokenForTest(ctx context.Context, token *CLIToken) context.Context

ContextWithCLITokenForTest 仅供单测把 CLI 令牌写入 context。 ContextWithCLITokenForTest is a test helper that stores a CLI token on a plain context.

func GetUserIDFromContext

func GetUserIDFromContext(c *gin.Context) uint64

GetUserIDFromContext 从 Gin 上下文获取用户 ID

func GetUserInfo

func GetUserInfo(c *gin.Context)

GetUserInfo 获取当前登录用户信息 @Tags auth @Produce json @Success 200 {object} UserInfoResponse @Router /api/v1/auth/user-info [get]

func GetUsernameFromContext

func GetUsernameFromContext(c *gin.Context) string

GetUsernameFromContext 从 Gin 上下文获取用户名

func ListCLITokens added in v1.2.0

func ListCLITokens(database *gorm.DB, filter CLITokenFilter, now time.Time) ([]CLITokenInfo, int64, CLITokenCounts, error)

ListCLITokens 返回管理员可见的令牌元数据与状态统计。 ListCLITokens returns administrator-visible token metadata and status counts.

func Login

func Login(c *gin.Context)

Login 处理用户登录 @Tags auth @Accept json @Produce json @Param request body LoginRequest true "登录请求" @Success 200 {object} LoginResponse @Router /api/v1/auth/login [post]

func LoginRequired

func LoginRequired() gin.HandlerFunc

LoginRequired 登录验证中间件 验证用户是否已登录,如果未登录则返回 401 错误

func LoginRequiredSessionOnly

func LoginRequiredSessionOnly() gin.HandlerFunc

LoginRequiredSessionOnly 轻量会话登录验证中间件(不查数据库) 适用于高频静态资源代理场景,避免每个请求触发数据库读取。

func Logout

func Logout(c *gin.Context)

Logout 处理用户登出 @Tags auth @Produce json @Success 200 {object} LogoutResponse @Router /api/v1/auth/logout [post]

func NormalizeLanguage

func NormalizeLanguage(value string) string

NormalizeLanguage 归一化用户语言偏好

func NormalizeTimezone added in v1.2.0

func NormalizeTimezone(value string) (string, bool)

NormalizeTimezone 校验用户时区:空串(跟随浏览器)或合法 IANA 名称;非法返回 false。 NormalizeTimezone validates a user timezone: "" (follow browser) or a valid IANA name.

func RevokeCLIToken

func RevokeCLIToken(database *gorm.DB, plaintext string, now time.Time) error

RevokeCLIToken 撤销令牌;重复撤销保持成功,便于登出请求幂等。 RevokeCLIToken revokes a token; repeated revocation remains successful.

func SetUserToContext

func SetUserToContext(c *gin.Context, user *User)

func UpdateProfile

func UpdateProfile(c *gin.Context)

UpdateProfile 更新当前登录用户的个人信息(支持邮箱和语言偏好)。 @Tags auth @Accept json @Produce json @Param request body UpdateProfileRequest true "更新个人信息请求" @Success 200 {object} UpdateProfileResponse @Router /api/v1/auth/profile [put]

Types

type CLILoginData

type CLILoginData struct {
	Token     string     `json:"token"`
	TokenType string     `json:"token_type"`
	ExpiresAt *time.Time `json:"expires_at,omitempty"`
	Permanent bool       `json:"permanent"`
	User      *UserInfo  `json:"user"`
}

CLILoginData 是 CLI 登录响应中的令牌信息。 CLILoginData contains the token information in a CLI login response.

type CLILoginRequest

type CLILoginRequest struct {
	Username  string `json:"username" binding:"required"`
	Password  string `json:"password" binding:"required"`
	ExpiresIn string `json:"expires_in"`
}

CLILoginRequest 是 CLI 登录请求。 CLILoginRequest is the CLI login request.

type CLILoginResponse

type CLILoginResponse struct {
	ErrorMsg string        `json:"error_msg"`
	Data     *CLILoginData `json:"data"`
}

CLILoginResponse 是 CLI 登录响应。 CLILoginResponse is the CLI login response.

type CLIToken

type CLIToken struct {
	ID          uint64     `json:"id" gorm:"primaryKey;autoIncrement"`
	UserID      uint64     `json:"user_id" gorm:"index;not null"`
	Name        string     `json:"name" gorm:"size:100;index"`
	TokenPrefix string     `json:"token_prefix" gorm:"size:16;index;not null"`
	TokenHash   string     `json:"-" gorm:"column:token_hash;size:64;unique;not null"`
	ExpiresAt   *time.Time `json:"expires_at,omitempty" gorm:"index"`
	RevokedAt   *time.Time `json:"revoked_at,omitempty" gorm:"index"`
	LastUsedAt  *time.Time `json:"last_used_at,omitempty"`
	CreatedAt   time.Time  `json:"created_at" gorm:"autoCreateTime"`
	UpdatedAt   time.Time  `json:"updated_at" gorm:"autoUpdateTime"`
}

CLIToken 保存 CLI 令牌的不可逆信息,不保存令牌原文。 CLIToken stores irreversible token data and never stores the plaintext token.

func CLITokenFromContext added in v1.2.0

func CLITokenFromContext(ctx context.Context) *CLIToken

CLITokenFromContext 从普通 context 读取已校验的 CLI 令牌。 CLITokenFromContext reads the authenticated CLI token from a plain context.

func FindCLITokenByID added in v1.2.0

func FindCLITokenByID(database *gorm.DB, id uint64) (*CLIToken, error)

FindCLITokenByID 按编号读取令牌元数据。 FindCLITokenByID loads token metadata by id.

func GetCLITokenFromGin added in v1.2.0

func GetCLITokenFromGin(c *gin.Context) *CLIToken

GetCLITokenFromGin 读取当前 HTTP 请求绑定的 CLI 令牌。 GetCLITokenFromGin returns the CLI token bound to the current HTTP request.

func RevokeCLITokenByID added in v1.2.0

func RevokeCLITokenByID(database *gorm.DB, id uint64, now time.Time) (*CLIToken, error)

RevokeCLITokenByID 按编号吊销令牌;重复吊销保持成功。 RevokeCLITokenByID revokes a token by id; repeated revocation remains successful.

func (CLIToken) TableName

func (CLIToken) TableName() string

TableName 指定 CLI 令牌表名。 TableName specifies the CLI token table name.

func (CLIToken) ToInfo added in v1.2.0

func (t CLIToken) ToInfo(username string, now time.Time) CLITokenInfo

ToInfo 把令牌行转成不含哈希的展示结构。 ToInfo converts a token row into display metadata without the hash.

type CLITokenCounts added in v1.2.0

type CLITokenCounts struct {
	Total   int64 `json:"total"`
	Active  int64 `json:"active"`
	Expired int64 `json:"expired"`
	Revoked int64 `json:"revoked"`
}

CLITokenCounts 是令牌状态统计。 CLITokenCounts is the token status summary.

type CLITokenFilter added in v1.2.0

type CLITokenFilter struct {
	UserID   uint64
	Username string
	Name     string
	Status   string
	Page     int
	PageSize int
}

CLITokenFilter 是管理员令牌列表的筛选条件。 CLITokenFilter is the administrator token list filter.

type CLITokenInfo added in v1.2.0

type CLITokenInfo struct {
	ID          uint64     `json:"id"`
	UserID      uint64     `json:"user_id"`
	Username    string     `json:"username"`
	Name        string     `json:"name"`
	TokenPrefix string     `json:"token_prefix"`
	ExpiresAt   *time.Time `json:"expires_at,omitempty"`
	RevokedAt   *time.Time `json:"revoked_at,omitempty"`
	LastUsedAt  *time.Time `json:"last_used_at,omitempty"`
	CreatedAt   time.Time  `json:"created_at"`
	Permanent   bool       `json:"permanent"`
	Status      string     `json:"status"`
}

CLITokenInfo 是管理员列表使用的令牌元数据,不含哈希和原文。 CLITokenInfo is administrator list metadata without the hash or plaintext.

type CLITokenIssue

type CLITokenIssue struct {
	ID        uint64     `json:"id"`
	Token     string     `json:"token"`
	Prefix    string     `json:"prefix"`
	Name      string     `json:"name,omitempty"`
	ExpiresAt *time.Time `json:"expires_at,omitempty"`
	Permanent bool       `json:"permanent"`
}

CLITokenIssue 是创建令牌后仅返回一次的结果。 CLITokenIssue is returned once when a token is created.

func IssueCLIToken

func IssueCLIToken(database *gorm.DB, user *User, expiresIn string, now time.Time) (*CLITokenIssue, error)

IssueCLIToken 校验用户并生成随机令牌,只把哈希和元数据写入数据库。 IssueCLIToken validates the user and stores only a hash and metadata.

func IssueNamedCLIToken added in v1.2.0

func IssueNamedCLIToken(database *gorm.DB, user *User, name, expiresIn string, now time.Time) (*CLITokenIssue, error)

IssueNamedCLIToken 由管理员签发带名称的 CLI 令牌,原文只返回一次。 IssueNamedCLIToken issues a named CLI token for an administrator; plaintext is returned once.

type CLITokenLifetime added in v1.2.0

type CLITokenLifetime struct {
	Permanent bool
	TTL       time.Duration
}

CLITokenLifetime 表示解析后的令牌有效期。 CLITokenLifetime is a parsed token lifetime.

func ParseCLITokenTTL

func ParseCLITokenTTL(value string) (CLITokenLifetime, error)

ParseCLITokenTTL 校验并解析 7d/30d/90d/never 或自定义 Nd。 ParseCLITokenTTL validates presets 7d/30d/90d/never or a custom Nd lifetime.

type CLIWhoAmIData added in v1.2.0

type CLIWhoAmIData struct {
	UserInfo
	TokenID        uint64     `json:"token_id,omitempty"`
	TokenPrefix    string     `json:"token_prefix,omitempty"`
	TokenName      string     `json:"token_name,omitempty"`
	TokenExpiresAt *time.Time `json:"token_expires_at,omitempty"`
	Permanent      bool       `json:"permanent"`
}

CLIWhoAmIData 是 whoami 返回的用户和当前令牌元数据。 CLIWhoAmIData is the whoami payload with the current token metadata.

type CLIWhoAmIResponse added in v1.2.0

type CLIWhoAmIResponse struct {
	ErrorMsg string         `json:"error_msg"`
	Data     *CLIWhoAmIData `json:"data"`
}

CLIWhoAmIResponse 是 CLI whoami 响应。 CLIWhoAmIResponse is the CLI whoami response.

type ErrorResponse

type ErrorResponse struct {
	ErrorMsg string      `json:"error_msg"`
	Data     interface{} `json:"data"`
}

错误响应

type LoginRequest

type LoginRequest struct {
	Username string `json:"username" binding:"required"`
	Password string `json:"password" binding:"required"`
}

LoginRequest 登录请求

type LoginResponse

type LoginResponse struct {
	ErrorMsg string      `json:"error_msg"`
	Data     interface{} `json:"data"`
}

LoginResponse 登录响应

type LogoutResponse

type LogoutResponse struct {
	ErrorMsg string      `json:"error_msg"`
	Data     interface{} `json:"data"`
}

LogoutResponse 登出响应

type UpdateProfileRequest

type UpdateProfileRequest struct {
	Email    string `json:"email" binding:"omitempty,max=255"`
	Language string `json:"language" binding:"omitempty,oneof=zh en"`
	// Timezone 为 nil 表示不修改;空串表示跟随浏览器;否则必须为 IANA 时区。
	// Timezone nil = unchanged; "" = follow browser; otherwise an IANA timezone name.
	Timezone *string `json:"timezone"`
}

UpdateProfileRequest 更新当前登录用户的个人信息请求。

type UpdateProfileResponse

type UpdateProfileResponse struct {
	ErrorMsg string    `json:"error_msg"`
	Data     *UserInfo `json:"data"`
}

UpdateProfileResponse 更新当前登录用户的个人信息响应。

type User

type User struct {
	ID           uint64 `json:"id" gorm:"primaryKey;autoIncrement"`
	Username     string `json:"username" gorm:"size:255;unique;not null"`
	PasswordHash string `json:"-" gorm:"column:password_hash;size:255"` // 密码哈希,OAuth 用户可为空
	Nickname     string `json:"nickname" gorm:"size:255"`
	Email        string `json:"email" gorm:"size:255;index"`
	Language     string `json:"language" gorm:"size:8;default:zh"`
	// Timezone 用户展示时区(IANA);空串表示跟随浏览器。/ User display timezone (IANA); empty means follow the browser.
	Timezone    string     `json:"timezone" gorm:"size:64;default:''"`
	AvatarURL   string     `json:"avatar_url" gorm:"column:avatar_url;size:255"`   // 头像 URL
	OAuthID     string     `json:"oauth_id" gorm:"column:oauth_id;size:255;index"` // OAuth 提供商 ID,格式: provider:id
	IsActive    bool       `json:"is_active" gorm:"default:true"`
	IsAdmin     bool       `json:"is_admin" gorm:"default:false"`
	LastLoginAt *time.Time `json:"last_login_at"`
	CreatedAt   time.Time  `json:"created_at" gorm:"autoCreateTime"`
	UpdatedAt   time.Time  `json:"updated_at" gorm:"autoUpdateTime"`
}

User 用户模型 用于存储系统用户信息,支持用户名密码认证和 OAuth 认证

func FindByID

func FindByID(db *gorm.DB, id uint64) (*User, error)

FindByID 根据 ID 查找用户

func FindByOAuthID

func FindByOAuthID(db *gorm.DB, oauthID string) (*User, error)

FindByOAuthID 根据 OAuth ID 查找用户

func FindByUsername

func FindByUsername(db *gorm.DB, username string) (*User, error)

FindByUsername 根据用户名查找用户

func GetUserFromContext

func GetUserFromContext(c *gin.Context) *User

GetUserFromContext 从 Gin 上下文获取用户信息

func (*User) CheckPassword

func (u *User) CheckPassword(password string) bool

CheckPassword 验证密码是否正确 使用 bcrypt 算法比较密码哈希

func (*User) Create

func (u *User) Create(db *gorm.DB) error

Create 创建新用户

func (*User) IsValidBcryptHash

func (u *User) IsValidBcryptHash() bool

IsValidBcryptHash 检查密码哈希是否为有效的 bcrypt 哈希

func (*User) SetPassword

func (u *User) SetPassword(password string, cost int) error

SetPassword 设置用户密码 使用 bcrypt 算法对密码进行哈希处理 cost 参数指定 bcrypt 的计算成本,如果为 0 则使用默认值

func (User) TableName

func (User) TableName() string

TableName 指定表名 使用 auth_users 避免与 oauth.User 的 users 表冲突

func (*User) ToUserInfo

func (u *User) ToUserInfo() *UserInfo

ToUserInfo 将 User 转换为 UserInfo

func (*User) UpdateLastLogin

func (u *User) UpdateLastLogin(db *gorm.DB) error

UpdateLastLogin 更新最后登录时间

type UserInfo

type UserInfo struct {
	ID       uint64 `json:"id"`
	Username string `json:"username"`
	Nickname string `json:"nickname"`
	Email    string `json:"email"`
	Language string `json:"language"`
	Timezone string `json:"timezone"`
	// SystemTimezone 系统默认展示时区(app.display_timezone)。/ System default display timezone.
	SystemTimezone string     `json:"system_timezone"`
	AvatarURL      string     `json:"avatar_url"`
	IsActive       bool       `json:"is_active"`
	IsAdmin        bool       `json:"is_admin"`
	LastLoginAt    *time.Time `json:"last_login_at"`
	CreatedAt      time.Time  `json:"created_at"`
}

UserInfo 用户信息(用于 API 响应,不包含敏感信息)

type UserInfoResponse

type UserInfoResponse struct {
	ErrorMsg string    `json:"error_msg"`
	Data     *UserInfo `json:"data"`
}

UserInfoResponse 用户信息响应

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL