本文同步發表於: Sponge Records
由於 API 成功被前端與分析端所使用,因此我們繼續設計會員系統的 API,本文將會實作更改密碼的功能,來讓使用者可以更換密碼,強化資安防護
這裡會將架構分為 main.go 、 controllers\accountsControllers.go 、 models\accounts.go,透過 main.go 的路由呼叫 accountsControllers.go 再透過 accounts.go 執行邏輯判斷與實作
在 main.go 中增加修改密碼的路由
//修改密碼 api
router.HandleFunc("/api/user/editor", controllers.EditorAccount).Methods("POST")
我們將會實作 controllers\accountsControllers.go 中的 EditorAccount,透過這個函數先解讀 json 格式的請求,並且驗證正確性,驗證完成後 call models\accounts.go 做事
controllers\accountsControllers.go
package controllers
import (
"net/http"
"encoding/json"
"golang-api/models"
u "golang-api/utils"
)
//修改密碼的函數
var EditorAccount = func(w http.ResponseWriter, r *http.Request) {
account := &models.Account{} //引用 accounts.go
err := json.NewDecoder(r.Body).Decode(account)//解析傳入的 json 請求
//如果輸入的請求錯誤
if err != nil {
u.Respond(w, u.Message(false, "Invalid request"))
return
}
resp := account.Editor() //呼叫 accounts.go 透過傳入的資料刪除帳號
u.Respond(w, resp)
}
我們將主要的邏輯放置在這裡,models\accounts.go 會包含驗證輸入的舊密碼是否正確,新密碼是否符合長度要求
models\accounts.go
package models
import (
u "golang-api/utils" // 開頭的 u 代表用 u 來引用他
"os"
"strings"
"github.com/dgrijalva/jwt-go"
"github.com/jinzhu/gorm"
"golang.org/x/crypto/bcrypt"
)
//JWT 結構
type Token struct {
UserId uint
jwt.StandardClaims
}
//帳號結構
type Account struct {
gorm.Model
Email string `json:"email"`
Password string `json:"Password"`
Token string `json:"token";sql:"-"`
}
//密碼修改
func Editor(email, oldPassword, newPassword string) (map[string]interface{}) {
//如果密碼小於8位數,回傳帳號格式錯誤
if len(oldPassword) < 8 && len(newPassword) < 8 {
return u.Message(false, "Password format error"), false
}
//帳號驗證
err := GetDB().Table("accounts").Where("email = ?", email).First(account).Error
if err != nil {
if err == gorm.ErrRecordNotFound {
return u.Message(false, "Email address not found")
}
return u.Message(false, "Connection error")
}
//舊密碼驗證
err = bcrypt.CompareHashAndPassword([]byte(oldPassword), []byte(password))
if err != nil && err == bcrypt.ErrMismatchedHashAndPassword {
return u.Message(false, "pwd error")
}
hashedPassword, _ := bcrypt.GenerateFromPassword([]byte(newPassword), bcrypt.DefaultCost)
account.Password = string(hashedPassword)
//保存
GetDB().Save(account)
//清空 pwd 的數值以便回傳
account.Password = ""
//修改完成
response := u.Message(true, "Account has been editor")
response["account"] = account
return response
}
下回將進行會員帳號停用的功能,模擬使用者將自己的帳號停用的情景