This is the 25th day of my participation in the November Gwen Challenge. Check out the event details: The last Gwen Challenge 2021

1. Register routes

  • Define a user login route
v1.POST("user/login", api.UserLogin)
Copy the code

2. Interface writing

2.1 the service layer

  • Define the service structure for user login
//UserLoginService Manages the login service of users
type UserLoginService struct {
	UserName  string `form:"user_name" json:"user_name" binding:"required,min=5,max=15"`
	Password  string `form:"password" json:"password" binding:"required,min=8,max=16"`
}
Copy the code
  • Write service methods for user login
func (service *UserLoginService) Login(a) serializer.Response{... }Copy the code

2.2 the API layer

  • Define the service to which the user logs in
var userLoginService service.UserLoginService
Copy the code
  • Data binding
c.ShouldBind(&userLoginService)
Copy the code
  • Run the login method of the userLoginService object
res := userLoginService.Login()
Copy the code
  • The interface function for user login is returned
c.JSON(200, res)
Copy the code
  • The complete code for the user login interface
func UserLogin(c *gin.Context) {
	var userLoginService service.UserLoginService
	if err := c.ShouldBind(&userLoginService); err == nil {
		res := userLoginService.Login()
		c.JSON(200, res)
	} else {
		c.JSON(400, ErrorResponse(err))
		logging.Info(err)
	}
}
Copy the code

2.3 the service

  • Query whether the user exists
	if err := model.DB.Where("user_name=?", service.UserName).First(&user).Error; err ! =nil {
		// If no query is found, an error is returned
		if gorm.IsRecordNotFoundError(err) {
			logging.Info(err)
			code = e.ErrorNotExistUser
			return serializer.Response{
				Status: code,
				Msg:    e.GetMsg(code),
			}
		}
		logging.Info(err)
		code = e.ErrorDatabase
		return serializer.Response{
			Status: code,
			Msg:    e.GetMsg(code),
		}
	}
Copy the code
  • Password under model/user
//CheckPassword CheckPassword
func (user *User) CheckPassword(password string) bool {
	err := bcrypt.CompareHashAndPassword([]byte(user.PasswordDigest), []byte(password))
	return err == nil
}
Copy the code
  • Verifying user passwords
	if user.CheckPassword(service.Password) == false {
		code = e.ErrorNotCompare
		return serializer.Response{
			Status: code,
			Msg:    e.GetMsg(code),
		}
	}
Copy the code
  • Issue a token to a user
token, err := util.GenerateToken(service.UserName, service.Password, 0)
Copy the code
  • Define the structure of claims
type Claims struct {
	ID 		  uint 	`json:"id"`
	Username  string `json:"username"`
	Authority int    `json:"authority"`
	jwt.StandardClaims
}
Copy the code
  • Generate token function

The id, username, password and authority of the incoming user are encrypted into tokens, and the identity can be verified later

func GenerateToken(id uint ,username, password string, authority int) (string, error) {
	nowTime := time.Now()
	expireTime := nowTime.Add(24 * time.Hour)
	claims := Claims{
		Username:  username,
		Password:  password,
		Authority: authority,
		StandardClaims: jwt.StandardClaims{
			ExpiresAt: expireTime.Unix(),
			Issuer:    "cmall",
		},
	}
	tokenClaims := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
	token, err := tokenClaims.SignedString(jwtSecret)
	return token, err
}
Copy the code
  • The complete code for the user to log into the service
func (service *UserLoginService) Login(a) serializer.Response {
	var user model.User
	code := e.SUCCESS
	if err := model.DB.Where("user_name=?", service.UserName).First(&user).Error; err ! =nil {
		// If no query is found, an error is returned
		if gorm.IsRecordNotFoundError(err) {
			logging.Info(err)
			code = e.ErrorNotExistUser
			return serializer.Response{
				Status: code,
				Msg:    e.GetMsg(code),
			}
		}
		logging.Info(err)
		code = e.ErrorDatabase
		return serializer.Response{
			Status: code,
			Msg:    e.GetMsg(code),
		}
	}
	if user.CheckPassword(service.Password) == false {
		code = e.ErrorNotCompare
		return serializer.Response{
			Status: code,
			Msg:    e.GetMsg(code),
		}
	}
	token, err := util.GenerateToken(user.ID, service.UserName, 0)
	iferr ! =nil {
		logging.Info(err)
		code = e.ErrorAuthToken
		return serializer.Response{
			Status: code,
			Msg:    e.GetMsg(code),
		}
	}
	return serializer.Response{
		Status: code,
		Data:   serializer.TokenData{User: serializer.BuildUser(user), Token: token},
		Msg:    e.GetMsg(code),
	}
}
Copy the code

3. Login test