べーごー signup,login,logout
Beegoで認証あたりを処理を書いた(メール飛ばしたりはしてない)。以下やっていること
- プロジェクト生成
- Model定義
- Form処理
- ユーザー, 認証処理
- Flash messages, Session処理
- login filter(require)なるもの
もろもろインストール
$ go get -u github.com/beego/bee $ go get -u github.com/astaxie/beego
プロジェクト作成コマンド
$ bee new auth
こんなツリーが出来る
$ tree . ├── conf │ └── app.conf ├── controllers │ └── default.go ├── main.go ├── models ├── routers │ └── router.go ├── static │ ├── css │ ├── img │ └── js ├── tests │ └── default_test.go └── views └── index.tpl
ユーザーを定義する
Email,Password,ログイン時間,作成時間,更新時間のよくある形
package models import ( "time" "github.com/astaxie/beego" "github.com/astaxie/beego/orm" ) type User struct { Id int64 Email string `orm:"size(64);unique"` Password string `orm:"size(32)"` Lastlogintime time.Time `orm:"type(datetime);null"` Created time.Time `orm:"auto_now_add;type(datetime)"` Updated time.Time `orm:"auto_now;type(datetime)"` } func init() { orm.RegisterModelWithPrefix( beego.AppConfig.String("dbprefix"), new(User)) }
.. doc::
Fieldに複数の属性をつける場合ははセミコロン(;)でつなげる どんな属性があるかはドキュメントを: Model Definition - beego: simple & powerful Go app framework
次
Modelを定義したらDDLを走らせる。 これは以下のようにorm.RunSyncdbをinitあたりに定義しておけばBeegoがやってくれる (ノリ的にDjangoのsyncdbと同じもの)
func init() { dbname, force, verbose := "default", false, true err := orm.RunSyncdb(dbname, force, verbose) if err != nil { panic(err) } }
私はこんなふうに書いてます: beego-samples/db.go at master · ikeikeikeike/beego-samples · GitHub
次
Formの定義
先ほど定義したuserテーブルを編集, パスワード確認のRepasswordと「form:」「valud:」を追加
type User struct { Id int64 Email string `orm:"size(64);unique" form:"Email" valid:"Required;Email"` Password string `orm:"size(32)" form:"Password" valid:"Required;MinSize(6)"` Repassword string `orm:"-" form:"Repassword" valid:"Required"` Lastlogintime time.Time `orm:"type(datetime);null" form:"-"` Created time.Time `orm:"auto_now_add;type(datetime)"` Updated time.Time `orm:"auto_now;type(datetime)"` }
「form:」はhtml上のkinput[name="Email"]のところ。「valud:」はValidation定義 ドキュメントはここ: Form validation - beego: simple & powerful Go app framework
上述に対応するHTMLが下記のような形になる。
<form method="POST" action='{{urlfor "LoginController.Login"}}'> {{ .xsrfdata }} <input name="Email" type="email" value="{{index .Params "Email"}}" required /> <input name="Password" type="password" value="" required pattern=".{6,}" title="パスワードは6文字以上を入力してください" /> <input name="Repassword" type="password" required pattern=".{6,}" title="パスワードは6文字以上を入力してください" /> <input type="submit" value="ログイン"> </form>
次は認証処理
- Routerの追加
Routerは以下の物があり,Automatching, Annotations, Namespaceがあったり色々できる
以下の例ははSinatra風に記述ができるRegex routerを使用している
package routers import ( ctl "bitbucket.org/ikeikeikeike/auth/controllers" "github.com/astaxie/beego" ) func init() { beego.Router("/login", &ctl.LoginController{}, "get,post:Login") beego.Router("/logout", &ctl.LoginController{}, "get:Logout") beego.Router("/signup", &ctl.LoginController{}, "get,post:Signup") }
- Controller Signup部分
xsrf, flash message, formのパース, Sessionとか色々やってる
func (c *LoginController) Signup() { c.TplNames = "login/signup.tpl" c.Data["xsrfdata"] = template.HTML(c.XsrfFormHtml()) if !c.Ctx.Input.IsPost() { return } var err error flash := beego.NewFlash() u := &models.User{} if err = c.ParseForm(u); err != nil { flash.Error("Signup invalid!") flash.Store(&c.Controller) return } if err = models.IsValid(u); err != nil { flash.Error(err.Error()) flash.Store(&c.Controller) return } id, err := lib.SignupUser(u) if err != nil || id < 1 { flash.Warning(err.Error()) flash.Store(&c.Controller) return } flash.Success("Register user: %s", u.Email) flash.Store(&c.Controller) c.SetLogin(u) c.Redirect(c.UrlFor("UsersController.Index"), 303) }
- Ctrl Login,Logout部分
とくに変わったことなし, URL参照: beego-samples/login.go at master · ikeikeikeike/beego-samples · GitHub
次,リクエスト時にログインしているか事前に確認するようにする
Filtersを使用: Filters - beego: simple & powerful Go app framework
beego.InsertFilter("/", beego.BeforeRouter, func(ctx *context.Context) { _, ok := ctx.Input.Session("userinfo").(int64) if !ok { ctx.Redirect(302, "/login") } }) beego.Router("/", &ctl.UsersController{}, "get:Index") beego.Router("/login", &ctl.LoginController{}, "get,post:Login") beego.Router("/logout", &ctl.LoginController{}, "get:Logout") beego.Router("/signup", &ctl.LoginController{}, "get,post:Signup")
Prepareをoverwriteすることでも実現できる: Controller funcs - beego: simple & powerful Go app framework
func (c *UsersController) Prepare() { if !c.IsLogin { c.Ctx.Redirect(302, c.LoginPath()) return } }
以上どす
上述の例を少しだけ拡張したサンプルソースコード