それでは、少し本題に移りましょう。セキュリティは重要な問題であり、API を構築している場合、誰かが勝手に侵入してデータをいじり始めることはできません。そこで窮地を救うためにJWT (JSON Web Tokens) が登場します。現在、JWT ベースの認証を追加して Go API をレベルアップしています。
古い github.com/dgrijalva/jwt-go パッケージを使用している場合は、アップグレードの時期が来ました。新しい標準は github.com/golang-jwt/jwt/v4 です。
なぜ切り替えたのですか?
さあ、素晴らしい新しい JWT ライブラリを始めましょう!
JWT を初めて使用する方へ:
理解できたので、コードを詳しく見ていきましょう!
前回の投稿で中断したところから続けていきます。 Go モジュールを更新し、必要なパッケージをインストールしましょう:
go get github.com/golang-jwt/jwt/v4 go get github.com/gorilla/mux
まず、ユーザーのログイン時に 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 分後に期限切れになるトークンを生成します。
次に、ユーザーが認証情報を送信するログイン エンドポイントを構築します。ログイン情報がチェックアウトされたら、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), }) }
ここで、保護されたルートへのアクセスを許可する前に 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 トークンがあるかどうかを確認します。そうでない場合は、不正な応答が返されます。
次に、認証ミドルウェアを適用して /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)) }
curl -X POST http://localhost:8000/login -d '{"username":"admin", "password":"password"}' -H "Content-Type: application/json"
curl --cookie "token=<your_token>" http://localhost:8000/books
トークンが有効であれば、アクセスできます。そうでない場合は、「401 Unauthorized」が表示されます。
次回は、API をデータベースに接続して、ユーザーの資格情報を管理し、データを保存します。続報をお楽しみに!
以上がJWT 認証による Go API の保護の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。