电话咨询

This commit is contained in:
duoaohui
2026-06-04 14:32:52 +08:00
parent edda31e8bf
commit b89b930c41
4 changed files with 134 additions and 20 deletions

View File

@@ -81,13 +81,30 @@ func (s *TokenStore) SaveTokens(ctx context.Context, userID int64, clientType, a
// ValidateAccessToken 校验 Access Token 是否与 Redis 中存储的一致
// clientType 用于定位正确的 Redis key前台 vs 管理端)
// username 用于识别云律临时会议账号,对其放宽「单点登录挤号」校验
// username 用于识别云律临时会议账号,对其放宽有状态校验
//
// 云律临时会议账号(cloudlaw_*)说明:按手机号即时创建、默认口令、仅用于视频/语音会议、角色受限,
// 在「双方进会 / SSO 多跳 / 多端 / 重进会议」时会被重复签发,单点登录语义会把先签发的 token 挤掉;
// 叠加 Redis key 过期/内存淘汰/重启、登出清理、并发等情况Redis 侧可能出现「不一致 / 缺失 / 查询失败」。
// 由于调用方(中间件/WS 握手)在调用本方法前已用 ParseToken 校验过 JWT 的签名与有效期,
// 对这类临时账号只要 JWT 有效即放行(不强依赖 Redis 有状态记录),避免 web-view 进会偶发「认证已失效」。
// 普通账号(前台用户/管理端)仍维持严格的有状态校验。
func (s *TokenStore) ValidateAccessToken(ctx context.Context, userID int64, clientType, token, username string) bool {
funcName := "service.token_store.ValidateAccessToken"
cloudLaw := isCloudLawUsername(username)
key := fmt.Sprintf("%s%s:%d", keyPrefixAccessToken, clientType, userID)
stored, err := s.redis.Get(ctx, key).Result()
if err == redis.Nil {
// 云律临时账号Redis 无记录(挤号后过期 / 内存淘汰 / 重启 / 登出清理)也凭有效 JWT 放行
if cloudLaw {
logs.Debug(ctx, funcName, "云律临时账号 Redis 无 token 记录,按宽松策略放行(仅凭有效 JWT",
zap.Int64("user_id", userID),
zap.String("client_type", clientType),
)
return true
}
logs.Debug(ctx, funcName, "Token 不存在(已登出或过期)",
zap.Int64("user_id", userID),
zap.String("client_type", clientType),
@@ -95,6 +112,15 @@ func (s *TokenStore) ValidateAccessToken(ctx context.Context, userID int64, clie
return false
}
if err != nil {
// 云律临时账号Redis 抖动/不可用时凭有效 JWT 放行,避免阻断进会
if cloudLaw {
logs.Warn(ctx, funcName, "Redis 查询 token 失败,云律临时账号按宽松策略放行(仅凭有效 JWT",
zap.Int64("user_id", userID),
zap.String("client_type", clientType),
zap.Error(err),
)
return true
}
logs.Error(ctx, funcName, "Redis 查询 Token 失败",
zap.Int64("user_id", userID),
zap.String("client_type", clientType),
@@ -107,11 +133,8 @@ func (s *TokenStore) ValidateAccessToken(ctx context.Context, userID int64, clie
return true
}
// 云律临时会议账号:同一手机号在「双方进会 / SSO 多跳 / 多端」场景会被重复签发会话,
// 单点登录会把先签发的 token 挤掉,导致 web-view 进会报「认证已失效」。
// 这里只要该账号在 Redis 中仍存在有效会话stored 非空,未登出/未过期),
// 且 token 已通过 JWT 签名与有效期校验(调用方 ParseToken 已保证),即放行。
if stored != "" && isCloudLawUsername(username) {
// 云律临时会议账号:token 已被新会话挤号stored != token也放行
if cloudLaw {
logs.Debug(ctx, funcName, "云律临时账号 token 已被新会话覆盖,按宽松策略放行",
zap.Int64("user_id", userID),
zap.String("client_type", clientType),