Security Primer
Security Primer
Section titled “Security Primer”当你已经通过 稳定根 确认改动仍属于默认服务路径,而且问题进一步收窄到服务如何保护自身时,就打开这一页:验证身份、加固 HTTP headers、清洗输入,或防范滥用。
security 拥有 auth identity 基础元语、JWT 助手、security headers、输入安全和防滥用保护基础元语。它被标记为 risk: critical — 此处的每一次改动都可能影响整个攻击面。
claims, err := jwt.Verify(r, secretKey)if err != nil { _ = contract.WriteError(w, r, contract.NewErrorBuilder(). Type(contract.TypeUnauthorized). Message("invalid token"). Build()) return}_ = contract.WriteResponse(w, r, http.StatusOK, map[string]string{"sub": claims.Subject}, nil)什么时候从这里开始
Section titled “什么时候从这里开始”- 你正在实现或验证 JWT token(
security/jwt) - 你正在设置或审计 HTTP security headers(
security/headers) - 你正在清洗用户输入或转义值(
security/input) - 你正在添加速率限制守卫或防滥用检测基础元语(
security/abuse) - 你正在对密码进行哈希或验证(
security/password) - 你正在读取或设置请求上的 auth identity(
security/authn)
什么时候不该从这里开始
Section titled “什么时候不该从这里开始”- 改动关于 session lifecycle、session 撤销或 tenant-session sentinel 错误 — 那属于
x/tenant - 改动添加了断路器或弹性封装 — 那属于
x/resilience - 改动引入了 app bootstrap、服务构造或持久化逻辑
- 工作关于可观测性策略、结构化日志或请求追踪
当前仓库里先读哪些文件
Section titled “当前仓库里先读哪些文件”security/module.yamlsecurity/authn/security/jwt/security/headers/security/input/security/abuse/security/password/
更具体的归属例子
Section titled “更具体的归属例子”这些工作适合留在 security | 一旦变成这些问题就应移出 |
|---|---|
JWT 签发、验证与 claims 提取 — security/jwt | session 撤销、token 刷新编排或 tenant-session lifecycle |
HTTP security headers:Content-Security-Policy、X-Frame-Options、HSTS — security/headers | 观察延迟、关联日志或计数错误的传输 middleware |
输入清洗、HTML 转义或危险字符拒绝 — security/input | 带有领域特定不变量的业务规则验证 |
速率限制基础元语与防滥用信号检测 — security/abuse | 完整弹性编排,如断路器或自适应退避 |
密码哈希与计时安全比较 — security/password | 用户管理、档案存储或身份联合 |
JWT — 签发与验证 token
Section titled “JWT — 签发与验证 token”import ( "github.com/spcent/plumego/security/jwt" kvstore "github.com/spcent/plumego/store/kv")
store, _ := kvstore.NewKVStore(kvstore.Options{DataDir: "/var/lib/myapp/jwt"})
cfg := jwt.DefaultJWTConfig() // HMAC-SHA256,access 15m,refresh 7dmanager, _ := jwt.NewJWTManager(store, cfg)
// 签发 token 对pair, _ := manager.GenerateTokenPair(ctx, jwt.IdentityClaims{Subject: userID}, jwt.AuthorizationClaims{Roles: []string{"user"}},)// pair.AccessToken — 短期有效// pair.RefreshToken — 长期有效
// 验证 tokenclaims, err := manager.VerifyToken(ctx, tokenString, jwt.TokenTypeAccess)完整接入流程见 添加 JWT 认证指南。
authn — 从 context 读取 identity
Section titled “authn — 从 context 读取 identity”import "github.com/spcent/plumego/security/authn"
// 在 handler 中,auth 中间件运行后:principal := authn.PrincipalFromContext(r.Context())if principal == nil { // 未认证 — 中间件应已拦截此请求}userID := principal.Subjectroles := principal.Rolesheaders — 设置安全头
Section titled “headers — 设置安全头”import ( "github.com/spcent/plumego/security/headers" secmw "github.com/spcent/plumego/middleware/security")
policy := headers.DefaultPolicy() // 合理的默认值// 或policy := headers.StrictPolicy() // 更严格的 CSP,适合 SPA
mw, err := secmw.Middleware(secmw.Config{Policy: &policy})if err != nil { return err}app.Use(mw)构建自定义 CSP:
csp := headers.NewCSPBuilder(). DefaultSrc("'self'"). ScriptSrc("'self'", "https://cdn.example.com"). StyleSrc("'self'", "'unsafe-inline'"). Build()
policy.ContentSecurityPolicy = cspinput — 验证与清洗用户数据
Section titled “input — 验证与清洗用户数据”import "github.com/spcent/plumego/security/input"
if !input.ValidateEmail(email) { ... }if !input.ValidateURL(rawURL) { ... }
clean := input.BestEffortSanitizeHTML(userContent) // 去除危险 HTML 标签safe := input.StripControlChars(rawInput) // 去除控制字符password — 哈希与验证密码
Section titled “password — 哈希与验证密码”import "github.com/spcent/plumego/security/password"
hash, _ := password.HashPassword(plaintext)err := password.CheckPassword(hash, plaintext) // 计时安全比较为什么单独写这一页
Section titled “为什么单独写这一页”安全是唯一一个部分正确会导致真实伤害的模块。security 的审查清单与所有其他稳定根不同:fail-closed 是强制要求,计时安全比较是强制要求,密钥绝不能被记录。了解哪个子包负责特定的安全问题,可以防止导致 auth 绕过或 header 注入的意外模糊。
- contract API 快速参考 —
TypeUnauthorized、TypeForbidden、TypeInvalidToken错误类型 - 错误参考 — auth 错误的完整排查步骤
- 添加 JWT 认证指南
- Contract Primer
- Middleware Primer
- 仓库边界