Easy JWT implementation by Casbin library
Posted on Wed 07 May 2025 in Journal
Abstract | IAM related protocols |
---|---|
Authors | Walter Fan |
Category | learning note |
Status | v1.0 |
Updated | 2025-05-07 |
License | CC-BY-NC-ND 4.0 |
Implement JWT authentication by Casbin in Go
使用 Go 编写一个简单的 HTTP 服务器,并通过 JWT(JSON Web Token)进行身份验证。此外,我们还将使用 Casbin 进行基于角色的访问控制(RBAC),以实现细粒度的权限管理。
源码地址:https://github.com/walterfan/kata-go/tree/master/kata/auth
初始化项目
首先,初始化 Go 模块并安装所需的依赖:
go mod init github.com/walterfan/kata-auth
go get github.com/gin-gonic/gin
go get github.com/golang-jwt/jwt/v5
go get github.com/casbin/casbin/v2
启动服务器
运行以下命令启动服务:
go run main.go
默认情况下,服务将在 http://localhost:8080
上运行。
测试接口
获取 JWT Token
发送 POST 请求获取 JWT Token:
export TOKEN=$(curl -s -X POST http://localhost:8080/token \
-H "Content-Type: application/json" \
-d '{"username":"test","password":"pass"}' | jq -r '.token')
echo $TOKEN
访问受保护的资源
- 成功访问
/admin
接口(返回 200):
curl -v -H "Authorization: Bearer $TOKEN" http://localhost:8080/admin
- 被拒绝访问
/user
接口(返回 403):
curl -v -H "Authorization: Bearer $TOKEN" http://localhost:8080/user
实现原理
JWT 认证中间件
我们使用 github.com/golang-jwt/jwt/v5
库来解析和验证 JWT Token。以下是 JWT 中间件的核心实现:
func JWTAuth() gin.HandlerFunc {
return func(c *gin.Context) {
authHeader := c.GetHeader("Authorization")
if authHeader == "" {
c.JSON(http.StatusUnauthorized, gin.H{"error": "Missing token"})
c.Abort()
return
}
parts := strings.Split(authHeader, "Bearer ")
if len(parts) != 2 {
c.JSON(http.StatusUnauthorized, gin.H{"error": "Invalid token format"})
c.Abort()
return
}
tokenStr := parts[1]
token, err := jwt.Parse(tokenStr, func(token *jwt.Token) (interface{}, error) {
return []byte(jwtSecret), nil
})
if err != nil || !token.Valid {
c.JSON(http.StatusUnauthorized, gin.H{"error": "Invalid token"})
c.Abort()
return
}
claims, ok := token.Claims.(jwt.MapClaims)
if !ok {
c.JSON(http.StatusUnauthorized, gin.H{"error": "Invalid claims"})
c.Abort()
return
}
c.Set("userID", claims["user_id"])
c.Set("role", claims["role"])
c.Next()
}
}
该中间件会拦截所有请求,检查请求头中的 Authorization
字段是否包含有效的 JWT Token。如果 Token 有效,则从中提取用户 ID 和角色信息,供后续处理逻辑使用。
基于 Casbin 的 RBAC 权限控制
Casbin 是一个强大的开源访问控制库,支持多种编程语言(如 Go、Java、Python 等)。它提供了灵活的权限管理功能,可以实现常见的访问控制模型,例如:
- ACL(Access Control List):基于资源和用户的直接授权。
- RBAC(Role-Based Access Control):通过角色来分配权限。
- ABAC(Attribute-Based Access Control):基于属性的动态访问控制。
配置文件说明
Casbin 使用 .conf 文件定义访问控制模型,策略则存储在 .csv
文件中。
model.conf
[request_definition]
r = sub, obj, act
[policy_definition]
p = sub, obj, act
[policy_effect]
e = some(where (p.eft == allow))
[matchers]
m = r.sub == p.sub && r.obj == p.obj && r.act == p.act
request_definition
定义了访问请求的结构:sub
(主体):通常是用户或角色。obj
(对象):被访问的资源(如/admin
,/user
)。-
act
(操作):对资源执行的操作(如GET
,POST
)。 -
policy_definition
定义了权限规则的结构: sub
:有权执行操作的主体(用户或角色)。obj
:可访问的资源。-
act
:允许的操作。 -
policy_effect
定义了策略的效果: -
只要有一条策略允许该请求(即
p.eft == allow
),整个请求就视为允许。 -
matchers
定义了如何将请求与策略进行匹配: - 只有当请求中的
sub
,obj
,act
都与某条策略完全匹配时,才认为该策略适用于当前请求。
policy.csv
p, admin, /admin, GET
p, user, /user, GET
表示:
admin
角色可以访问/admin
接口的GET
请求。user
角色可以访问/user
接口的GET
请求。
如需进一步扩展功能,可以考虑以下方向:
- 支持刷新 Token;
- 添加数据库支持,用于持久化用户信息和权限配置;
- 支持多租户架构;
- 集成 OpenID Connect 或 OAuth 2.0 协议进行联合认证。
参考资料
IAM(Identity and Access Management)相关协议
IAM related protocols
Protocol | Purpose | Abstract Summary | Spec/RFC |
---|---|---|---|
LDAP (Lightweight Directory Access Protocol) | Centralized directory-based authentication and user lookup | A protocol to query and modify identity info stored in a directory (like Active Directory). Common in enterprise systems. | RFC 4510 |
Kerberos | Network authentication using tickets | A time-based ticketing system where users authenticate once and receive time-limited tickets for accessing resources securely. | RFC 4120 |
RADIUS (Remote Authentication Dial-In User Service) | Centralized authentication for network access | Used for authenticating users to network devices (e.g., VPNs, Wi-Fi). Provides authentication, authorization, and accounting (AAA). | RFC 2865, RFC 2866 |
TACACS+ | Cisco-focused AAA protocol | Similar to RADIUS, but separates the AAA components more clearly and encrypts the entire payload. | No official RFC (Cisco proprietary); Cisco TACACS+ Documentation |
SAML 2.0 (Security Assertion Markup Language) | Federated SSO for enterprise applications | XML-based protocol used for browser-based SSO, mainly between identity providers (IdPs) and service providers (SPs). | OASIS SAML 2.0 Specification |
OAuth 2.0 | Authorization delegation (not authentication) | A token-based authorization protocol allowing third-party apps to access user data without seeing the user’s credentials. | RFC 6749 |
OpenID Connect (OIDC) | Identity layer on top of OAuth 2.0 for SSO and identity federation | Adds login and user info features to OAuth 2.0 using JSON Web Tokens (JWT). Ideal for modern web/mobile SSO. | OpenID Connect Core 1.0 |
SCIM (System for Cross-domain Identity Management) | Automating user provisioning/deprovisioning | Standard for managing user identities between systems (e.g., auto-creating accounts when users join an org). | RFC 7641, RFC 7642, RFC 7643, RFC 7644 |
JWT (JSON Web Token) | Compact, self-contained format for identity/auth info | Often used with OAuth/OIDC to carry identity claims. Not a protocol itself, but a building block for them. | RFC 7519 |
WS-Federation | SSO and identity federation (Microsoft-centric) | XML-based protocol used in Microsoft environments to federate identity between systems. Precursor to OIDC in some orgs. | WS-Federation Specification |
SPIFFE (Secure Production Identity Framework for Everyone) | Provides standardized identities for services in dynamic, distributed environments | SPIFFE defines a way to issue cryptographically verifiable identities (SPIFFE IDs) to workloads without requiring secrets like passwords or API keys. It enables zero-trust, mutual TLS (mTLS), and secure service-to-service communication. | SPIFFE ID Specification |
SPIRE (SPIFFE Runtime Environment) | A reference implementation of SPIFFE | SPIRE issues, rotates, and manages SPIFFE identities on a running system. It provides workload attestation, certificate issuance, and integrates with K8s, VMs, and cloud providers. Think of SPIRE as the "engine" that brings SPIFFE to life. | SPIRE Documentation |
x509-SVID (SPIFFE Verifiable Identity Document) | Standard format for SPIFFE identity | An X.509 certificate format used in SPIFFE to represent a workload’s identity. Contains the SPIFFE ID in a SAN (Subject Alternative Name) field. | x509-SVID Specification |
JWT-SVID | Token format for SPIFFE identity | A JWT-based alternative to x509-SVID, useful when TLS is not feasible. Enables secure identity propagation between services. | JWT-SVID Specification |