Heim > Backend-Entwicklung > Golang > Funktion zum Zurücksetzen des Passworts: Verwenden von OTP zum Zurücksetzen des Passworts

Funktion zum Zurücksetzen des Passworts: Verwenden von OTP zum Zurücksetzen des Passworts

Linda Hamilton
Freigeben: 2024-10-01 18:09:03
Original
1019 Leute haben es durchsucht

Password Reset Feature: Using OTP to Reset Password

Backend

2. Passwort zurücksetzen

Weiter zur nächsten API.

PUT auf /api/reset-password, req -> otp, E-Mail, neues Passwort, res -> kein Inhalt

// controllers/passwordReset.go
func ResetPassword(c *fiber.Ctx) error {
    type Input struct {
        OTP         string `json:"otp"`
        Email       string `json:"email"`
        NewPassword string `json:"new_password"`
    }

    var input Input

    err := c.BodyParser(&input)
    if err != nil {
        return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
            "error": "invalid data",
        })
    }

    // no input field should be empty
    if input.OTP == "" || input.Email == "" || input.NewPassword == "" {
        return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
            "error": "invalid data",
        })
    }

    // TODO: check redis for otp and update password

    return c.SendStatus(fiber.StatusNoContent)
}
Nach dem Login kopieren

Route dafür hinzufügen

// routes/routes.go
api.Put("/reset-password", controllers.ResetPassword)
Nach dem Login kopieren

Jetzt brauche ich zwei Funktionen:

  1. OTP überprüfen -> Eingabe = otp, E-Mail; Ausgabe = Fehler (falls vorhanden)
  2. UpdatePassword -> Eingabe = E-Mail, Passwort; Ausgabe = Fehler (falls vorhanden)
// utils/passwordReset.go
func VerifyOTP(otp string, email string, c context.Context) (error, bool) {
    key := otpKeyPrefix + email

    // get the value for the key
    value, err := config.RedisClient.Get(c, key).Result()
    if err != nil {
        // the following states that the key was not found
        if err == redis.Nil {
            return errors.New("otp expired / incorrect email"), false
        }

        // for other errors
        return err, true
    }

    // compare received otp's hash with value in redis
    err = bcrypt.CompareHashAndPassword([]byte(value), []byte(otp))
    if err != nil {
        return errors.New("incorrect otp"), false
    }

    // delete redis key to prevent abuse of otp
    err = config.RedisClient.Del(c, key).Err()
    if err != nil {
        return err, true
    }

    return nil, false
}

func UpdatePassword(email string, password string, c context.Context) error {
    users := config.DB.Collection("users")

    // hash the password
    hashedPassword, _ := bcrypt.GenerateFromPassword([]byte(password), 10)

    // update the password
    update := bson.M{
        "$set": bson.M{
            "password": hashedPassword,
        },
    }
    _, err := users.UpdateByID(c, email, update)
    if err != nil {
        return err
    }

    return nil
}
Nach dem Login kopieren

Jetzt muss ich beides im Controller zusammenfügen. Ich verwende den Bool aus der VerifyOTP-Funktion, um anzugeben, ob es sich bei dem Fehler um einen internen Fehler handelt oder ob er an der Eingabe liegt.

// controllers/passwordReset.go
func ResetPassword(c *fiber.Ctx) error {
    type Input struct {
        OTP         string `json:"otp"`
        Email       string `json:"email"`
        NewPassword string `json:"new_password"`
    }

    var input Input

    err := c.BodyParser(&input)
    if err != nil {
        return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
            "error": "invalid data",
        })
    }

    // no input field should be empty
    if input.OTP == "" || input.Email == "" || input.NewPassword == "" {
        return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
            "error": "invalid data",
        })
    }

    // check redis for otp
    err, isInternalErr := utils.VerifyOTP(input.OTP, input.Email, c.Context())
    if err != nil {
        var code int
        if isInternalErr {
            code = fiber.StatusInternalServerError
        } else {
            code = fiber.StatusUnauthorized
        }

        return c.Status(code).JSON(fiber.Map{
            "error": err.Error(),
        })
    }

    err = utils.UpdatePassword(input.Email, input.NewPassword, c.Context())
    if err != nil {
        return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
            "error": err.Error(),
        })
    }

    return c.SendStatus(fiber.StatusNoContent)
}
Nach dem Login kopieren

Die API ist jetzt erstellt und der Test kann mit dem folgenden cURL-Befehl durchgeführt werden

curl --location --request PUT 'localhost:3000/api/reset-password' \
--header 'Content-Type: application/json' \
--data-raw '{
    "email": "yashjaiswal.cse@gmail.com",
    "new_password": "tester123",
    "otp": "DM4RDNF07B"
}'
Nach dem Login kopieren

Im nächsten Teil beginne ich mit dem Frontend

Das obige ist der detaillierte Inhalt vonFunktion zum Zurücksetzen des Passworts: Verwenden von OTP zum Zurücksetzen des Passworts. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Quelle:dev.to
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Neueste Artikel des Autors
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage