8
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Go言語】Ginでログイン認証を実装する

Posted at

はじめに

今回は、Go言語のWebフレームワーク「Gin」を用いてログイン認証を実装していこうと思います。
本記事では、エンドポイントの構築、JWT(JSON Web Token)による認証、MySQLデータベースとの連携方法について詳しく説明します。
まずは基本的なセットアップから始め、順を追って実装していきましょう!

環境

・MacBook Air M1

使用技術

  • VScode
  • Go
    • バージョンは1.23.2を使用
  • Gin
    • Go言語のWebフレームワーク
  • MySQL
    • 認証情報を MySQL データベースに保存しようと思います
    • mysqlコマンドが使える状態にしておいてください
  • Docker
    • Dockerを使ってMySQLを用意します
    • dockerコマンドが使える状態にしておいてください
  • Postman
    • エンドポイントの検証に使用します

手順

始める前に、作成するAPIについて簡単に触れておきます。
1. 「サインアップ」エンドポイント

  • /api/register
    • ユーザー登録のパス
    • JWTを不要にし公開したままにする

2. 「ログイン」エンドポイント

  • /api/login
    • ログインに利用するパス
    • 「ユーザー名」と「パスワード」を受け取り、JWT を生成して返却

3. 「ログイン後にしか呼び出しできない」エンドポイント

  • /api/admin/user
    • JWT が必須

この3つのエンドポイントを作成していきます。

それでは始めてきましょう!

セットアップ

terminal
# 作業用のディレクトリを作成(go-authで進めていきます)
$ mkdir go-auth

# 作成したディレクトリに移動後、VScodeを起動
$ cd go-auth
$ code .

まずはGoモジュールの初期化を行うために、以下のコマンドを叩いてください。

# 作成するモジュール名は「go-auth」でいきます
$ go mod init go-auth

次に必要なモジュールのインストールを行います。

terminal
# Gin フレームワーク
$ go get -u github.com/gin-gonic/gin

# ORM ライブラリ
$ go get -u gorm.io/gorm

# JWT の認証と生成に使用するパッケージ
$ go get -u github.com/dgrijalva/jwt-go

# .env ファイルから環境変数を読み込む
$ go get -u github.com/joho/godotenv

# パスワード暗号化
$ go get -u golang.org/x/crypto

インストールが終えたら、main関数を作成し最初のエンドポイントを作っていきます!

コーディング開始

main関数の作成

main.goファイルを作成したら、以下のコードを記述してください。

main.go
package main

import (
    "net/http"

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

func main() {
    router := gin.Default()

    public := router.Group("/api")

    public.POST("/register", func(c *gin.Context) {
        c.JSON(http.StatusOK, gin.H{
            "data": "register endpoint",
        })
    })

    router.Run(":8080")
}

では、以下のコマンドをVScode上のターミナルで叩いて、実行してみましょう。

terminal
$ go run main.go

# 「Listening and serving HTTP on :8080」と出力されればOKです

ブラウザや、curlコマンドでアクセスしてJSONが返ってきたらOKです。

$ curl -X POST http://localhost:8080/api/register
{"data":"register endpoint"}%

「サインアップ」エンドポイントの作成

登録処理の追加を行うため、controllersディレクトリを作成します。
この中にController処理を実装するためにauth.goファイルを作成してください。
それではauth.goファイルにコードを書いていきましょう。

controllers/auth.go
package controllers

import (
    "net/http"

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

func Register(c *gin.Context) {
    c.JSON(http.StatusOK, gin.H{
        "data": "register endpoint.",
    })
}

次に、Register関数が/registerエンドポイントと結びつくように、main.goファイルを修正していきます。

main.go
package main

import (
    // controllersパッケージのインポート
    "go-auth/controllers"

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

func main() {
    router := gin.Default()

    public := router.Group("/api")
  // Register関数の呼び出し
    public.POST("/register", controllers.Register)

    router.Run(":8080")
}

再度、Goを起動させ、curlコマンドあるいはブラウザでJSONを出力されるか確認しましょう。

$ go run main.go

$ curl -X POST http://localhost:8080/api/register
{"data":"register endpoint."}%

「サインアップ」エンドポイントのバリデーションチェック

今回は、サインアップに「ユーザー名」+「パスワード」のみ入力します。
その入力情報をチェックするためにGinのbindingというチェック機能を使用します。

controllers/auth.go
package controllers

import (
	"net/http"

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

type RegisterInput struct {
	Username string `json:"username" binding:"required"`
	Password string `json:"password" binding:"required"`
}

func Register(c *gin.Context) {
	var input RegisterInput

	if err := c.ShouldBindJSON(&input); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"data": "validated!",
	})
}

それではgoを起動させ、動作するか確認してきます。
まずは、「パスワード」のみの入力で検証していきましょう。
この検証をするにあたって Postmanを使用します。
入力内容は以下の通りです。
スクリーンショット 2024-11-05 22.32.15.png

  • メソッドをPOSTを指定し、http://localhost:8080/api/registerとする
  • Bodyrowにチェックを入れ、JSONを選択しましょう
  • 以下のJSONが返ってくるか確認してください

スクリーンショット 2024-11-05 22.37.58.png

次はユーザー名のみも同様に{"username":"<ユーザー名>"}だけを入れて、エラーがJSONで返ってくるか確かめます。
スクリーンショット 2024-11-05 22.40.34.png

最後に「ユーザー名」と「パスワード」の両方を入れましょう。
スクリーンショット 2024-11-05 22.42.47.png
画像の通りのJSONが返ってきたらOKです!

認証情報を MySQL データベースに保存

Dockerを起動させ、MySQLを用意します。
以下のコマンドを叩いてDockerを起動させましょう。

$ docker run --rm -p 3307:3306 -e MYSQL_ROOT_PASSWORD=dev -e MYSQL_USER=dev -e MYSQL_PASSWORD=dev -e MYSQL_DATABASE=dev -d mysql/mysql-server:5.7

簡単にコマンドの説明をすると、

  • docker run:Dockerコンテナの実行を
  • 環境変数の設定は以下の通りです
    • -e MYSQL_USER=dev:devというユーザーの作成
    • -e MYSQL_PASSWORD=dev:devユーザーのパスワードをdevに設定
    • -e MYSQL_DATABASE=dev:DB名をdevに設定
    • -d:バックグラウンドでコンテナが実行されるため、ターミナルを占有しません

起動させた後は、MySQLに接続していきます。以下のコマンドで接続を確認してください。

$ mysql -h 127.0.0.1 -P 3307 -u dev -pdev dev

データベースへの接続処理と Model を格納するためのパッケージとコードを作成します。
それでは、modelsディレクトリを作成し、その中にsetup.goファイルを作成してコードを書いていきましょう。

models/setup.go
package models

import (
	"fmt"
	"log"
	"os"

	"github.com/joho/godotenv"
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
)

var DB *gorm.DB

func ConnectDataBase() {
	err := godotenv.Load()

	if err != nil {
		log.Fatalf("Error loading .env file")
	}

	dbUser := os.Getenv("DB_USER")
	dbPass := os.Getenv("DB_PASS")
	dbName := os.Getenv("DB_NAME")
	dbHost := os.Getenv("DB_HOST")
	dbPort := os.Getenv("DB_PORT")

	dsn := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=utf8mb4&parseTime=True&loc=Local", dbUser, dbPass, dbHost, dbPort, dbName)

	DB, err = gorm.Open(mysql.Open(dsn), &gorm.Config{})
	if err != nil {
		log.Fatal("Could not connect to the database", err)
	}

	// ここで適切なエンティティに対してマイグレーションを実行します。
	DB.AutoMigrate(&User{})
}

また、.envファイルとUser構造体の二つを用意する必要があるので作成していきましょう。
ルートディレクトリに.envファイルを作成し以下のコードを書いてください。

.env
DB_DRIVER=mysql
DB_USER=dev
DB_PASS=dev
DB_NAME=dev
DB_HOST=localhost
DB_PORT=3307

次に、modelsディレクトリにuser.goファイルを作成しUserModelを作成しましょう。

models/user.go
package models

import "gorm.io/gorm"

type User struct {
	gorm.Model
	Username string `gorm:"size:255;not null;unique" json:"username"`
	Password string `gorm:"size:255;not null;" json:"password"`
}

また、main.goファイルにDB接続する処理を追加していきます。

main.go
package main

import (
	"go-auth/controllers"
	"go-auth/models"

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

func main() {
	models.ConnectDataBase()

	router := gin.Default()

	public := router.Group("/api")

	public.POST("/register", controllers.Register)

	router.Run(":8080")
}

処理がかけたのでGoを起動させましょう。
その前に、go mod tidyを叩いて依存関係の整理をしておきましょう。

go mod tidyはGoモジュールの依存関係を整えるためのコマンドです。
依存関係を追加した後や削除した後には、適宜このコマンドを実行しましょう!

terminal
# 使用するパッケージの追加処理
$ go mod tidy

$ go run main.go

起動できたら、以下のコマンドでMySQLに接続し、usersテーブルを表示させてみましょう。

terminal
$ mysql -h 127.0.0.1 -P 3307 -u dev -pdev dev

mysql> show tables;
+---------------+
| Tables_in_dev |
+---------------+
| users         |
+---------------+

DBのマイグレーション処理が正しく動作し users テーブルが追加されたのことが確認できます。

ユーザー情報の登録

サインアップ実装の最終段階をしていきましょう。
usersテーブルへの登録ロジックを実装していきます。

models/user.go
package models

import (
	"strings"

	"golang.org/x/crypto/bcrypt"
	"gorm.io/gorm"
)

type User struct {
	gorm.Model
	Username string `gorm:"size:255;not null;unique" json:"username"`
	Password string `gorm:"size:255;not null;" json:"password"`
}

// User オブジェクトをデータベースに保存する
func (u *User) Save() (*User, error) {
	err := DB.Create(u).Error
	if err != nil {
		return nil, err
	}
	return u, nil
}

// Userオブジェクトが保存される前に実行する
func (u *User) BeforeSave(*gorm.DB) error {
	// パスワードをハッシュ化する
	hashedPassword, err := bcrypt.GenerateFromPassword([]byte(u.Password), bcrypt.DefaultCost)
	if err != nil {
		return err
	}

	u.Password = string(hashedPassword)

	// ユーザーネームを小文字に変換する
	u.Username = strings.ToLower(u.Username)

	return nil
}

// パスワードを空文字にして出力準備をする
func (u *User) PrepareOutput() *User {
	u.Password = ""
	return u
}

auth.goファイルも修正していきます。

controllers/auth.go
package controllers

import (
	"go-auth/models"
	"net/http"

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

type RegisterInput struct {
	Username string `json:"username" binding:"required"`
	Password string `json:"password" binding:"required"`
}

func Register(c *gin.Context) {
	var input RegisterInput

	// リクエストのJSONデータをRegisterInput構造体にバインドする
	if err := c.ShouldBindJSON(&input); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	// ユーザーオブジェクトを作成し、データベースに保存する
	user := &models.User{Username: input.Username, Password: input.Password}
	user, err := user.Save()
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"data": user.PrepareOutput(),
	})
}

Saveメソッドも戻り値を正しく受け取るために、user変数をポインタ型 (*models.User) に変更しました。
Goを起動させ、検証していきましょう!

terminal
$ go run main.go 

Postmanを使用してPOSTリクエストを送ってみましょう。以下の画像の通りに進めてください。
スクリーンショット 2024-11-07 21.37.39.png
ステータスコード200が返ってきたことを確認した後、MySQLに接続しusersテーブルにデータが追加されているか確認していきます。

# MySQLに接続
$ mysql -h 127.0.0.1 -P 3307 -u dev -pdev dev

# SELECT文でusersテーブルのデータを確認
mysql> select * from users;
+----+-------------------------+-------------------------+------------+----------+--------------------------------------------------------------+
| id | created_at              | updated_at              | deleted_at | username | password                                                     |
+----+-------------------------+-------------------------+------------+----------+--------------------------------------------------------------+
|  4 | 2024-11-07 21:33:43.172 | 2024-11-07 21:33:43.172 | NULL       | fujifuji | $2a$10$IZpxktFgsKDLyDOkK/m1te8.DLAPh/XuFcBf5BO0ci4XRgKbJ.Ak6 |
+----+-------------------------+-------------------------+------------+----------+--------------------------------------------------------------+

データが登録され、パスワードがハッシュ化されていればOKです!

「ログイン」エンドポイントの作成

それでは、ログイン用のエンドポイントを作成していきましょう。
「ユーザー名」と「パスワード」を受け取り、DBにあるusersテーブルと照合を行う処理を書いていきます。
main.goファイルから編集していきます。

main.go
package main

import (
	"go-auth/controllers"
	"go-auth/models"

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

func main() {
	models.ConnectDataBase()

	router := gin.Default()

	public := router.Group("/api")

	public.POST("/register", controllers.Register)
 // /loginエンドポイントの追加
	public.POST("/login", controllers.Login)

	router.Run(":8080")
}

auth.goファイルにcontrollers.Loginメソッドの作成をしていきます。

controllers/auth.go
package controllers

import (
	"go-auth/models"
	"net/http"

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

type RegisterInput struct {
	Username string `json:"username" binding:"required"`
	Password string `json:"password" binding:"required"`
}

func Register(c *gin.Context) {
	var input RegisterInput

	// リクエストのJSONデータをRegisterInput構造体にバインドする
	if err := c.ShouldBindJSON(&input); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	// ユーザーオブジェクトを作成し、データベースに保存する
	user := &models.User{Username: input.Username, Password: input.Password}
	user, err := user.Save()
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	// 成功した場合、ユーザー情報をレスポンスとして返す
	c.JSON(http.StatusOK, gin.H{
		"data": user.PrepareOutput(),
	})
}

type LoginInput struct {
	Username string `json:"username" binding:"required"`
	Password string `json:"password" binding:"required"`
}

func Login(c *gin.Context) {
	var input LoginInput

	if err := c.ShouldBindJSON(&input); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	token, err := models.GenerateToken(input.Username, input.Password)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"token": token,
	})
}

Controller であるLogin関数から呼び出している GenerateToken 関数を user.go ファイルに追記します。

models/user.go
package models

import (
	"go-auth/utils/token"
	"strings"

	"golang.org/x/crypto/bcrypt"
	"gorm.io/gorm"
)

type User struct {
	gorm.Model
	Username string `gorm:"size:255;not null;unique" json:"username"`
	Password string `gorm:"size:255;not null;" json:"password"`
}

// User オブジェクトをデータベースに保存する
func (u *User) Save() (*User, error) {
	err := DB.Create(u).Error
	if err != nil {
		return nil, err
	}
	return u, nil
}

// Userオブジェクトが保存される前に実行する
func (u *User) BeforeSave(*gorm.DB) error {
	// パスワードをハッシュ化する
	hashedPassword, err := bcrypt.GenerateFromPassword([]byte(u.Password), bcrypt.DefaultCost)
	if err != nil {
		return err
	}

	u.Password = string(hashedPassword)

	// ユーザーネームを小文字に変換する
	u.Username = strings.ToLower(u.Username)

	return nil
}

// パスワードを空文字にして出力準備をする
func (u *User) PrepareOutput() *User {
	u.Password = ""
	return u
}

func GenerateToken(username string, password string) (string, error) {
	var user User

	err := DB.Where("username = ?", username).First(&user).Error

	if err != nil {
		return "", err
	}

	err = bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(password))

	if err != nil {
		return "", err
	}

	token, err := token.GenerateToken(user.ID)

	if err != nil {
		return "", err
	}

	return token, nil
}

token.goファイルを作成し、このファイルにトークンの操作する関数を作成していきます。

terminal
$ mkdir -p ./utils/token

$ touch ./utils/token/token.go

以下の3つの関数を外部から呼び出せるようにします。

  • GenerateToken 関数
  • TokenValid 関数
  • ExtractTokenId 関数

TokenValid 関数と ExtractTokenId 関数の2つに関しては後ほど利用します。
それではtoken.goファイルを編集していきましょう。

utils/token/token.go
package token

import (
   "fmt"
   "os"
   "strconv"
   "strings"
   "time"

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

// 指定されたユーザーIDに基づいてJWTトークンを生成する
func GenerateToken(id uint) (string, error) {
   tokenLifespan, err := strconv.Atoi(os.Getenv("TOKEN_HOUR_LIFESPAN"))

   if err != nil {
   	return "", err
   }

   claims := jwt.MapClaims{}
   claims["authorized"] = true
   claims["user_id"] = id
   claims["exp"] = time.Now().Add(time.Hour * time.Duration(tokenLifespan)).Unix()
   token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)

   return token.SignedString([]byte(os.Getenv("API_SECRET")))
}

func extractTokenString(c *gin.Context) string {
   bearToken := c.Request.Header.Get("Authorization")
   strArr := strings.Split(bearToken, " ")
   if len(strArr) == 2 {
   	return strArr[1]
   }

   return ""
}

func parseToken(tokenString 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("There was an error")
   	}
   	return []byte(os.Getenv("API_SECRET")), nil
   })

   if err != nil {
   	return nil, err
   }

   return token, nil
}

// トークンが有効かどうかを検証
func TokenValid(c *gin.Context) error {
   tokenString := extractTokenString(c)

   token, err := parseToken(tokenString)

   if err != nil {
   	return err
   }

   if !token.Valid {
   	return fmt.Errorf("Invalid token")
   }

   return nil
}

// トークンからユーザーIDを取得
func ExtractTokenId(c *gin.Context) (uint, error) {
   tokenString := extractTokenString(c)

   token, err := parseToken(tokenString)

   if err != nil {
   	return 0, err
   }

   claims, ok := token.Claims.(jwt.MapClaims)

   if ok && token.Valid {
   	userId, ok := claims["user_id"].(float64)

   	if !ok {
   		return 0, nil
   	}

   	return uint(userId), nil
   }

   return 0, nil
}

そして、コードに登場したTOKEN_HOUR_LIFESPANAPI_SECRETの2つの環境変数を.envファイルに追加していきます。

.env
DB_DRIVER=mysql
DB_USER=dev
DB_PASS=dev
DB_NAME=dev
DB_HOST=localhost
DB_PORT=3307
// トークンの有効期限
TOKEN_HOUR_LIFESPAN=1
// JSONの署名に使用する秘密鍵
API_SECRET=go-auth-dev

では、Goを起動させてみましょう!

terminal
# 使用するパッケージの追加処理(忘れないように👍)
$ go mod tidy
$ go run main.go

Postmanでリクエストを投げて動作確認していきましょう。
まずは、ユーザー名のみ正しいパターン
スクリーンショット 2024-11-07 23.19.54.png
以下のJSONが返ってくるか確認しましょう。

JSON
"error": "crypto/bcrypt: hashedPassword is not the hash of the given password"

次は、パスワードのみ正しいパターン
スクリーンショット 2024-11-07 23.25.25.png

JSON
"error": "record not found"

ラストに、ユーザー名・パスワードともに正しいパターン
スクリーンショット 2024-11-07 23.25.52.png
ログインに成功した際に、トークンが生成されるようになりました。

認証用ミドルウェアの作成

Ginにはミドルウェアという機能があり、これを使用してController にリクエストが到達する前に処理を行うようにしていきます。
middlerwareディレクトリを作成し、その中にmiddlerwares.goファイルを作成し、以下のように書いてください。

middlewares/middlerwares.go
package middlewares

import (
	"go-auth/utils/token"
	"net/http"

	"github.com/gin-gonic/gin"
)
// JwtAuthMiddleware はJWT認証を行うミドルウェアを返します
func JwtAuthMiddleware() gin.HandlerFunc {
	return func(c *gin.Context) {
		err := token.TokenValid(c)

		if err != nil {
			c.JSON(http.StatusUnauthorized, gin.H{"error": err.Error()})
			c.Abort()
			return
		}

		c.Next()
	}
}

main.goファイルに新しい/api/admin/user エンドポイントの追加とこれに対するミドルウェアの設定を行います。

main.go
package main

import (
	"go-auth/controllers"
	middlewares "go-auth/middlerwares"
	"go-auth/models"

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

func main() {
	models.ConnectDataBase()

	router := gin.Default()

	public := router.Group("/api")
    
	public.POST("/register", controllers.Register)
	public.POST("/login", controllers.Login)

	protected := router.Group("/api/admin")
   // JWT認証ミドルウェアを適用
	protected.Use(middlewares.JwtAuthMiddleware())
   // 認証されたユーザー情報を取得するルートを定義
	protected.GET("/user", controllers.CurrentUser)

	router.Run(":8080")
}

そして新たに追加したCurrentUser 関数をauth.goファイルに書いていきます。

controllers/auth.go
package controllers

import (
	"go-auth/models"
	"go-auth/utils/token"
	"net/http"

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

type RegisterInput struct {
	Username string `json:"username" binding:"required"`
	Password string `json:"password" binding:"required"`
}

func Register(c *gin.Context) {
	var input RegisterInput

	// リクエストのJSONデータをRegisterInput構造体にバインドする
	if err := c.ShouldBindJSON(&input); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	// ユーザーオブジェクトを作成し、データベースに保存する
	user := &models.User{Username: input.Username, Password: input.Password}
	user, err := user.Save()
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	// 成功した場合、ユーザー情報をレスポンスとして返す
	c.JSON(http.StatusOK, gin.H{
		"data": user.PrepareOutput(),
	})
}

type LoginInput struct {
	Username string `json:"username" binding:"required"`
	Password string `json:"password" binding:"required"`
}

func Login(c *gin.Context) {
	var input LoginInput

	if err := c.ShouldBindJSON(&input); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	token, err := models.GenerateToken(input.Username, input.Password)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"token": token,
	})
}

func CurrentUser(c *gin.Context) {
   // トークンからユーザーIDを抽出する
	userId, err := token.ExtractTokenId(c)

	if err != nil {
		c.JSON(http.StatusUnauthorized, gin.H{"error": err.Error()})
		return
	}

	var user models.User
   // ユーザーIDに基づいてユーザー情報をデータベースから取得する
	err = models.DB.First(&user, userId).Error

	if err != nil {
		c.JSON(http.StatusUnauthorized, gin.H{"error": err.Error()})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"data": user.PrepareOutput(),
	})
}

それでは、Go起動させて検証していきましょう!
ますは/api/loginエンドポイントに対してログインを行い、トークンを取得していきます。
スクリーンショット 2024-11-08 21.37.28.png
取得したトークンは後で使用するのでPostmanで別タブを開いておきましょう。

次に、/api/admin/userエドポイントにGETリクエストを送ってみましょう。
まずはトークンを使用しないパターンを検証していきます。Postmanの設定は以下の画像の通りです。

  • メソッドをGETにする
  • Headersタブを開いてKeyAuthorizationValueは空で大丈夫です

スクリーンショット 2024-11-08 21.45.03.png
エラーが返ってきたのでOKです!
今度はValueにトークンを設定してリクエストを送ってみましょう。

  • ValueBearer <トークン>を入力する
    • Bearerの後は半角スペースを入れてください

スクリーンショット 2024-11-08 21.49.45.png
うまくデータが取得できたらOKです!

さいごに

今回はGo言語のGinを使い、簡単なログイン認証システムを作成しました。
エンドポイントの構築やJWTによる認証、MySQLデータベースとの連携方法を通して、Webアプリケーションの基本的な認証の仕組みについて学べたら幸いです。

参考

8
3
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
8
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?