GinでJWT認証入門
Gin初心者のための認証ミドルウェア入門
Ginは軽量で高速なWebフレームワークですが、認証機能を自前で実装するのは手間がかかります。そこで、認証ミドルウェアを活用すると、リクエストの前にユーザー情報を検証し、認可ロジックを統一的に管理できます。まずは、Ginのミドルウェア構造を理解し、認証フローを設計しましょう。
認証ミドルウェアは、c.Next()で次のハンドラへ処理を渡す前に、ヘッダーやクッキーからトークンを取得し、検証します。検証に失敗した場合は、c.AbortWithStatusJSON()で401を返却し、以降のハンドラを実行しません。
BasicAuthで簡単に始めるトークン認証
BasicAuthはHTTPヘッダーにAuthorization: Basic base64(username:password)を付与するだけで認証が可能です。Ginではgin.BasicAuth()を使えば、簡単にミドルウェアを作成できます。
func main() {
r := gin.Default()
authorized := r.Group("/", gin.BasicAuth(gin.Accounts{
"admin": "admin123",
"user": "user123",
}))
authorized.GET("/dashboard", func(c *gin.Context) {
c.JSON(200, gin.H{"message": "Welcome!"})
})
r.Run()
}
BasicAuthは開発環境や内部ツールでの簡易認証に適していますが、パスワードを平文で送信するため、HTTPSを必ず併用してください。トークン認証に移行する場合は、JWTやOAuth2を検討しましょう。
JWTを使ったスケーラブルな認可設計
JWT(JSON Web Token)は、サーバー側で状態を保持せずにユーザー情報を安全に転送できるトークンです。発行側は秘密鍵で署名し、受信側は公開鍵で検証します。GinでJWTを扱うには、github.com/dgrijalva/jwt-goやgithub.com/golang-jwt/jwt/v4などのライブラリが便利です。
func JWTAuthMiddleware() gin.HandlerFunc {
return func(c *gin.Context) {
tokenStr := c.GetHeader("Authorization")
if tokenStr == "" {
c.AbortWithStatusJSON(401, gin.H{"error": "token required"})
return
}
token, err := jwt.Parse(tokenStr, func(token *jwt.Token) (interface{}, error) {
return []byte("secret"), nil
})
if err != nil || !token.Valid {
c.AbortWithStatusJSON(401, gin.H{"error": "invalid token"})
return
}
c.Set("user", token.Claims.(jwt.MapClaims)["sub"])
c.Next()
}
}
JWTを使うことで、マイクロサービス間で認可情報を共有しやすくなります。トークンにロールや権限情報を埋め込むことで、アクセス制御を柔軟に実装できます。
アクセス制御とセキュリティのベストプラクティス
認可(Authorization)は、認証(Authentication)に続く重要なステップです。ユーザーが持つ権限に応じてリソースへのアクセスを制限することで、システム全体のセキュリティを確保します。以下に代表的なベストプラクティスをまとめます。
- ロールベースアクセス制御(RBAC)を導入し、権限をロール単位で管理する。
- 最小権限の原則を徹底し、必要最低限の権限のみ付与する。
- トークンの有効期限を短く設定し、リフレッシュトークンで継続的な認証を行う。
- HTTPSを必須にし、通信の盗聴や改ざんを防止する。
- CORSポリシーを適切に設定し、外部ドメインからの不正アクセスを制限する。
また、ログ監視や異常検知を組み合わせることで、侵入や不正利用を早期に検知できます。セキュリティは設計段階から組み込むことが重要です。
コメント
コメントを投稿