LoginSignup
1
1

[Golang]JWTを実装してみる

Posted at

必要なライブラリ

go get github.com/dgrijalva/jwt-go

色々な動作確認

package main

import (
	"fmt"
	"time"

	"github.com/dgrijalva/jwt-go"
)

func CreateToken(secretKey string) (string, error) {
	claims := jwt.MapClaims{}
	claims["authorized"] = true
	claims["user_id"] = "sample"
	claims["exp"] = time.Now().Add(time.Second * 2).Unix() // 有効期限を1時間に設定

	token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
	return token.SignedString([]byte(secretKey))
}

func ValidateToken(tokenString string, secretKey string) (*jwt.Token, error) {
	token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
		if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
			return nil, fmt.Errorf("予期しない署名方法: %v", token.Header["alg"])
		}
		return []byte(secretKey), nil
	})

	if err != nil {
		return nil, err
	}

	return token, nil
}

func IsAuthorized(token *jwt.Token) bool {
	if _, ok := token.Claims.(jwt.MapClaims); ok && token.Valid {
		return true
	}
	return false
}

// falseの場合は期限が切れていない
func IsExpired(token *jwt.Token) bool {
	// トークンのクレームをMapClaimsとして取得し、トークンが有効であるか確認
	if claims, ok := token.Claims.(jwt.MapClaims); ok && token.Valid {
		// `exp`クレームをUnixタイムスタンプとして取得
		if exp, ok := claims["exp"].(float64); ok {
			// 現在時刻と比較し、有効期限が切れているか確認
			return int64(exp) < time.Now().Unix()
		}
	}
	// 有効期限の情報がない場合は、期限切れとみなす
	return true
}

func GetUserID(token *jwt.Token) string {
	if claims, ok := token.Claims.(jwt.MapClaims); ok && token.Valid {
		return claims["user_id"].(string)
	}
	return ""
}

func main() {

	secretKey := "abcdesfghijklmnopqrstuvwxyz"
	wrongKey := "abcdesfghijklmnopqrstuvwxy"
	tokenString, err := CreateToken(secretKey)
	if err != nil {
		fmt.Println(err)
	}
	fmt.Println(tokenString)

	token, err := ValidateToken(tokenString, secretKey)
	if err != nil {
		fmt.Println(err)
	}
	fmt.Println(token)

	// secretKeyが違う場合
	wrongToken, err := ValidateToken(tokenString, wrongKey)
	if err != nil {
		fmt.Println(err)
	}
	fmt.Println(wrongToken)

	isAuthorized := IsAuthorized(token)
	fmt.Println(isAuthorized)

	// 本当はこの処理は不要
	isExpired := IsExpired(token)
	fmt.Println(isExpired)

	// wait 2 seconds
	time.Sleep(5 * time.Second)

	wrongToken2, err := ValidateToken(tokenString, secretKey)
	if err != nil {
		fmt.Println("有効期限切れ")
		fmt.Println(err)
	}
	fmt.Println(wrongToken2)

	isExpired = IsExpired(token)
	fmt.Println(isExpired)

	userID := GetUserID(token)
	fmt.Println(userID)

}

GolangでJWTをPythonで認証できるかやってみる

JWTの有効期限を1時間に変更する

func CreateToken(secretKey string) (string, error) {
	claims := jwt.MapClaims{}
	claims["authorized"] = true
	claims["user_id"] = "sample"
	claims["exp"] = time.Now().Add(time.Hour * 1).Unix() // 有効期限を1時間に設定

	token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
	return token.SignedString([]byte(secretKey))
}

HS256アルゴリズムを使用してJWTトークンを生成しているためPythonのように言語が違ってもトークンとシークレットキーがあればトークンをデコードできます。

import jwt

# トークンをデコードする関数
def decode_token(token, secret_key):
    try:
        # トークンをデコード
        decoded = jwt.decode(token, secret_key, algorithms=["HS256"])
        return decoded
    except jwt.ExpiredSignatureError:
        # トークンの有効期限切れ
        return "Expired token."
    except jwt.InvalidTokenError:
        # トークンが無効
        return "Invalid token."

# トークンと秘密鍵
token = ""  # ここにGo言語のコードで生成されたトークンを入れる
secret_key = "abcdesfghijklmnopqrstuvwxyz"  # ここに秘密鍵を入れる

# トークンをデコード
decoded_token = decode_token(token, secret_key)
print(decoded_token)


1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1