LoginSignup
0
0

More than 1 year has passed since last update.

zinのLogin

Posted at

はじめに

GolangのZinを使いログイン処理を書きました 

Login

[hoge] % tree                                                                         ~/go/src/login
.
├── SessionInfo
│   └── sessioninfo.go
├── controller
│   └── Login.go
├── crypto
│   └── crypto.go
├── db
│   └── db.go
├── go.mod
├── go.sum
├── login
├── main.go
├── migrate
│   └── migrate.go
├── model
│   ├── Login.go
│   └── User.go
└── template
    ├── login.html
    ├── logout.html
    ├── menu.html
    └── singup.html

7 directories, 15 files

main

package main

import (
   "log"
   sessioninfo "login/SessionInfo"
   "login/controller"
   "net/http"

   "github.com/gin-contrib/sessions"
   "github.com/gin-contrib/sessions/cookie"
   "github.com/gin-gonic/gin"
)

var LoginInfo sessioninfo.SessionInfo

func main() {
   engine := gin.Default()
   engine.LoadHTMLGlob("template/*")
   store := cookie.NewStore([]byte("select"))
   engine.Use(sessions.Sessions("mysession", store))

   engine.GET("/login", func(c *gin.Context) {
       c.HTML(200, "login.html", gin.H{
           "UserId": "",
       })
   })
   engine.POST("/login", controller.NewLogin().LoginK)

   engine.GET("/singup", func(c *gin.Context) {
       c.HTML(200, "singup.html", gin.H{})
   })
   engine.POST("/singup", controller.NewLogin().SingUp)
   menu := engine.Group("/menu")
   menu.Use(sessionCheck())
   {
       menu.GET("/top", controller.GetMenu)

   }

   engine.POST("/logout", controller.PostLogout)
   engine.Run(":8080")
}

func sessionCheck() gin.HandlerFunc {
   return func(c *gin.Context) {
       session := sessions.Default(c)
       LoginInfo.Name = session.Get("name")
       // セッションがない場合、ログインフォームをだす
       if LoginInfo.Name == nil {
           log.Println(session)
           log.Println("ログインしていません")
           c.Redirect(http.StatusMovedPermanently, "/login")
           c.Abort() // これがないと続けて処理されてしまう
       } else {
           c.Set("name", LoginInfo.Name) // ユーザidをセット
           c.Next()
       }
       log.Println("ログインチェック終わり")
   }
}

db

package db

import (
 "fmt"
 "os"

 "github.com/jinzhu/gorm"
 _ "github.com/jinzhu/gorm/dialects/mysql"
 "github.com/joho/godotenv"
)

func Connection() *gorm.DB {
 err := godotenv.Load(fmt.Sprintf("./%s.env", os.Getenv("GO_ENV")))
 if err != nil {
   // .env読めなかった場合の処理
 }
 DBMS := os.Getenv("login_DBMS")
 USER := os.Getenv("login_USER")
 PASS := os.Getenv("login_PASS")
 DBNAME := os.Getenv("login_DBNAME")
 CONNECT := USER + ":" + PASS + "@/" + DBNAME + "?parseTime=true"
 db, err := gorm.Open(DBMS, CONNECT)

 if err != nil {
   panic(err.Error())
 }
 db.LogMode(true)
 return db
}

migrate

package main

import (
   "login/db"
   "login/model"
)

func main() {
   db := db.Connection()
   defer db.Close()

   db.AutoMigrate(&model.Login{})
   db.AutoMigrate(&model.User{})
}

model

DB

package model

import (
   _ "github.com/go-sql-driver/mysql"
   "github.com/jinzhu/gorm"
   _ "github.com/jinzhu/gorm/dialects/mysql"
)

type Login struct {
   gorm.Model
   Name string `gorm:"unique; not null"`
   Pass string `gorm:"not null"`
}

crypto

package crypto

import (
   "golang.org/x/crypto/bcrypt"
)

// PasswordEncrypt パスワードをhash化
func PasswordEncrypt(password string) (string, error) {
   hash, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
   return string(hash), err
}

// CompareHashAndPassword hashと非hashパスワード比較
func CompareHashAndPassword(hash, password string) error {
   return bcrypt.CompareHashAndPassword([]byte(hash), []byte(password))
}

Sessions

package sessioninfo

type SessionInfo struct {
   Name interface{}
}

Controller

package controller

import (
   "log"
   "login/crypto"
   "login/db"
   "login/model"
   "net/http"

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

type Login struct{}

func NewLogin() *Login {
   return &Login{}
}

func LoginM(c *gin.Context, name string) {
   session := sessions.Default(c)
   session.Set("name", name)
   session.Save()
}
func getUser(username string) model.Login {
   db := db.Connection()
   var user model.Login
   db.First(&user, "name = ?", username)
   db.Close()
   return user
}
func (l *Login) LoginK(c *gin.Context) {
   db := db.Connection()
   defer db.Close()
   log.Println("ログイン処理")
   name := c.PostForm("name")

   LoginM(c, name) // // 同じパッケージ内のログイン処理

   dbPassword := getUser(c.PostForm("name")).Pass
   log.Println(dbPassword)
   // フォームから取得したユーザーパスワード
   formPassword := c.PostForm("pass")

   // ユーザーパスワードの比較
   if err := crypto.CompareHashAndPassword(dbPassword, formPassword); err != nil {
       log.Println("ログインできませんでした")

       c.Abort()
   } else {
       log.Println("ログインできました")
       c.Redirect(http.StatusMovedPermanently, "/menu/top")
   }
}
func (l *Login) SingUp(c *gin.Context) {
   var form Login
   if err := c.Bind(&form); err != nil {
       c.Abort()
   } else {
       username := c.PostForm("name")
       password := c.PostForm("pass")
       // 登録ユーザーが重複していた場合にはじく処理PasswordEncrypt

       passwordEncrypt, _ := crypto.PasswordEncrypt(password)
       db := db.Connection()
       defer db.Close()

       if err := db.Create(&model.Login{Name: username, Pass: passwordEncrypt}).GetErrors(); err != nil {

       }
       c.Redirect(302, "/login")   }
}
func PostLogout(c *gin.Context) {
   log.Println("ログアウト処理")
   Logout(c) // 同じパッケージ内のログアウト処理

   // ログインフォームに戻す
   c.HTML(http.StatusOK, "login.html", gin.H{
       "name":         "",
       "ErrorMessage": "",
   })
}
func Logout(c *gin.Context) {
   session := sessions.Default(c)
   log.Println("セッション取得")
   session.Clear()
   log.Println("クリア処理")
   session.Save()
}
func GetMenu(c *gin.Context) {
   name, _ := c.Get("name") // ログインユーザの取得

   c.HTML(http.StatusOK, "menu", gin.H{"name": name})
}

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