Registered interface

  • To check submission data is complete, mandatory fields must be filled in
  • Check whether the submitted data exists (user name, mobile phone number)
  • Submit password sensitive information for encryption
  • The ID is generated using the snowflake algorithm
  • Confirm the password twice and check whether the password is the same
  • Table design User information and passwords are stored in different tables. Associate the password table with the user userId
  • You need to send the SMS verification code and submit the information to the server to verify whether the verification code is valid
  • Because the interface does not require authorization to access, frequent access needs to be blocked
  • .

Add a registered route

account_controller.go

type AccountController struct{}

func (ac *AccountController) RegisterRouter(app *gin.Engine) {
	group := app.Group("/api/v1/account")
	group.POST("/register", ac.Register)
	
	// TODO: login interface 
	group.POST("/login", ac.Login)
}

func (ac *AccountController) Register(c *gin.Context) {
	var registerInfo model.RegisterInfo
	iferr := c.BindJSON(&registerInfo); err ! =nil {
		common.Failed(c, api.ParseParamCode, err.Error())
		return
	}
	log.Printf("receiver param %s", registerInfo)
	accountService := service.AccountService{}
	accountService.AddUser(&registerInfo)
	common.Success(c, 1)}Copy the code
  • The submitted data is in JSON format
  • Data binding API BindJSON is provided using GIN to bind mapped data to the RegisterInfo structure
  • The AccountService provides the AddUser method for business logic processing

register_info.go

package model

type RegisterInfo struct {
	UserName    string `form:"userName" json:"userName" binding:"required"`
	Password    string `form:"password" json:"password" binding:"required"`
	RePassword  string `form:"rePassword" json:"rePassword" binding:"required"`
	Phone       string `form:"phone" json:"phone" binding:"required"`
	SmsCode     string `form:"smsCode" json:"smsCode" binding:"required"`
	Gender      string `form:"gender" json:"gender"`
	Avatar      string `form:"avatar" json:"avatar"`
	Email       string `form:"email" json:"email"`
	Job         string `form:"job" json:"job"`
	Address     string `form:"address" json:"address"`
	Description string `form:"description" json:"description"`
}

Copy the code
  • Define the RegisterInfo structure
  • Binding :” Required “is used for any data that must be filled in. The BindJSON method validates the submission to the interface.

account_service.go

type AccountService struct{}

func (us *AccountService) AddUser(registerInfo *model.RegisterInfo) {
	password := registerInfo.Password
	repassword := registerInfo.RePassword

	if! strings.EqualFold(password, repassword) { api.NewException(api.PasswordInconsistencyCode) } worker, err := util.NewWorker(16)
	iferr ! =nil {
		log.Print(err)
		api.NewException(api.AddUserFailCode)
	}

	userDao := dao.UserDao{DbEngine: engine.GetOrmEngine()}

	// check user info
	checkUserInfo(registerInfo)

	userInfo := &model.UserInfo{
		UserName:    registerInfo.UserName,
		UserId:      strconv.FormatInt(worker.GetId(), 10),
		Gender:      registerInfo.Gender,
		Phone:       registerInfo.Phone,
		Avatar:      registerInfo.Avatar,
		Email:       registerInfo.Email,
		Address:     registerInfo.Address,
		Description: registerInfo.Description,
	}
	result, err := userDao.InsertUser(userInfo)
	log.Printf("add user result %d error %s", result, err)
	iferr ! =nil {
		panic(api.NewException(api.AddUserFailCode))
	}

	passwordInfo := &model.Password{
		PwdId:  strconv.FormatInt(worker.GetId(), 10),
		UserId: userInfo.UserId,
		Pwd:    util.CryptoSha1(password),
	}
	result, err = userDao.InsertPassword(passwordInfo)
	log.Printf("add password result %d error %s", result, err)
	iferr ! =nil {
		panic(api.NewException(api.AddUserFailCode))
	}
}

func checkUserInfo(registerInfo *model.RegisterInfo) {
	userDao := dao.UserDao{DbEngine: engine.GetOrmEngine()}
	exist, err := userDao.QueryByPhone(registerInfo.Phone)
	log.Printf("check Phone %v %v", exist, err)
	if exist {
		panic(api.NewException(api.PhoneExistCode))
	}

	exist, err = userDao.QueryByUserName(registerInfo.UserName)
	log.Printf("check UserName %v %v", exist, err)
	if exist {
		panic(api.NewException(api.UserNameExistCode))
	}
}
Copy the code
  • Strings. EqualFold(password, repassword) performs password comparison
  • Use worker, err := util.newworker (16) to generate the snowflake ID
  • Util.CryptoSha1 Uses the SHA1 algorithm to encrypt passwords
  • Check user information from the chckUserInfo database
  • After checking the data, perform data landing and save the user information and password to the database respectively

password.go

package model

type Password struct {
	PwdId  string `xorm:"pwd_id"`
	UserId string `xorm:"user_id"`
	Pwd    string `xorm:"pwd"`
}

Copy the code
  • User_id Associated user table

Password encryption

  • In the GO language, there are many encryption algorithms that can be used to encrypt

  • Sha1 encryption
package util

import (
	"crypto/sha1"

	"encoding/hex"
)

func CryptoSha1(s string) string {
	s1 := sha1.New()
	s1.Write([]byte(s))
	return hex.EncodeToString(s1.Sum(nil))}Copy the code

TODO:

Send a text message

  • You can use the third-party SMS service to send SMS messages through API, save the SMS verification code in Redis, and set the expiration time, which is valid within XXX minutes
  • Obtain the SMS verification code and mobile phone number from the submitted data, and save the verification code from the Reids for comparison

The interface current limiting

  • Gin middleware can be used to limit the flow of IP acquisition methods
  • The project is deployed to the server with the ngx_HTTP_limit_req_module configuration using Nginx