认证鉴权

认证用于确认“你是谁”,鉴权用于判断“你能做什么”。golang-jwt/jwt 负责签发和验证 JWT,Casbin 负责根据策略判断访问权限,两者解决的问题不同。

go get github.com/golang-jwt/jwt/v5
go get github.com/casbin/casbin/v3

JWT 身份认证

签发 Token 时使用标准 Claims,并设置明确的过期时间、签发者和受众:

type Claims struct {
    UserID string `json:"user_id"`
    jwt.RegisteredClaims
}

claims := Claims{
    UserID: "user-1",
    RegisteredClaims: jwt.RegisteredClaims{
        Issuer:    "api.example.com",
        Audience:  jwt.ClaimStrings{"web.example.com"},
        Subject:   "user-1",
        ExpiresAt: jwt.NewNumericDate(time.Now().Add(15 * time.Minute)),
        IssuedAt:  jwt.NewNumericDate(time.Now()),
    },
}

token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
tokenString, err := token.SignedString(secret)

解析时应限制允许的签名算法,并校验签发者和受众:

token, err := jwt.ParseWithClaims(tokenString, &Claims{}, func(token *jwt.Token) (any, error) {
    return secret, nil
},
    jwt.WithValidMethods([]string{jwt.SigningMethodHS256.Alg()}),
    jwt.WithIssuer("api.example.com"),
    jwt.WithAudience("web.example.com"),
)
if err != nil || !token.Valid {
    return errors.New("invalid token")
}

claims, ok := token.Claims.(*Claims)

生产环境应从密钥管理系统读取密钥,不要硬编码。短期 Access Token 通常搭配可撤销的 Refresh Token;JWT 的 Payload 只是编码,不应存放密码或其他敏感信息。

Casbin 权限控制

Casbin 将访问模型和权限策略分开。下面使用 RBAC 模型与策略文件创建 Enforcer:

enforcer, err := casbin.NewEnforcer("model.conf", "policy.csv")
if err != nil {
    return err
}

allowed, err := enforcer.Enforce("alice", "/orders", "read")
if err != nil {
    return err
}
if !allowed {
    return errors.New("permission denied")
}

model.conf 定义请求、策略、角色和匹配规则:

[request_definition]
r = sub, obj, act

[policy_definition]
p = sub, obj, act

[role_definition]
g = _, _

[policy_effect]
e = some(where (p.eft == allow))

[matchers]
m = g(r.sub, p.sub) && r.obj == p.obj && r.act == p.act

policy.csv 保存角色权限和用户角色关系:

p, admin, /orders, read
p, admin, /orders, write
g, alice, admin

生产项目通常通过 Adapter 把策略保存到数据库,并在策略变化时同步多个服务实例。鉴权应默认拒绝访问,不能因为 Casbin 执行出错而放行请求。

组合流程

  1. 从请求头读取 Bearer Token,并使用 JWT 验证身份。
  2. 从 Claims 中取得用户 ID,不能直接信任客户端提交的身份。
  3. 将用户、资源和操作传给 Casbin 执行鉴权。
  4. 只有认证和鉴权都成功后,才调用业务逻辑。