ホームページ >バックエンド開発 >Golang >Go API での JWT 認証の実装

Go API での JWT 認証の実装

Susan Sarandon
Susan Sarandonオリジナル
2024-12-27 20:56:14497ブラウズ

Implementing JWT Authentication in Go API

JWT (JSON Web Token) は、トークンベースの認証を通じて API を保護するための非常に効果的な方法であり、認証されたユーザーのみが API エンドポイントにアクセスできるようにします。従来のセッションベースのアプローチとは異なり、JWT はステートレスであり、サーバー側のセッション ストレージの必要がないため、スケーラブルでパフォーマンスの高いアプリケーションに最適です。このガイドでは、ユーザーのログイン時のトークンの生成から、これらのトークンを検証してエンドポイントを保護し、最終的にアプリケーションのデータとリソースのセキュリティと堅牢性を強化するまで、Go API での JWT 認証の実装について説明します。

前提条件

  • Go 1.21

プロジェクトのセットアップ

go mod init app
go get github.com/gin-gonic/gin@v1.5.0
go get github.com/golang-jwt/jwt
go get github.com/joho/godotenv 

プロジェクトの構造

├─ .env
├─ main.go
├─ middleware
│  └─ authenticate.go
└─ public
   ├─ index.html
   └─ login.html

プロジェクトファイル

.env

jwt_secret = b0WciedNJvFCqFRbB2A1QhZoCDnutAOen5g1FEDO0HsLTwGINp04GXh2OXVpTqQL

この .env ファイルには、アプリケーション内の JWT トークンの署名と検証に使用される秘密鍵を保持する単一の環境変数 jwt_secret が含まれています。

認証する.go

package middleware

import (
    "net/http"
    "os"
    "strings"

    "github.com/gin-gonic/gin"
    "github.com/golang-jwt/jwt"
)

type Claims struct {
    Id int `json:"id"`
    Name string `json:"name"`
    jwt.StandardClaims
}

func Authenticate() gin.HandlerFunc {
    return func(c *gin.Context) {
        if c.Request.URL.Path == "/" || c.Request.URL.Path == "/login" {
            c.Next()
            return
        }
        authHeader := c.GetHeader("Authorization")
        if authHeader == "" {
            c.Status(http.StatusUnauthorized)
            c.Abort()
            return
        }
        tokenString := strings.TrimPrefix(authHeader, "Bearer ")
        token, err := jwt.ParseWithClaims(tokenString, &Claims{}, func(token *jwt.Token) (interface{}, error) {
            return []byte(os.Getenv("jwt_secret")), nil
        })
        if err != nil || !token.Valid {
            c.Status(http.StatusUnauthorized)
            c.Abort()
            return
        }
        if claims, ok := token.Claims.(*Claims); ok {
            c.Set("user", claims)
        } else {
            c.Status(http.StatusUnauthorized)
            c.Abort()
            return
        }
        c.Next()
    }
}

authenticate.go ミドルウェアは、Gin フレームワークを使用して Go API で JWT 認証の関数を定義します。リクエストが / または /login パスに対するものであるかどうかをチェックします。その場合、認証は必要ありません。他のルートの場合は、Bearer トークンを期待して Authorization ヘッダーを取得します。トークンは、jwt パッケージと環境変数の秘密キーを使用して解析および検証されます。トークンが無効または欠落している場合、リクエストは 401 Unauthorized ステータスで中止されます。有効な場合、ユーザー クレーム (ID や名前など) が抽出され、Gin コンテキストに追加され、保護されたルートへのアクセスが許可されます。

メイン.ゴー

package main

import (
    "app/middleware"
    "net/http"
    "os"
    "time"

    "github.com/gin-gonic/gin"
    "github.com/golang-jwt/jwt"
    "github.com/joho/godotenv"
)

func main() {
    godotenv.Load()
    router := gin.Default()
    router.Use(middleware.Authenticate())
    router.LoadHTMLFiles("public/index.html", "public/login.html")

    router.GET("/", func(c *gin.Context) {
        c.HTML(http.StatusOK, "index.html", nil)
    })

    router.GET("/login", func(c *gin.Context) {
        c.HTML(http.StatusOK, "login.html", nil)
    })

    router.GET("/user", func(c *gin.Context) {
        user, _ := c.Get("user")
        claims := user.(*middleware.Claims)
        c.JSON(http.StatusOK, gin.H{"name": claims.Name})
    })

    router.POST("/login", func(c *gin.Context) {
        var login map[string]string
        c.BindJSON(&login)
        if login["name"] == "admin" && login["password"] == "1234" {
            token := jwt.NewWithClaims(jwt.SigningMethodHS256, &middleware.Claims{
                Id: 1,
                Name: login["name"],
                StandardClaims: jwt.StandardClaims{
                    IssuedAt: time.Now().Unix(),
                    ExpiresAt: time.Now().Add(24 * time.Hour).Unix(),
                },
            })
            tokenString, _ := token.SignedString([]byte(os.Getenv("jwt_secret")))
            c.JSON(http.StatusOK, gin.H{"token": tokenString})
        } else {
            c.Status(http.StatusBadRequest)
        }
    })
    router.Run()
}

main.go ファイルは、JWT ベースの認証でルートを処理するために、Gin フレームワークを使用して Go Web サーバーをセットアップします。認証にはミドルウェアを使用し、リクエスト内の有効な JWT トークンをチェックします。サーバーは、index.html と login.html という 2 つの HTML ページを提供し、/ および /login ルート経由でアクセスできます。

/user ルートの場合、サーバーは認証されたユーザーの名前を JWT クレームから取得し、応答でそれを返します。 /login POST ルートの場合、サーバーはユーザーの資格情報 (名前とパスワード) を検証し、有効な場合は JWT トークンを生成し、秘密キーで署名してクライアントに送り返します。サーバーはリクエストをリッスンし、デフォルトのポートで実行するように構成されています。

インデックス.html

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <link href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.3/css/bootstrap.min.css" rel="stylesheet">
    <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.0/css/all.min.css" rel="stylesheet">
</head>
<body>
    <div>



<p>The index.html is a simple web page that provides a user interface for displaying the login status of a user. It uses Bootstrap for styling and Font Awesome for icons. On page load, it checks the user's authentication status by sending a request to the server with a JWT token stored in localStorage. If the user is logged in, it shows a success message with the user's name and a logout button. If not logged in, it shows a message indicating the user is not logged in and redirects them to the login page after a few seconds.</p>

<h3>
  
  
  login.html
</h3>



<pre class="brush:php;toolbar:false"><!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <link href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.3/css/bootstrap.min.css" rel="stylesheet">
    <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.0/css/all.min.css" rel="stylesheet">
</head>
<body>
    <div>



<p>The login.html page provides a simple login form where users can input their username and password. It uses Bootstrap for styling and Font Awesome for icons. When the user submits the form, a JavaScript function login() sends a POST request to the /login endpoint with the entered credentials. If the login is successful, the server returns a JWT token, which is stored in localStorage. The page then redirects the user to the home page (/). If the login fails, an error message is displayed.</p>

<h2>
  
  
  Run project
</h2>



<pre class="brush:php;toolbar:false">go run main.go

Web ブラウザを開いて http://localhost:8080 に移動します

このテスト ページが表示されます。

Implementing JWT Authentication in Go API

テスト

数秒後に、ログイン ページにリダイレクトされます。

Implementing JWT Authentication in Go API

ログイン ボタンを押すと、ホームページにログインし、ログインしているユーザーの名前が表示されます。

Implementing JWT Authentication in Go API

ブラウザを更新してみると、まだログインしていることがわかります。次に、ログアウト ボタンを押すと、JWT トークンが削除され、再びログイン ページにリダイレクトされます。

Implementing JWT Authentication in Go API

結論

結論として、Go API に JWT 認証を実装すると、ユーザー認証を処理するための安全でスケーラブルなアプローチが提供されます。 gin フレームワークを golang-jwt/jwt パッケージとともに使用することで、トークンベースの認証をアプリケーションに簡単に統合できます。 JWT トークンはログイン中に生成され、ユーザーの資格情報を安全に検証し、保護されたルートへのアクセスを許可します。ミドルウェアは、トークンの有効性を検証することで、認証されたユーザーのみがこれらのルートにアクセスできるようにします。このステートレス認証メカニズムは、パフォーマンスと柔軟性の強化を提供するため、最新の API アーキテクチャにとって理想的な選択肢となります。

ソースコード: https://github.com/stackpuz/Example-JWT-Go

数分で CRUD Web アプリを作成: https://stackpuz.com

以上がGo API での JWT 認証の実装の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。