W3Cschool
恭喜您成為首批注冊用戶
獲得88經(jīng)驗值獎勵
在開發(fā)Web應(yīng)用過程中,用戶認證是開發(fā)者經(jīng)常遇到的問題,用戶登錄、注冊、登出等操作,而一般認證也分為三個方面的認證
beego目前沒有針對這三種方式進行任何形式的集成,但是可以充分的利用第三方開源庫來實現(xiàn)上面的三種方式的用戶認證,不過后續(xù)beego會對前面兩種認證逐步集成。
這兩個認證是一些應(yīng)用采用的比較簡單的認證,目前已經(jīng)有開源的第三方庫支持這兩個認證:
github.com/abbot/go-http-auth
下面代碼演示了如何把這個庫引入beego中從而實現(xiàn)認證:
package controllers
import (
"github.com/abbot/go-http-auth"
"github.com/astaxie/beego"
)
func Secret(user, realm string) string {
if user == "john" {
// password is "hello"
return "$1$dlPL2MqE$oQmn16q49SqdmhenQuNgs1"
}
return ""
}
type MainController struct {
beego.Controller
}
func (this *MainController) Prepare() {
a := auth.NewBasicAuthenticator("example.com", Secret)
if username := a.CheckAuth(this.Ctx.Request); username == "" {
a.RequireAuth(this.Ctx.ResponseWriter, this.Ctx.Request)
}
}
func (this *MainController) Get() {
this.Data["Username"] = "astaxie"
this.Data["Email"] = "astaxie@gmail.com"
this.TplNames = "index.tpl"
}
上面代碼利用了beego的prepare函數(shù),在執(zhí)行正常邏輯之前調(diào)用了認證函數(shù),這樣就非常簡單的實現(xiàn)了http auth,digest的認證也是同樣的原理。
oauth和oauth2是目前比較流行的兩種認證方式,還好第三方有一個庫實現(xiàn)了這個認證,但是是國外實現(xiàn)的,并沒有QQ、微博之類的國內(nèi)應(yīng)用認證集成:
github.com/bradrydzewski/go.auth
下面代碼演示了如何把該庫引入beego中從而實現(xiàn)oauth的認證,這里以github為例演示:
添加兩條路由
beego.RegisterController("/auth/login", &controllers.GithubController{})
beego.RegisterController("/mainpage", &controllers.PageController{})
然后我們處理GithubController登陸的頁面:
package controllers
import (
"github.com/astaxie/beego"
"github.com/bradrydzewski/go.auth"
)
const (
githubClientKey = "a0864ea791ce7e7bd0df"
githubSecretKey = "a0ec09a647a688a64a28f6190b5a0d2705df56ca"
)
type GithubController struct {
beego.Controller
}
func (this *GithubController) Get() {
// set the auth parameters
auth.Config.CookieSecret = []byte("7H9xiimk2QdTdYI7rDddfJeV")
auth.Config.LoginSuccessRedirect = "/mainpage"
auth.Config.CookieSecure = false
githubHandler := auth.Github(githubClientKey, githubSecretKey)
githubHandler.ServeHTTP(this.Ctx.ResponseWriter, this.Ctx.Request)
}
處理登陸成功之后的頁面
package controllers
import (
"github.com/astaxie/beego"
"github.com/bradrydzewski/go.auth"
"net/http"
"net/url"
)
type PageController struct {
beego.Controller
}
func (this *PageController) Get() {
// set the auth parameters
auth.Config.CookieSecret = []byte("7H9xiimk2QdTdYI7rDddfJeV")
auth.Config.LoginSuccessRedirect = "/mainpage"
auth.Config.CookieSecure = false
user, err := auth.GetUserCookie(this.Ctx.Request)
//if no active user session then authorize user
if err != nil || user.Id() == "" {
http.Redirect(this.Ctx.ResponseWriter, this.Ctx.Request, auth.Config.LoginRedirect, http.StatusSeeOther)
return
}
//else, add the user to the URL and continue
this.Ctx.Request.URL.User = url.User(user.Id())
this.Data["pic"] = user.Picture()
this.Data["id"] = user.Id()
this.Data["name"] = user.Name()
this.TplNames = "home.tpl"
}
整個的流程如下,首先打開瀏覽器輸入地址:
整個的流程如下,首先打開瀏覽器輸入地址:
圖14.4 顯示帶有登錄按鈕的首頁
然后點擊鏈接出現(xiàn)如下界面:
圖14.5 點擊登錄按鈕后顯示github的授權(quán)頁
然后點擊Authorize app就出現(xiàn)如下界面:
圖14.6 授權(quán)登錄之后顯示的獲取到的github信息頁
自定義的認證一般都是和session結(jié)合驗證的,如下代碼來源于一個基于beego的開源博客:
//登陸處理
func (this *LoginController) Post() {
this.TplNames = "login.tpl"
this.Ctx.Request.ParseForm()
username := this.Ctx.Request.Form.Get("username")
password := this.Ctx.Request.Form.Get("password")
md5Password := md5.New()
io.WriteString(md5Password, password)
buffer := bytes.NewBuffer(nil)
fmt.Fprintf(buffer, "%x", md5Password.Sum(nil))
newPass := buffer.String()
now := time.Now().Format("2006-01-02 15:04:05")
userInfo := models.GetUserInfo(username)
if userInfo.Password == newPass {
var users models.User
users.Last_logintime = now
models.UpdateUserInfo(users)
//登錄成功設(shè)置session
sess := globalSessions.SessionStart(this.Ctx.ResponseWriter, this.Ctx.Request)
sess.Set("uid", userInfo.Id)
sess.Set("uname", userInfo.Username)
this.Ctx.Redirect(302, "/")
}
}
//注冊處理
func (this *RegController) Post() {
this.TplNames = "reg.tpl"
this.Ctx.Request.ParseForm()
username := this.Ctx.Request.Form.Get("username")
password := this.Ctx.Request.Form.Get("password")
usererr := checkUsername(username)
fmt.Println(usererr)
if usererr == false {
this.Data["UsernameErr"] = "Username error, Please to again"
return
}
passerr := checkPassword(password)
if passerr == false {
this.Data["PasswordErr"] = "Password error, Please to again"
return
}
md5Password := md5.New()
io.WriteString(md5Password, password)
buffer := bytes.NewBuffer(nil)
fmt.Fprintf(buffer, "%x", md5Password.Sum(nil))
newPass := buffer.String()
now := time.Now().Format("2006-01-02 15:04:05")
userInfo := models.GetUserInfo(username)
if userInfo.Username == "" {
var users models.User
users.Username = username
users.Password = newPass
users.Created = now
users.Last_logintime = now
models.AddUser(users)
//登錄成功設(shè)置session
sess := globalSessions.SessionStart(this.Ctx.ResponseWriter, this.Ctx.Request)
sess.Set("uid", userInfo.Id)
sess.Set("uname", userInfo.Username)
this.Ctx.Redirect(302, "/")
} else {
this.Data["UsernameErr"] = "User already exists"
}
}
func checkPassword(password string) (b bool) {
if ok, _ := regexp.MatchString("^[a-zA-Z0-9]{4,16}$", password); !ok {
return false
}
return true
}
func checkUsername(username string) (b bool) {
if ok, _ := regexp.MatchString("^[a-zA-Z0-9]{4,16}$", username); !ok {
return false
}
return true
}
有了用戶登陸和注冊之后,其他模塊的地方可以增加如下這樣的用戶是否登陸的判斷:
func (this *AddBlogController) Prepare() {
sess := globalSessions.SessionStart(this.Ctx.ResponseWriter, this.Ctx.Request)
sess_uid := sess.Get("userid")
sess_username := sess.Get("username")
if sess_uid == nil {
this.Ctx.Redirect(302, "/admin/login")
return
}
this.Data["Username"] = sess_username
}
Copyright©2021 w3cschool編程獅|閩ICP備15016281號-3|閩公網(wǎng)安備35020302033924號
違法和不良信息舉報電話:173-0602-2364|舉報郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號
聯(lián)系方式:
更多建議: