【Go】echoフレームワークでログイン機能を作成する
2017.03.14

こんにちは。ユニトラストの白石です。
今回はGoで作成されたフレームワークecho(v3.0.3)でログイン機能を実装する形で紹介します。
echoとは
Go製の軽量なフレームワークの1つです。「golang echo」で使用例を検索するとjsonを返すAPIサーバーの事例が多いですが、Goのパッケージであるhtml/templateを使うことでwebアプリケーションの開発も可能です。また、echoは拡張性が高く、Middleware群によって機能を追加することができます。
インストール
echoは「go get github.com/labstack/echo」のコマンドで簡単にインストールすることができます。
コード
下記のコードがログイン機能を実装した全コードです。抜粋しながら説明をしていきます。
package main import ( "io" "github.com/labstack/echo" "html/template" "net/http" "html" "github.com/ipfans/echo-session" ) type Template struct { templates *template.Template } func (t *Template) Render(w io.Writer, name string, data interface{}, c echo.Context) error { return t.templates.ExecuteTemplate(w, name, data) } func main() { var e = echo.New() //テンプレートの設定 t := &Template{ templates: template.Must(template.ParseGlob("static/template/*.html")), } e.Renderer = t //セッションを設定 store := session.NewCookieStore([]byte("secret-key")) //セッション保持時間 store.MaxAge(86400) e.Use(session.Sessions("ESESSION", store)) e.GET("/login", ShowLoginHtml) e.POST("/login", Login) // ポート9000でサーバーを起動 e.Logger.Fatal(e.Start(":9000")) // Let's Encrypt から証明書を自動取得してhttpsサーバーを起動 //e.Logger.Fatal(e.StartAutoTLS(":443")) } type LoginForm struct { UserId string Password string ErrorMessage string } type CompleteJson struct { Success bool `json:"success"` } func ShowLoginHtml(c echo.Context) error { session := session.Default(c) loginId := session.Get("loginCompleted") if loginId != nil && loginId == "completed" { completeJson := CompleteJson{ Success: true, } return c.JSON(http.StatusOK, completeJson) } return c.Render(http.StatusOK, "login", LoginForm{}) } func Login(c echo.Context) error { loginForm := LoginForm{ UserId: c.FormValue("userId"), Password: c.FormValue("password"), } userId := html.EscapeString(loginForm.UserId) password := html.EscapeString(loginForm.Password) if userId != "userId" && password != "password" { loginForm.ErrorMessage = "ユーザーID または パスワードが間違っています" return c.Render(http.StatusOK, "login", loginForm) } //セッションにデータを保存する session := session.Default(c) session.Set("loginCompleted", "completed") session.Save() completeJson := CompleteJson{ Success: true, } return c.JSON(http.StatusOK, completeJson) }
main
mainメソッドを見ていきます。
最初にechoを初期化します。
var e = echo.New()
今回はログイン画面にテンプレートを使うので、echoにテンプレートを設定します。(/static/templateディレクトリ以下のhtmlを対象にしています)
//テンプレートの設定 t := &Template{ templates: template.Must(template.ParseGlob("static/template/*.html")), } e.Renderer = t
未ログインとログイン中を区別するために、Middlewareのecho-sessionを使って、ログイン情報をセッションに保持します。(echo-sessionはgo get github.com/ipfans/echo-sessionでインストールします)
//セッションを設定 store := session.NewCookieStore([]byte("secret-key")) //セッション保持時間 store.MaxAge(86400) e.Use(session.Sessions("ESESSION", store))
/loginにGETでアクセスをするとShowLoginHtmlメソッドが呼ばれます。
e.GET("/login", ShowLoginHtml)
/loginにPOSTでアクセスするとLoginメソッドが呼ばれます。
e.POST("/login", Login)
最後にサーバーを起動します。起動に失敗したらログが出力されます。
// ポート9000でサーバーを起動 e.Logger.Fatal(e.Start(":9000"))
ShowLoginHtml
ShowLoginHtmlメソッドを見ていきます。
ログイン中だった場合はJSONを返します。
ログイン中でなかった場合はlogin.htmlのテンプレートを表示します。第3引数に空の構造体を使います。(構造体のstringはnilではなく空文字です)
return c.Render(http.StatusOK, "login", LoginForm{})
Login
Loginメソッドを見ていきます。
フォームからpostされた値を確認して、ユーザーIDとパスワードに一致していた場合は、JSONを返します。
一致していない場合は、ShowLoginHtmlでは空だったLoginForm構造体のメンバにユーザーが入力したパラメーターとエラーメッセージを設定して、login.htmlのテンプレートを表示します。こうすることで、前回の入力とエラーメッセージが表示されます。
(今回はユーザーIDとパスワードをコードに書いていますが、ユーザーIDとsaltを使ったhash化したパスワードをDBに保存するのが適切です。)
loginForm := LoginForm{ UserId: c.FormValue("userId"), Password: c.FormValue("password"), } loginForm.ErrorMessage = "ユーザーID または パスワードが間違っています" return c.Render(http.StatusOK, "login", loginForm)
テンプレート
LoginForm.ErrorMessageが空文字でない(ne)ときに、エラーメッセージを表示します。if文の条件にはne(不一致)の他に、eq(一致)、lt(より下)、le(以下)、gt(より上)、ge(以上)があります。
詳しくは、公式ドキュメントを参照してください。
{{define "login"}} <!DOCTYPE html> <html lang="jp"> <head> <meta charset="UTF-8"> <title>ログイン</title> </head> <body> <form action="/login" method="post"> {{if ne .ErrorMessage ""}} <p>{{.ErrorMessage}}</p> {{end}} <p>ユーザーID</p> <p><input type="text" name="userId" value="{{.UserId}}"></p> <p>パスワード</p> <p><input type="password" name="password" value="{{.Password}}"></p> <p><input type="submit" value="ログイン"></p> </form> </body> </html> {{end}}
まとめ
今回、echoを使ってログイン機能を作成しました。紹介したechoの機能は一部に過ぎません。例えば、Basic認証を設定したり、Let’s Encryptから自動で証明書を取得する機能などもあります。この機会にPHP、Javaから離れて、GoでWebアプリケーションを作成してみてはいかがでしょうか?
CONTACT
お問い合わせ
あなたの「想い」に挑戦します。
どうぞお気軽にお問い合わせください。
受付時間:平日9:00〜18:00 日・祝日・弊社指定休業日は除く
