当前位置:网站首页>15. User web layer services (III)
15. User web layer services (III)
2022-07-28 11:48:00 【Endless character】
Catalog
One 、 Graphic verification code
1 - Generate image captcha
- Official address :https://mojotv.cn/go/refactor-base64-captcha
- user_web\api\chaptcha.go
package api
import (
"net/http"
"github.com/gin-gonic/gin"
"github.com/mojocn/base64Captcha"
"go.uber.org/zap"
)
var store = base64Captcha.DefaultMemStore
func GetCaptcha(ctx *gin.Context) {
driver := base64Captcha.NewDriverDigit(80, 240, 5, 0.7, 80)
cp := base64Captcha.NewCaptcha(driver, store)
id, b64s, err := cp.Generate()
if err != nil {
zap.S().Errorf(" Error generating verification code ,: ", err.Error())
ctx.JSON(http.StatusInternalServerError, gin.H{
"msg": " Error generating verification code ",
})
return
}
ctx.JSON(http.StatusOK, gin.H{
"captchaId": id,
"picPath": b64s,
})
}
- user_web\router\router_base.go
package router
import (
"github.com/gin-gonic/gin"
"web_api/user_web/api"
)
func InitBaseRouter(Router *gin.RouterGroup) {
BaseRouter := Router.Group("base")
{
BaseRouter.GET("captcha", api.GetCaptcha)
}
}
- user_web\initialize\init_router.go
package initialize
import (
"github.com/gin-gonic/gin"
"web_api/user_web/middlewares"
"web_api/user_web/router"
)
func Routers() *gin.Engine {
Router := gin.Default()
// Configure cross domain
Router.Use(middlewares.Cors())
ApiGroup := Router.Group("/u/v1")
router.InitUserRouter(ApiGroup)
router.InitBaseRouter(ApiGroup)
return Router
}

- Online conversion view base64 picture :https://www.qvdv.net/tools/qvdv-img2base64.html

2 - Login and add image verification code
- user_web\forms\form_user.go
package forms
type PassWordLoginForm struct {
Mobile string `form:"mobile" json:"mobile" binding:"required,mobile"` // There are specifications for the format of mobile phone numbers , Customize validator
PassWord string `form:"password" json:"password" binding:"required,min=3,max=20"`
Captcha string `form:"captcha" json:"captcha" binding:"required,min=5,max=5"`
CaptchaId string `form:"captcha_id" json:"captcha_id" binding:"required"`
}
- user_web\api\api_user.go
func PassWordLogin(c *gin.Context) {
// Form validation
passwordLoginForm := forms.PassWordLoginForm{
}
if err := c.ShouldBind(&passwordLoginForm); err != nil {
HandleValidatorError(c, err)
return
}
if store.Verify(passwordLoginForm.CaptchaId, passwordLoginForm.Captcha, false) {
c.JSON(http.StatusBadRequest, gin.H{
"captcha": " Verification code error ",
})
return
}
//... Omit

Two 、 User registration
1 - docker install redis
- Reference address :https://blog.csdn.net/qq23001186/article/details/126023939
- redis Of go drive :https://github.com/go-redis/redis
2 - Alicloud SMS verification code
- user_web\forms\form_sms.go
package forms
type SendSmsForm struct {
Mobile string `form:"mobile" json:"mobile" binding:"required,mobile"` // There are specifications for the format of mobile phone numbers , Customize validator
Type uint `form:"type" json:"type" binding:"required,oneof=1 2"` // Register to send SMS verification code and dynamic verification code, login to send verification code
}
- user_web\router\router_base.go
package router
import (
"github.com/gin-gonic/gin"
"web_api/user_web/api"
)
func InitBaseRouter(Router *gin.RouterGroup) {
BaseRouter := Router.Group("base")
{
BaseRouter.GET("captcha", api.GetCaptcha)
BaseRouter.POST("send_sms", api.SendSms)
}
}
- user_web\api\sms.go
package api
import (
"context"
"fmt"
"math/rand"
"net/http"
"strings"
"time"
"web_api/user_web/forms"
"github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests"
"github.com/aliyun/alibaba-cloud-sdk-go/services/dysmsapi"
"github.com/gin-gonic/gin"
"github.com/go-redis/redis/v8"
"web_api/user_web/global"
)
func GenerateSmsCode(witdh int) string {
// Generate width Length of SMS verification code
numeric := [10]byte{
0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
r := len(numeric)
rand.Seed(time.Now().UnixNano())
var sb strings.Builder
for i := 0; i < witdh; i++ {
fmt.Fprintf(&sb, "%d", numeric[rand.Intn(r)])
}
return sb.String()
}
func SendSms(ctx *gin.Context) {
sendSmsForm := forms.SendSmsForm{
}
if err := ctx.ShouldBind(&sendSmsForm); err != nil {
HandleValidatorError(ctx, err)
return
}
client, err := dysmsapi.NewClientWithAccessKey("cn-beijing", global.ServerConfig.AliSmsInfo.ApiKey, global.ServerConfig.AliSmsInfo.ApiSecrect)
if err != nil {
panic(err)
}
smsCode := GenerateSmsCode(6)
request := requests.NewCommonRequest()
request.Method = "POST"
request.Scheme = "https" // https | http
request.Domain = "dysmsapi.aliyuncs.com"
request.Version = "2017-05-25"
request.ApiName = "SendSms"
request.QueryParams["RegionId"] = "cn-beijing"
request.QueryParams["PhoneNumbers"] = sendSmsForm.Mobile // cell-phone number
request.QueryParams["SignName"] = " Mu Xue online " // Alibaba cloud verified project name Set up your own
request.QueryParams["TemplateCode"] = "SMS_181850725" // Alibaba cloud's SMS template number Set up your own
request.QueryParams["TemplateParam"] = "{\"code\":" + smsCode + "}" // Verification code content in SMS template Make your own I tried to return directly before , But it failed , add code success .
response, err := client.ProcessCommonRequest(request)
fmt.Print(client.DoAction(request, response))
if err != nil {
fmt.Print(err.Error())
}
// Save the verification code - redis
rdb := redis.NewClient(&redis.Options{
Addr: fmt.Sprintf("%s:%d", global.ServerConfig.RedisInfo.Host, global.ServerConfig.RedisInfo.Port),
})
rdb.Set(context.Background(), sendSmsForm.Mobile, smsCode, time.Duration(global.ServerConfig.RedisInfo.Expire)*time.Second)
ctx.JSON(http.StatusOK, gin.H{
"msg": " Send successfully ",
})
}
- yaml: Privacy reasons key and secret Not configured
//user_web\config_debug.yaml
//user_web\config_pro.yaml
name: 'user-web'
port: '8081'
user_srv:
host: '127.0.0.1'
port: '50051'
jwt:
key: 'VYLDYq3&hGWjWqF$K1ih'
sms:
key: ''
secrect: ''
expire: 300
redis:
host: '192.168.124.51'
port: '6379'
3、 ... and 、 User registration interface
- user_web\forms\form_user.go
package forms
type PassWordLoginForm struct {
Mobile string `form:"mobile" json:"mobile" binding:"required,mobile"` // There are specifications for the format of mobile phone numbers , Customize validator
PassWord string `form:"password" json:"password" binding:"required,min=3,max=20"`
Captcha string `form:"captcha" json:"captcha" binding:"required,min=5,max=5"`
CaptchaId string `form:"captcha_id" json:"captcha_id" binding:"required"`
}
type RegisterForm struct {
Mobile string `form:"mobile" json:"mobile" binding:"required,mobile"` // There are specifications for the format of mobile phone numbers , Customize validator
PassWord string `form:"password" json:"password" binding:"required,min=3,max=20"`
Code string `form:"code" json:"code" binding:"required,min=6,max=6"`
}
- user_web\api\api_user.go
func Register(c *gin.Context) {
// User registration
registerForm := forms.RegisterForm{
}
if err := c.ShouldBind(®isterForm); err != nil {
HandleValidatorError(c, err)
return
}
// Verification Code
rdb := redis.NewClient(&redis.Options{
Addr: fmt.Sprintf("%s:%d", global.ServerConfig.RedisInfo.Host, global.ServerConfig.RedisInfo.Port),
})
value, err := rdb.Get(registerForm.Mobile).Result()
if err == redis.Nil {
c.JSON(http.StatusBadRequest, gin.H{
"code": " Verification code error ",
})
return
} else {
if value != registerForm.Code {
c.JSON(http.StatusBadRequest, gin.H{
"code": " Verification code error ",
})
return
}
}
user, err := global.UserSrvClient.CreateUser(context.Background(), &proto.CreateUserInfo{
NickName: registerForm.Mobile,
PassWord: registerForm.PassWord,
Mobile: registerForm.Mobile,
})
if err != nil {
zap.S().Errorf("[Register] Inquire about 【 New user failed 】 Failure : %s", err.Error())
HandleGrpcErrorToHttp(err, c)
return
}
j := middlewares.NewJWT()
claims := models.CustomClaims{
ID: uint(user.Id),
NickName: user.NickName,
AuthorityId: uint(user.Role),
StandardClaims: jwt.StandardClaims{
NotBefore: time.Now().Unix(), // Effective time of signature
ExpiresAt: time.Now().Unix() + 60*60*24*30, //30 Days overdue
Issuer: "imooc",
},
}
token, err := j.CreateToken(claims)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{
"msg": " Generate token Failure ",
})
return
}
c.JSON(http.StatusOK, gin.H{
"id": user.Id,
"nick_name": user.NickName,
"token": token,
"expired_at": (time.Now().Unix() + 60*60*24*30) * 1000,
})
}
- user_web\router\router_user.go
package router
import (
"web_api/user_web/api"
"web_api/user_web/middlewares"
"github.com/gin-gonic/gin"
"go.uber.org/zap"
)
func InitUserRouter(Router *gin.RouterGroup) {
UserRouter := Router.Group("user")
//UserRouter := Router.Group("user").Use(middlewares.JWTAuth()) // To the whole user Add login verification
zap.S().Info(" Configure user related url")
{
UserRouter.GET("list", middlewares.JWTAuth(), middlewares.IsAdminAuth(), api.GetUserList)
UserRouter.POST("pwd_login", api.PassWordLogin)
UserRouter.POST("register", api.Register)
}
}
- YApi Configure the registration interface

Four 、 Complete source code
边栏推荐
- Byte side: how to realize reliable transmission with UDP?
- Localization, low latency, green and low carbon: Alibaba cloud officially launched Fuzhou data center
- An example of the mandatory measures of Microsoft edge browser tracking prevention
- Shell (II)
- 拥抱开源指南
- 可视化大型时间序列的技巧。
- Shell (I)
- 从0开发一个自己的npm包
- Function of interface test
- [极客大挑战 2019]BabySQL-1|SQL注入
猜你喜欢

Digital twin rail transit: "intelligent" monitoring to clear the pain points of urban operation

A new mode of one-stop fixed asset management

Software testing and quality learning notes 1 --- black box testing

【一知半解】零值拷贝

Unity鼠标带动物体运动的三种方法

PFP会是数字藏品的未来吗?

Byte side: how to realize reliable transmission with UDP?

Six papers that must be seen in the field of target detection

Refresh your understanding of redis cluster

目标检测领域必看的6篇论文
随机推荐
R language uses LM function to build regression model, uses the augmented function of bloom package to store the model results in dataframe, and uses ggplot2 to visualize the regression residual diagr
Understand how to prevent tampering and hijacking of device fingerprints
中国业务型CDP白皮书 | 爱分析报告
Using C language to realize bidirectional linked list
多线程与高并发(三)—— 源码解析 AQS 原理
Design and implementation of SSM personal blog system
可视化大型时间序列的技巧。
Flash point list of cross platform efficiency software
Digital twin rail transit: "intelligent" monitoring to clear the pain points of urban operation
Router firmware decryption idea
R语言-用于非平衡数据集的一些度量指标
[pyGame practice] the super interesting bubble game is coming - may you be childlike and always happy and simple~
Install SSL Certificate in Litespeed web server
Open source huizhichuang future | 2022 open atom global open source summit openatom openeuler sub forum was successfully held
PFP会是数字藏品的未来吗?
The fifth generation verification code of "cloud centered, insensitive and extremely fast" is coming heavily
Top ten application development trends from 2022 to 2023
拥抱开源指南
STL の 概念及其应用
Anonymous subclass objects of abstract classes