Documentation
¶
Overview ¶
Package auth 提供用户认证相关的 HTTP 处理器
Package auth 提供用户认证相关的中间件 ¶
Package auth 提供用户认证相关功能
Index ¶
- Constants
- Variables
- func AdminRequired() gin.HandlerFunc
- func AuthenticateCLIToken(database *gorm.DB, plaintext string, now time.Time) (*CLIToken, *User, error)
- func CLIAuthRequired() gin.HandlerFunc
- func CLIClientRequired() gin.HandlerFunc
- func CLILogin(c *gin.Context)
- func CLILogout(c *gin.Context)
- func CLITokenStatusOf(token *CLIToken, now time.Time) string
- func CLIWhoAmI(c *gin.Context)
- func ContextWithCLITokenForTest(ctx context.Context, token *CLIToken) context.Context
- func GetUserIDFromContext(c *gin.Context) uint64
- func GetUserInfo(c *gin.Context)
- func GetUsernameFromContext(c *gin.Context) string
- func ListCLITokens(database *gorm.DB, filter CLITokenFilter, now time.Time) ([]CLITokenInfo, int64, CLITokenCounts, error)
- func Login(c *gin.Context)
- func LoginRequired() gin.HandlerFunc
- func LoginRequiredSessionOnly() gin.HandlerFunc
- func Logout(c *gin.Context)
- func NormalizeLanguage(value string) string
- func NormalizeTimezone(value string) (string, bool)
- func RevokeCLIToken(database *gorm.DB, plaintext string, now time.Time) error
- func SetUserToContext(c *gin.Context, user *User)
- func UpdateProfile(c *gin.Context)
- type CLILoginData
- type CLILoginRequest
- type CLILoginResponse
- type CLIToken
- type CLITokenCounts
- type CLITokenFilter
- type CLITokenInfo
- type CLITokenIssue
- type CLITokenLifetime
- type CLIWhoAmIData
- type CLIWhoAmIResponse
- type ErrorResponse
- type LoginRequest
- type LoginResponse
- type LogoutResponse
- type UpdateProfileRequest
- type UpdateProfileResponse
- type User
- func (u *User) CheckPassword(password string) bool
- func (u *User) Create(db *gorm.DB) error
- func (u *User) IsValidBcryptHash() bool
- func (u *User) SetPassword(password string, cost int) error
- func (User) TableName() string
- func (u *User) ToUserInfo() *UserInfo
- func (u *User) UpdateLastLogin(db *gorm.DB) error
- type UserInfo
- type UserInfoResponse
Constants ¶
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" )
const ( SessionKeyUserID = "user_id" SessionKeyUsername = "username" )
会话键常量
const ( ErrMsgInvalidCredentials = "用户名或密码错误" ErrMsgEmptyCredentials = "用户名和密码不能为空" ErrMsgUserInactive = "用户账户已禁用" ErrMsgSessionError = "会话错误" ErrMsgInternalError = "内部服务器错误" ErrMsgCLIHeaderRequired = "缺少 CLI 请求标识" ErrMsgCLITokenInvalid = "CLI 令牌无效或已过期" )
错误消息常量(不暴露具体是用户名还是密码错误)
const ( ContextKeyUser = "auth_user" ContextKeyCLIToken = "auth_cli_token" )
上下文键常量
const DefaultBcryptCost = 10
DefaultBcryptCost 默认 bcrypt 加密成本
const DefaultLanguage = "zh"
DefaultLanguage 默认用户语言偏好
Variables ¶
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 令牌不存在") )
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: 用户名已存在") )
错误定义
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 ¶
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 ¶
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
CLITokenStatusOf 根据吊销和过期时间计算令牌状态。 CLITokenStatusOf computes token status from revocation and expiry.
func CLIWhoAmI ¶
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
ContextWithCLITokenForTest 仅供单测把 CLI 令牌写入 context。 ContextWithCLITokenForTest is a test helper that stores a CLI token on a plain context.
func GetUserIDFromContext ¶
GetUserIDFromContext 从 Gin 上下文获取用户 ID
func GetUserInfo ¶
GetUserInfo 获取当前登录用户信息 @Tags auth @Produce json @Success 200 {object} UserInfoResponse @Router /api/v1/auth/user-info [get]
func GetUsernameFromContext ¶
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 ¶
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 ¶
Logout 处理用户登出 @Tags auth @Produce json @Success 200 {object} LogoutResponse @Router /api/v1/auth/logout [post]
func NormalizeTimezone ¶ added in v1.2.0
NormalizeTimezone 校验用户时区:空串(跟随浏览器)或合法 IANA 名称;非法返回 false。 NormalizeTimezone validates a user timezone: "" (follow browser) or a valid IANA name.
func RevokeCLIToken ¶
RevokeCLIToken 撤销令牌;重复撤销保持成功,便于登出请求幂等。 RevokeCLIToken revokes a token; repeated revocation remains successful.
func SetUserToContext ¶
func UpdateProfile ¶
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
CLITokenFromContext 从普通 context 读取已校验的 CLI 令牌。 CLITokenFromContext reads the authenticated CLI token from a plain context.
func FindCLITokenByID ¶ added in v1.2.0
FindCLITokenByID 按编号读取令牌元数据。 FindCLITokenByID loads token metadata by id.
func GetCLITokenFromGin ¶ added in v1.2.0
GetCLITokenFromGin 读取当前 HTTP 请求绑定的 CLI 令牌。 GetCLITokenFromGin returns the CLI token bound to the current HTTP request.
func RevokeCLITokenByID ¶ added in v1.2.0
RevokeCLITokenByID 按编号吊销令牌;重复吊销保持成功。 RevokeCLITokenByID revokes a token by id; repeated revocation remains successful.
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
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 FindByOAuthID ¶
FindByOAuthID 根据 OAuth ID 查找用户
func FindByUsername ¶
FindByUsername 根据用户名查找用户
func GetUserFromContext ¶
GetUserFromContext 从 Gin 上下文获取用户信息
func (*User) CheckPassword ¶
CheckPassword 验证密码是否正确 使用 bcrypt 算法比较密码哈希
func (*User) IsValidBcryptHash ¶
IsValidBcryptHash 检查密码哈希是否为有效的 bcrypt 哈希
func (*User) SetPassword ¶
SetPassword 设置用户密码 使用 bcrypt 算法对密码进行哈希处理 cost 参数指定 bcrypt 的计算成本,如果为 0 则使用默认值
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 ¶
UserInfoResponse 用户信息响应