2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Ginを利用して新規登録、ログイン機能をJWT認証で実装(ログイン編)

Last updated at Posted at 2023-03-01

概要

今回は下記の続きでログイン機能の実装を行なっていきます。

バージョン等の情報は上記の記事に記載されているので

もし知りたい方がいらっしゃれば、前回の記事を閲覧いただけると幸いです。

ログイン処理の実装

それではさっそく実装を行なっていきます。

まずは前回同様モデルの構築から行なっていきます。

モデルの構築

前回解説の際に使用したpkg/models/user.goに追記していきます。

pkg/models/user.go
package models

import (
	"github.com/go-ozzo/ozzo-validation"
	"github.com/go-ozzo/ozzo-validation/is"
	"gorm.io/gorm"

	"github.com/soicchi/chatapp_backend/pkg/utils"
)

type User struct {
	gorm.Model
	Name     string `gorm:"size:255;not null"`
	Email    string `gorm:"size:255;not null;unique"`
	Password string `gorm:"size:255;not null"`
}

type SignUpInput struct {
	Name     string `json:"name" binding:"required"`
	Email    string `json:"email" binding:"required"`
	Password string `json:"password" binding:"required"`
}

type LoginInput struct {
	Email    string `json:"email" binding:"required"`
	Password string `json:"password" binding:"required"`
}

func (u *User) Create(db *gorm.DB) (User, error) {
	user := User{
		Name:     u.Name,
		Email:    u.Email,
		Password: utils.Encrypt(u.Password),
	}
	result := db.Create(&user)

	return user, result.Error
}

// ここから追記
func FindUserByEmail(db *gorm.DB, email string) (User, error) {
	var user User
	result := db.Where("email = ?", email).First(&user)

	return user, result.Error
}

func (u *User) VerifyPassword(inputPassword string) bool {
	return u.Password == utils.Encrypt(inputPassword)
}

ログインする際はメールアドレスパスワードを用いるので、

メールアドレスでユーザーを検索できるようにFindUserByEmail()を定義しています。

また、VerifyPassword()はログインの際のパスワードをコントローラー側で

検証するために定義しています。

さらに前回同様ログインの際にバインドさせるための構造体LoginInput)を定義しています。

コントローラーの定義

続いてコントローラーの定義を行なっていきます。

こちらもモデル同様に追記していきます。

pkg/controllers/auth.go
func (handler *Handler) LoginHandler(context *gin.Context) {
	var loginInput models.LoginInput
	if err := context.ShouldBind(&loginInput); err != nil {
        context.JSON(http.StatusBadRequest, gin.H{
			"error":   err.Error(),
			"message": "Invalid request body",
		})
		return
    }

	user, err := models.FindUserByEmail(handler.DB, loginInput.Email)
	if err != nil {
		context.JSON(http.StatusBadRequest, gin.H{
			"error":   err.Error(),
			"message": "Failed to find user",
		})
		return
	}

    // 入力されたパスワードとIDから取得したパスワードが等しいかを検証
	if !user.VerifyPassword(loginInput.Password) {
		context.JSON(http.StatusUnauthorized, gin.H{
			"message": "Password is invalid",
		})
		return
	}

	context.JSON(http.StatusOK, gin.H{
		"message": "Successfully logged in",
	})
}

routerの設定

最後にrouterの設定を行います。

pkg/router/auth.go
package router

import (
	"github.com/gin-gonic/gin"

	"github.com/soicchi/chatapp_backend/pkg/controllers"
)

func addAuthRoutes(routerGroup *gin.RouterGroup, handler *controllers.Handler) {
	auth := routerGroup.Group("/auth")
	{
		auth.POST("/signup", handler.SignUpHandler)
        // 追記
		auth.POST("/login", handler.LoginHandler)
	}
}

これでログインのための一通りの実装は終わりました。

検証

では、実際に立ち上げてログインしてみましょう。

下記コマンドでコンテナを立ち上げます。

docker compose up

下記のようになれば立ち上げの成功です。

api    | [GIN-debug] [WARNING] Creating an Engine instance with the Logger and Recovery middleware already attached.
api    | 
api    | [GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production.
api    |  - using env:	export GIN_MODE=release
api    |  - using code:	gin.SetMode(gin.ReleaseMode)
api    | 
api    | [GIN-debug] POST   /api/v1/auth/signup       --> app/pkg/controllers.(*Handler).SignUpHandler-fm (3 handlers)
api    | [GIN-debug] POST   /api/v1/auth/login        --> app/pkg/controllers.(*Handler).LoginHandler-fm (3 handlers)
api    | [GIN-debug] [WARNING] You trusted all proxies, this is NOT safe. We recommend you to set a value.
api    | Please check https://pkg.go.dev/github.com/gin-gonic/gin#readme-don-t-trust-all-proxies for details.
api    | [GIN-debug] Environment variable PORT is undefined. Using port :8080 by default
api    | [GIN-debug] Listening and serving HTTP on :8080

前回登録したユーザー情報は下記なので

そのユーザーIDとパスワードを使用してログインしてみます。

前回登録したユーザー情報

{"name":"sample-test", "email":"sample@sample.com", "password":"Test1234"}

下記コマンドを入力してリクエストを送ってみます。

curl -X POST -H "Content-Type: application/json" http://127.0.0.1:8080/api/v1/auth/login -d '{"email":"sample@sample.com", "password":"Test1234"}'

正常に動作していれば下記のようにレスポンスが返ってくると思います。

{"message":"Successfully logged in"}

まとめ

いかがだったでしょうか。

ログイン機能の実装自体はそれほど難しくはなかったと思います。

しかし、私が記載した方法よりももっといい方法があるかもしれません。

もしそういった意見がありましたら是非コメントしていただけると幸いです。

次回はいよいよJWT認証機能を説明します!

最後まで読んでいただきありがとうございました!

2
2
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
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?