JWT Starter
简介
JWT(JSON Web Token)Starter 为 Hiboot 应用程序提供身份验证和授权功能。它支持令牌生成、验证和中间件集成。
安装
在应用程序中导入 JWT starter:
import "github.com/hidevopsio/hiboot/pkg/starter/jwt"
配置
在 application.yml 中配置 JWT:
app:
profiles:
include:
- jwt
jwt:
# RSA 私钥文件路径
private_key_path: "config/keys/private.pem"
# RSA 公钥文件路径
public_key_path: "config/keys/public.pem"
生成 RSA 密钥
生成用于令牌签名的 RSA 密钥对:
# 生成私钥
openssl genrsa -out config/keys/private.pem 2048
# 从私钥生成公钥
openssl rsa -in config/keys/private.pem -pubout -out config/keys/public.pem
基本用法
生成令牌
注入 jwt.Token 来生成令牌:
package controller
import (
"time"
"github.com/hidevopsio/hiboot/pkg/app"
"github.com/hidevopsio/hiboot/pkg/at"
"github.com/hidevopsio/hiboot/pkg/model"
"github.com/hidevopsio/hiboot/pkg/starter/jwt"
)
type loginController struct {
at.RestController
at.RequestMapping `value:"/auth"`
token jwt.Token
}
type LoginRequest struct {
model.RequestBody
Username string `json:"username" validate:"required"`
Password string `json:"password" validate:"required"`
}
type LoginResponse struct {
Token string `json:"token"`
ExpiresIn int64 `json:"expires_in"`
}
func init() {
app.Register(newLoginController)
}
func newLoginController(token jwt.Token) *loginController {
return &loginController{
token: token,
}
}
// Post 处理 POST /auth/login
func (c *loginController) PostLogin(request *LoginRequest) (model.Response, error) {
// 验证凭据(实现你自己的逻辑)
if request.Username != "admin" || request.Password != "password" {
response := new(model.BaseResponse)
response.SetCode(401)
response.SetMessage("凭据无效")
return response, nil
}
// 生成 JWT 令牌
claims := jwt.Map{
"username": request.Username,
"role": "admin",
}
// 令牌在 30 分钟后过期
tokenString, err := c.token.Generate(claims, 30, time.Minute)
if err != nil {
return nil, err
}
response := new(model.BaseResponse)
response.SetData(&LoginResponse{
Token: tokenString,
ExpiresIn: 1800, // 30 分钟(秒)
})
return response, nil
}
JWT 中间件
使用 JWT 中间件保护路由:
package controller
import (
"github.com/hidevopsio/hiboot/pkg/app"
"github.com/hidevopsio/hiboot/pkg/at"
"github.com/hidevopsio/hiboot/pkg/model"
"github.com/hidevopsio/hiboot/pkg/starter/jwt"
)
type protectedController struct {
at.RestController
at.RequestMapping `value:"/api"`
// 用于路由保护的 JWT 中间件
Middleware *jwt.Middleware `inject:""`
}
func init() {
app.Register(newProtectedController)
}
func newProtectedController() *protectedController {
return &protectedController{}
}
// Before 在每个请求之前调用
// 使用此方法应用 JWT 验证
func (c *protectedController) Before() {
c.Middleware.Serve(c.Ctx)
}
// GetProfile 处理 GET /api/profile
func (c *protectedController) GetProfile() (model.Response, error) {
// 从上下文获取声明
claims := c.Ctx.Values().Get("jwt").(*jwt.Token)
response := new(model.BaseResponse)
response.SetData(map[string]interface{}{
"username": claims.Get("username"),
"role": claims.Get("role"),
})
return response, nil
}
令牌 API
jwt.Token 接口
type Token interface {
// Generate 创建新的 JWT 令牌
Generate(claims Map, expiresAt int64, timeUnit time.Duration) (string, error)
// VerifyKey 返回用于验证的公钥
VerifyKey() interface{}
// SignKey 返回用于签名的私钥
SignKey() interface{}
}
jwt.Map
jwt.Map 是 map[string]interface{} 的别名,用于令牌声明:
claims := jwt.Map{
"user_id": 123,
"username": "john",
"role": "admin",
"permissions": []string{"read", "write"},
}
高级用法
自定义令牌过期时间
// 令牌有效期 24 小时
token, err := c.token.Generate(claims, 24, time.Hour)
// 令牌有效期 7 天
token, err := c.token.Generate(claims, 7*24, time.Hour)
// 令牌有效期 15 分钟
token, err := c.token.Generate(claims, 15, time.Minute)
从令牌提取声明
func (c *protectedController) GetUserInfo() (model.Response, error) {
// 从上下文访问 JWT 声明
jwtValue := c.Ctx.Values().Get("jwt")
if jwtValue == nil {
response := new(model.BaseResponse)
response.SetCode(401)
response.SetMessage("未授权")
return response, nil
}
token := jwtValue.(*jwt.MapClaims)
username := (*token)["username"].(string)
role := (*token)["role"].(string)
response := new(model.BaseResponse)
response.SetData(map[string]interface{}{
"username": username,
"role": role,
})
return response, nil
}
基于角色的访问控制
func (c *adminController) Before() {
c.Middleware.Serve(c.Ctx)
// 检查管理员角色
jwtValue := c.Ctx.Values().Get("jwt")
if jwtValue != nil {
token := jwtValue.(*jwt.MapClaims)
role := (*token)["role"].(string)
if role != "admin" {
c.Ctx.StatusCode(403)
c.Ctx.JSON(map[string]string{
"error": "禁止访问:需要管理员权限",
})
c.Ctx.StopExecution()
}
}
}
发送认证请求
在 Authorization 头中包含 JWT 令牌:
# 登录获取令牌
TOKEN=$(curl -s -X POST http://localhost:8080/auth/login \
-H "Content-Type: application/json" \
-d '{"username":"admin","password":"password"}' | jq -r '.data.token')
# 发送认证请求
curl http://localhost:8080/api/profile \
-H "Authorization: Bearer $TOKEN"
配置参考
| 属性 | 描述 | 默认值 |
|---|---|---|
jwt.private_key_path |
RSA 私钥路径 | - |
jwt.public_key_path |
RSA 公钥路径 | - |
下一步
- 自动配置 - 创建自定义 Starter
- 网络应用 - 构建 REST API
- Actuator Starter - 健康检查和指标