Skip to main content
Version: 2.10.x(Latest)

Upon receiving the username and password at the login endpoint, it compares them with the information in the database. If correct, it generates and returns a Token, otherwise, it prompts "Username or password error."

Similarly, it follows the development principle of Three Boards: writing Api to generate Controller, writing core logic Logic, and having the Controller call Logic.

Add Api​


api/users/v1/users.go

...

type LoginReq struct {
g.Meta `path:"users/login" method:"post" sm:"Login" tags:"User"`
Username string `json:"username" v:"required|length:3,12"`
Password string `json:"password" v:"required|length:6,16"`
}

type LoginRes struct {
Token string `json:"token" dc:"Add Authorization: token in the header for authentication-required interfaces"`
}

Don't forget to execute gf gen ctrl! You need to execute it every time you change the Api, not repeated in the text below.

Write Logic​


The difficulty of the login logic lies in generating the Token. Prepare a random string JwtKey as the signature, and define it in the utility directory.

utility/jwt.go

package utility  

var JwtKey = []byte("db03d23b03ec405793b38f10592a2f34")

Write the core logic. First, perform a Where query based on the username. After data retrieval, encrypt the password again. If it matches the encrypted text in the database, it's a legitimate user and a Token is generated and returned.

internal/logic/users/account.go

package users  

import (
"context"
"errors"
"time"

"github.com/golang-jwt/jwt/v5"

"star/internal/dao"
"star/internal/model/entity"
"star/utility"
)

type userClaims struct {
Id uint
Username string
jwt.RegisteredClaims
}

func (u *Users) Login(ctx context.Context, username, password string) (tokenString string, err error) {
var user entity.Users
err = dao.Users.Ctx(ctx).Where("username", username).Scan(&user)
if err != nil {
return "", errors.New("Username or password error")
}

if user.Id == 0 {
return "", errors.New("User does not exist")
}

// Encrypt the password and compare it with the password in the database
if user.Password != encryptPassword(password) {
return "", errors.New("Username or password error")
}

// Generate token
uc := &userClaims{
Id: user.Id,
Username: user.Username,
RegisteredClaims: jwt.RegisteredClaims{
ExpiresAt: jwt.NewNumericDate(time.Now().Add(6 * time.Hour)),
},
}
token := jwt.NewWithClaims(jwt.SigningMethodHS256, uc)
return token.SignedString(utility.JwtKey)
}

As seen in the above code, we need to declare a struct UserClaims to store the signature information. It saves the Id and Username and sets the token validity to 6 hours. The final declared object needs to call the SignedString method and pass in JwtKey to generate a signature.

Controller calls Logic​


internal/controller/users/users_v1_login.go

package users  

import (
"context"

"star/internal/logic/users"
"star/api/users/v1"
)

func (c *ControllerV1) Login(ctx context.Context, req *v1.LoginReq) (res *v1.LoginRes, err error) {
token, err := c.users.Login(ctx, req.Username, req.Password)
if err != nil {
return
}
return &v1.LoginRes{Token: token}, nil
}

Interface Testing​


$ curl -X POST http://127.0.0.1:8000/v1/users/login -H "Content-Type: application/json" -d "{\"username\":\"oldme\", \"password\":\"123456\"}"

{
"code":0,
"message":"",
"data":{
"token":"eyJhbGciOi...ZY_ATzOU"
}
}