当前位置:网站首页>15、用户web层服务(三)
15、用户web层服务(三)
2022-07-28 11:13:00 【无休止符】
一、图形验证码
1 - 生成图片验证码
- 官方地址: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("生成验证码错误,: ", err.Error())
ctx.JSON(http.StatusInternalServerError, gin.H{
"msg": "生成验证码错误",
})
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()
//配置跨域
Router.Use(middlewares.Cors())
ApiGroup := Router.Group("/u/v1")
router.InitUserRouter(ApiGroup)
router.InitBaseRouter(ApiGroup)
return Router
}

- 在线转换查看base64图片:https://www.qvdv.net/tools/qvdv-img2base64.html

2 - 登录添加图片验证码
- user_web\forms\form_user.go
package forms
type PassWordLoginForm struct {
Mobile string `form:"mobile" json:"mobile" binding:"required,mobile"` //手机号码格式有规范可寻, 自定义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) {
//表单验证
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": "验证码错误",
})
return
}
//...省略

二、用户注册
1 - docker安装redis
- 参考地址:https://blog.csdn.net/qq23001186/article/details/126023939
- redis的go驱动:https://github.com/go-redis/redis
2 - 阿里云短信验证码
- user_web\forms\form_sms.go
package forms
type SendSmsForm struct {
Mobile string `form:"mobile" json:"mobile" binding:"required,mobile"` // 手机号码格式有规范可寻, 自定义validator
Type uint `form:"type" json:"type" binding:"required,oneof=1 2"` // 注册发送短信验证码和动态验证码登录发送验证码
}
- 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 {
//生成width长度的短信验证码
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 //手机号
request.QueryParams["SignName"] = "慕学在线" //阿里云验证过的项目名 自己设置
request.QueryParams["TemplateCode"] = "SMS_181850725" //阿里云的短信模板号 自己设置
request.QueryParams["TemplateParam"] = "{\"code\":" + smsCode + "}" //短信模板中的验证码内容 自己生成 之前试过直接返回,但是失败,加上code成功。
response, err := client.ProcessCommonRequest(request)
fmt.Print(client.DoAction(request, response))
if err != nil {
fmt.Print(err.Error())
}
//将验证码保存起来 - 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": "发送成功",
})
}
- yaml:隐私原因key和secret未配置
//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'
三、用户注册接口
- user_web\forms\form_user.go
package forms
type PassWordLoginForm struct {
Mobile string `form:"mobile" json:"mobile" binding:"required,mobile"` //手机号码格式有规范可寻, 自定义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"` //手机号码格式有规范可寻, 自定义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) {
//用户注册
registerForm := forms.RegisterForm{
}
if err := c.ShouldBind(®isterForm); err != nil {
HandleValidatorError(c, err)
return
}
//验证码
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": "验证码错误",
})
return
} else {
if value != registerForm.Code {
c.JSON(http.StatusBadRequest, gin.H{
"code": "验证码错误",
})
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] 查询 【新建用户失败】失败: %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(), //签名的生效时间
ExpiresAt: time.Now().Unix() + 60*60*24*30, //30天过期
Issuer: "imooc",
},
}
token, err := j.CreateToken(claims)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{
"msg": "生成token失败",
})
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()) //给整个user都添加登录验证
zap.S().Info("配置用户相关的url")
{
UserRouter.GET("list", middlewares.JWTAuth(), middlewares.IsAdminAuth(), api.GetUserList)
UserRouter.POST("pwd_login", api.PassWordLogin)
UserRouter.POST("register", api.Register)
}
}
- YApi配置注册接口

四、完整源码
边栏推荐
- [cesium] entity property and timing binding: the sampledproperty method is simple to use
- How to use JWT for authentication and authorization
- 「以云为核,无感极速」第五代验证码重磅来袭
- MySQL离线同步到odps的时候 可以配置动态分区吗
- Cvpr2020 best paper: unsupervised learning of symmetric deformable 3D objects
- 目标检测领域必看的6篇论文
- 学会使用MySQL的Explain执行计划,SQL性能调优从此不再困难
- Guys, ask me, this can't be checkpoint, because there is a JDBC task whose task status is finished,
- Google Earth engine - use geetool to download single scene images in batches and retrieve NDSI results with Landsat 8
- R language uses LM function to build regression model and regression model for transformed data (for example, it is necessary to build regression model for X and y, but they have no linear relationshi
猜你喜欢

Five Ali technical experts have been offered. How many interview questions can you answer

WPF layout controls are scaled up and down with the window, which is suitable for multi-resolution full screen filling applications
![Full version of H5 social chat platform source code [complete database + complete document tutorial]](/img/3f/03239c1b4d6906766348d545a4f234.png)
Full version of H5 social chat platform source code [complete database + complete document tutorial]

Localization, low latency, green and low carbon: Alibaba cloud officially launched Fuzhou data center

天狼星网络验证源码/官方正版/内附搭建教程
![[pyGame practice] when the end of the world comes, how long can you live in a cruel survival game that really starts from scratch?](/img/2b/1eb02249ab9ad0b4e1bfeeee87418c.png)
[pyGame practice] when the end of the world comes, how long can you live in a cruel survival game that really starts from scratch?

A lock faster than read-write lock. Don't get to know it quickly

Three methods of using unity mouse to drive objects

Are interviews all about memorizing answers?

CVPR2021 行人重识别/Person Re-identification 论文+开源代码汇总
随机推荐
Digital twin rail transit: "intelligent" monitoring to clear the pain points of urban operation
STL の 概念及其应用
Service Workers让网站动态加载Webp图片
MySQL (version 8.0.16) command and description
[pyGame practice] when the end of the world comes, how long can you live in a cruel survival game that really starts from scratch?
R language uses dplyr package group_ By function and summarize function calculate the mean value of all covariates involved in the analysis based on grouped variables (difference in means of covariate
CVPR2020 best paper:对称可变形三维物体的无监督学习
Understand how to prevent tampering and hijacking of device fingerprints
Random talk on GIS data (V) - geographic coordinate system
Jupiter、spyder、Anaconda Prompt 、navigator 快捷键消失的解决办法
一种比读写锁更快的锁,还不赶紧认识一下
【补题日记】[2022牛客暑期多校2]L-Link with Level Editor I
对话庄表伟:开源第一课
Object to object mapping -automapper
Using C language to realize bidirectional linked list
AlexNet—论文分析及复现
Embrace open source guidelines
MySQL离线同步到odps的时候 可以配置动态分区吗
js代码如何被浏览器引擎编译执行的?
业务可视化-让你的流程图'Run'起来(4.实际业务场景测试)