目錄
- 圖形化驗證碼生成和驗證
- 項目集成驗證碼生成和Redis緩存
- 用戶名密碼登錄功能開發(fā)
- 登錄流程編程實現(xiàn)
圖形化驗證碼生成和驗證
功能介紹
在使用用戶名和密碼登錄功能時,需要填寫驗證碼,驗證碼是以圖形化的方式進(jìn)行獲取和展示的。
驗證碼使用原理
驗證碼的使用流程和原理為:在服務(wù)器端負(fù)責(zé)生成圖形化驗證碼,并以數(shù)據(jù)流的形式供前端訪問獲取,同時將生成的驗證碼存儲到全局的緩存中,在本案例中,我們使用redis作為全局緩存,并設(shè)置緩存失效時間。當(dāng)用戶使用用戶名和密碼進(jìn)行登錄時,進(jìn)行驗證碼驗證。驗證通過即可繼續(xù)進(jìn)行登錄。
驗證碼庫安裝
借助開源的驗證碼工具庫可以生成驗證碼。
首先,安裝開源的驗證碼生成庫:
go get -u github.com/mojocn/base64Captcha
go get github.com/mojocn/base64Captcha@v1.2.2
驗證碼代碼示例
在下載后的base64Captcha庫的目錄中,可以看到有_example和_example_redis兩個目錄。第一個example是用于演示生成驗證碼和驗證碼的示例代碼。
按照示例代碼的說明,運(yùn)行程序并在瀏覽器進(jìn)行端口訪問:
go run main.go
//瀏覽器中訪問:http://localhost:8777
如下圖所示:
通過自定義配置,可以選擇不同的生成驗證碼的參數(shù),并刷新驗證碼,同時還可以對驗證碼進(jìn)行驗證。
通過exmaple目錄下的main.go程序可以看到生成驗證碼和驗證驗證碼的邏輯,此處不再贅述。
項目集成驗證碼生成和Redis緩存
通常來說,驗證碼都是有一定的實效性的,過期驗證碼也就無效了。
因此,我們考慮在項目中引入Redis作為數(shù)據(jù)緩存。當(dāng)驗證碼生成后,將驗證碼存放在Redis中,并根據(jù)配置文件對Redis進(jìn)行設(shè)置。
安裝go-redis庫
在項目中使用redis,需要安裝go-redis庫,可以在https://github.com/go-redis/redis中查看如何下載go-redis和配置。
增加Redis配置
在配置文件app.json中新增redis配置:
"redis_config": {
"addr": "127.0.0.1",
"port": "6379",
"password": "",
"db": 0
}
同時,新增RedisConfig結(jié)構(gòu)體定義,如下所示:
type RedisConfig struct {
Addr string `json:"addr"`
Port string `json:"port"`
Password string `json:"password"`
Db int `json:"db"`
}
Redis初始化操
進(jìn)行了redis配置以后,需要對redis進(jìn)行初始化。可以封裝redis初始化操作函數(shù)如下所示:
type RedisStore struct {
redisClient *redis.Client
}
var Redis *redis.Client
func InitRediStore() *RedisStore {
config := GetConfig().RedistConfig
Redis = redis.NewClient(redis.Options{
Addr: config.Addr + ":" + config.Port,
Password: config.Password,
DB: config.Db,
})
customeStore := RedisStore{Redis}
base64Captcha.SetCustomStore(customeStore)
return customeStore
}
同時,為customeStore提供Set和Get兩個方法,如下所示:
func (cs *RedisStore) Set(id string, value string) {
err := cs.redisClient.Set(id, value, time.Minute*2).Err()
if err != nil {
log.Println(err.Error())
}
}
func (cs *RedisStore) Get(id string, clear bool) string {
val, err := cs.redisClient.Get(id).Result()
if err != nil {
toolbox.Error(err.Error())
return ""
}
if clear {
err := cs.redisClient.Del(id).Err()
if err != nil {
toolbox.Error(err.Error())
return ""
}
}
return val
}
對Redis進(jìn)行初始化和定義完成以后,需要在main中調(diào)用一下初始化操作InitRediStore:
func main(){
...
//Redis配置初始化
toolbox.InitRediStore()
...
}
驗證碼生成和驗證
本項目中采用的驗證碼的生成庫支持三種驗證碼,分別是:audio,character和digit。我們選擇character類型。
定義Captcha.go文件,實現(xiàn)驗證碼的生成和驗證碼函數(shù)的定義。在進(jìn)行驗證碼生成時,默認(rèn)提供驗證碼的配置,并生成驗證碼后返回給客戶端瀏覽器。如下是生成驗證碼的函數(shù)定義:
//生成驗證碼
func GenerateCaptchaHandler(ctx *gin.Context) {
//圖形驗證碼的默認(rèn)配置
parameters := base64Captcha.ConfigCharacter{
Height: 60,
Width: 240,
Mode: 3,
ComplexOfNoiseText: 0,
ComplexOfNoiseDot: 0,
IsUseSimpleFont: true,
IsShowHollowLine: false,
IsShowNoiseDot: false,
IsShowNoiseText: false,
IsShowSlimeLine: false,
IsShowSineLine: false,
CaptchaLen: 4,
BgColor: color.RGBA{
R: 3,
G: 102,
B: 214,
A: 254,
},
}
captchaId, captcaInterfaceInstance := base64Captcha.GenerateCaptcha("", parameters)
base64blob := base64Captcha.CaptchaWriteToBase64Encoding(captcaInterfaceInstance)
captchaResult := CaptchaResult{Id: captchaId, Base64Blob: base64blob}
// 設(shè)置json響應(yīng)
tool.Success(ctx, map[string]interface{}{
"captcha_result": captchaResult,
})
}
驗證碼接口解析
圖形化驗證碼是用戶名和密碼登錄功能的數(shù)據(jù),屬于Member模塊。因此在MemberController中增加獲取驗證碼的接口解析,如下:
func (mc *MemberController) Router(engine *gin.Engine){
//獲取驗證碼
engine.GET("/api/captcha", mc.captcha)
}
測試結(jié)果如下,能夠正常獲取到數(shù)據(jù):
驗證碼的驗證
同理,可以對客戶端提交的驗證碼進(jìn)行驗證,具體實現(xiàn)邏輯如下:
//驗證驗證碼是否正確
func CaptchaVerify(r *http.Request) bool {
var captchaResult CaptchaResult
//接收客戶端發(fā)送來的請求參數(shù)
decoder := json.NewDecoder(r.Body)
err := decoder.Decode(captchaResult)
if err != nil {
log.Println(err)
}
defer r.Body.Close()
//比較圖像驗證碼
verifyResult := base64Captcha.VerifyCaptcha(captchaResult.Id, captchaResult.VertifyValue)
return verifyResult
}
用戶名密碼登錄功能開發(fā)
功能介紹
上節(jié)課已經(jīng)完成了驗證碼的生成,本節(jié)課來開發(fā)用戶名、密碼和驗證碼登錄功能。
接口和參數(shù)解析定義
用戶名和密碼的登錄接口為:
接口請求類型為POST,接口參數(shù)有三個:name,pwd,captcha。其中:captcha為驗證碼。
定義登錄參數(shù)結(jié)構(gòu)體LoginParam:
//用戶名,密碼和驗證碼登錄
type LoginParam struct {
Name string `json:"name"` //用戶名
Password string `json:"pwd"` //密碼
Id string `json:"id"`// captchaId 驗證碼ID
Value string `json:"value"` //驗證碼
}
邏輯控制層實現(xiàn)登錄流程控制
方法解析
在MemberController.go文件中,編寫方法用于處理用戶名密碼登錄的解析方法如下所示:
func (mc *MemberController) Router(engine *gin.Engine){
engine.POST("/api/login_pwd", mc.nameLogin)
}
登錄流程編程實現(xiàn)
定義新的func并命名為nameLogin,實現(xiàn)登錄流程邏輯控制:
//用戶名、密碼登錄
func (mc *MemberController) nameLogin(context *gin.Context) {
//1、登錄參數(shù)解析
var loginParam param.LoginParam
err := toolbox.Decode(context.Request.Body, loginParam)
if err != nil {
toolbox.Failed(context, "參數(shù)解析失敗")
return
}
//2、驗證驗證碼
service := impl.NewMemberService()
validate := toolbox.CaptchaVerify(loginParam.Id, loginParam.Value)
fmt.Println(validate)
if !validate {
toolbox.ValidateFailed(context, "驗證碼不正確, 請重新驗證 ")
return
}
//3、登錄
member := service.Login(loginParam.Name, loginParam.Password)
if member.Id == 0 {
toolbox.Failed(context, "登錄失敗")
return
}
toolbox.Success(context, member)
}
在控制層的nameLogin方法中,主要有3個邏輯處理:
- 1、通過*gin.Context解析請求登錄請求攜帶的參數(shù)。
- 2、從攜帶的參數(shù)中得到提交的驗證碼數(shù)據(jù),調(diào)用驗證碼判斷驗證碼方法對驗證碼進(jìn)行判斷。驗證碼驗證失敗或者驗證碼失效,直接返回登錄失敗信息。
- 3、使用用戶名、密碼參數(shù)進(jìn)行登錄,判斷登錄結(jié)果。如果登錄成功,返回用戶登錄信息,否則返回登錄失敗。
Service層實現(xiàn)
在功能服務(wù)層的MemberService文件中,定義和實現(xiàn)用戶名密碼登錄的Login方法。詳細(xì)實現(xiàn)如下:
//用戶登錄: 如果沒有登錄過,自動進(jìn)行登錄
func (msi *MemberServiceImpl) Login(name string, password string) *model.Member {
dao := impl.NewMemberDao()
//1、先查詢是否已經(jīng)存在該用戶
member := dao.Query(name, password)
if member.Id != 0 {
return member
}
user := model.Member{}
user.UserName = name
user.Password = toolbox.EncoderSha256(password)
user.RegisterTime = time.Now().Unix()
result := dao.InsertMember(user)
user.Id = result
return user
}
在service層的Login方法中,分為兩步邏輯判斷:
1、先查詢是否已經(jīng)存在該用戶,如果該用于已經(jīng)存在,則直接將查詢到的用戶信息返回。
2、如果用戶不存在,將用戶信息作為新記錄保存到數(shù)據(jù)庫中,新增一條記錄。并返回用戶信息。
最后,涉及到操作數(shù)據(jù)庫的兩個方法分別是:Query和InsertMember方法。InsertMember方法之前已經(jīng)編寫過,只需要重新編寫一個Query方法即可,Query方法實現(xiàn)如下所示:
//根據(jù)用戶名和密碼查詢用戶記錄
func (mdi *MemberDaoImpl) Query(name string, password string) *model.Member {
var member model.Member
password = toolbox.EncoderSha256(password)
_, err := mdi.Where(" user_name = ? and password = ? ", name, password).Get(member)
if err != nil {
toolbox.Error(err.Error())
return nil
}
return member
}
到此這篇關(guān)于Go+Vue開發(fā)一個線上外賣應(yīng)用(用戶名密碼和圖形驗證碼)的文章就介紹到這了,更多相關(guān)Go線上外賣內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
您可能感興趣的文章:- vue實現(xiàn)驗證用戶名是否可用
- vue+element-ui集成隨機(jī)驗證碼+用戶名+密碼的form表單驗證功能
- Vue驗證用戶名是否可用的方法