JWT 認証による Go API の保護
Oct 03, 2024 pm 12:07 PMそれでは、少し本題に移りましょう。セキュリティは重要な問題であり、API を構築している場合、誰かが勝手に侵入してデータをいじり始めることはできません。そこで窮地を救うためにJWT (JSON Web Tokens) が登場します。現在、JWT ベースの認証を追加して Go API をレベルアップしています。
簡単な注意事項 ?
古い github.com/dgrijalva/jwt-go パッケージを使用している場合は、アップグレードの時期が来ました。新しい標準は github.com/golang-jwt/jwt/v4 です。
なぜ切り替えたのですか?
- 元の作成者が主導権を引き継ぎ、新しいメンテナは改良とセキュリティ問題の修正に忙しく取り組んでいます。
- バージョン 4.0.0 から、Go モジュールのサポートが追加され、トークン検証が改善されました。
- 古いパッケージをまだ使用している場合は、MIGRATION_GUIDE.md を確認してください。
さあ、素晴らしい新しい JWT ライブラリを始めましょう!
もう一度 JWT とは何ですか? ?
JWT を初めて使用する方へ:
- これは、API にアクセスするための署名済みの許可票のようなものです。
- API はトークンを生成して署名し、クライアント (ユーザー、アプリなど) はそのトークンをすべてのリクエストに含めます。
- サーバーはトークンをチェックし、「はい、あなたは正当です。」
理解できたので、コードを詳しく見ていきましょう!
プロジェクトのセットアップ
前回の投稿で中断したところから続けていきます。 Go モジュールを更新し、必要なパッケージをインストールしましょう:
- JWT パッケージと多重ルーターを追加します。
go get github.com/golang-jwt/jwt/v4 go get github.com/gorilla/mux
- main.go ファイルを開いてコーディングを始めましょう!
ステップ 1: JWT トークンを生成する
まず、ユーザーのログイン時に JWT トークンを生成する関数を作成します。このトークンにはユーザー名が含まれ、秘密鍵を使用して署名されます。
var jwtKey = []byte("my_secret_key") type Credentials struct { Username string `json:"username"` Password string `json:"password"` } type Claims struct { Username string `json:"username"` jwt.RegisteredClaims } func generateToken(username string) (string, error) { expirationTime := time.Now().Add(5 * time.Minute) claims := &Claims{ Username: username, RegisteredClaims: jwt.RegisteredClaims{ ExpiresAt: jwt.NewNumericDate(expirationTime), }, } token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) tokenString, err := token.SignedString(jwtKey) return tokenString, err }
この関数は、HS256 アルゴリズムを使用して署名された、5 分後に期限切れになるトークンを生成します。
ステップ 2: ログインエンドポイントを作成する
次に、ユーザーが認証情報を送信するログイン エンドポイントを構築します。ログイン情報がチェックアウトされたら、JWT を生成し、Cookie で送り返します。
func login(w http.ResponseWriter, r *http.Request) { var creds Credentials err := json.NewDecoder(r.Body).Decode(&creds) if err != nil { w.WriteHeader(http.StatusBadRequest) return } if creds.Username != "admin" || creds.Password != "password" { w.WriteHeader(http.StatusUnauthorized) return } token, err := generateToken(creds.Username) if err != nil { w.WriteHeader(http.StatusInternalServerError) return } http.SetCookie(w, &http.Cookie{ Name: "token", Value: token, Expires: time.Now().Add(5 * time.Minute), }) }
ステップ 3: JWT 検証用のミドルウェア
ここで、保護されたルートへのアクセスを許可する前に JWT トークンを検証するミドルウェア関数が必要です。
func authenticate(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { c, err := r.Cookie("token") if err != nil { if err == http.ErrNoCookie { w.WriteHeader(http.StatusUnauthorized) return } w.WriteHeader(http.StatusBadRequest) return } tokenStr := c.Value claims := &Claims{} tkn, err := jwt.ParseWithClaims(tokenStr, claims, func(token *jwt.Token) (interface{}, error) { return jwtKey, nil }) if err != nil || !tkn.Valid { w.WriteHeader(http.StatusUnauthorized) return } next.ServeHTTP(w, r) }) }
このミドルウェアは、リクエストに有効な JWT トークンがあるかどうかを確認します。そうでない場合は、不正な応答が返されます。
ステップ 4: ルートの保護
次に、認証ミドルウェアを適用して /books ルートを保護しましょう:
func main() { r := mux.NewRouter() r.HandleFunc("/login", login).Methods("POST") r.Handle("/books", authenticate(http.HandlerFunc(getBooks))).Methods("GET") fmt.Println("Server started on port :8000") log.Fatal(http.ListenAndServe(":8000", r)) }
API のテスト
- ログインしてトークンを生成します:
curl -X POST http://localhost:8000/login -d '{"username":"admin", "password":"password"}' -H "Content-Type: application/json"
- 保護された /books エンドポイントにアクセスします:
curl --cookie "token=<your_token>" http://localhost:8000/books
トークンが有効であれば、アクセスできます。そうでない場合は、「401 Unauthorized」が表示されます。
次は何ですか?
次回は、API をデータベースに接続して、ユーザーの資格情報を管理し、データを保存します。続報をお楽しみに!
以上がJWT 認証による Go API の保護の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

人気の記事

人気の記事

ホットな記事タグ

メモ帳++7.3.1
使いやすく無料のコードエディター

SublimeText3 中国語版
中国語版、とても使いやすい

ゼンドスタジオ 13.0.1
強力な PHP 統合開発環境

ドリームウィーバー CS6
ビジュアル Web 開発ツール

SublimeText3 Mac版
神レベルのコード編集ソフト(SublimeText3)

ホットトピック











Go Language Packのインポート:アンダースコアとアンダースコアなしの違いは何ですか?

GOでテスト用のモックオブジェクトとスタブを書くにはどうすればよいですか?

GOのジェネリックのカスタムタイプ制約を定義するにはどうすればよいですか?

トレースツールを使用して、GOアプリケーションの実行フローを理解するにはどうすればよいですか?

Linterと静的分析ツールを使用して、GOコードの品質と保守性を向上させるにはどうすればよいですか?

MySQLクエリ結果リストをGO言語のカスタム構造スライスに変換する方法は?
