Hoe om te gaan met de workflow voor vergeten en opnieuw instellen van wachtwoorden met React en Node.js
Laat bezoekers van uw site niet in de steek; laat ze hun wachtwoord opnieuw instellen als ze het vergeten zijn.
Authenticatiesystemen spelen een cruciale rol bij het bieden van een naadloze en veilige gebruikerservaring. Een authenticatieworkflow omvat doorgaans twee processen: aanmelden en inloggen.
Naarmate het aantal onlinediensten toeneemt, maken mensen accounts aan, en voor elk account zijn unieke inloggegevens vereist. Dit maakt het echter gemakkelijk om inloggegevens te vergeten of te verwarren. Om dit aan te pakken, moet uw app een functie voor het opnieuw instellen van het wachtwoord implementeren waarmee een gebruiker zijn wachtwoord gemakkelijk en veilig kan resetten.
Zet het React-project op
U kunt een workflow voor het opnieuw instellen van wachtwoorden op verschillende manieren implementeren. Er bestaat geen universele standaard waaraan elke toepassing moet voldoen. In plaats daarvan moet u de aanpak die u kiest afstemmen op de specifieke behoeften van uw toepassing.
De workflow waarover u hier leert, omvat de volgende stappen:
Om aan de slag te gaan, start u snel een React-project op. Installeer vervolgens Axios, een JavaScript HTTP-verzoekbibliotheek.
npm install axiosU kunt de code van het project vinden in deze GitHub-repository.
Maak een inlogcomponent
Maak in de src-map een nieuw components/Login.js-bestand en voeg de volgende code toe. Begin met het definiëren van het proces voor het opnieuw instellen van het wachtwoord:
import axios from "axios";
import React, { useState } from "react";
import { useContext } from "react";
import { RecoveryContext } from "../App";
import "./global.component.css";
export default function Login() {
const { setPage, setOTP, setEmail } = useContext(RecoveryContext);
const [userEmail, setUserEmail] = useState("");
function sendOtp() {
if (userEmail) {
axios.get(`http://localhost:5000/check_email?email=${userEmail}`).then((response) => {
if (response.status === 200) {
const OTP = Math.floor(Math.random() * 9000 + 1000);
console.log(OTP);
setOTP(OTP);
setEmail(userEmail);
axios.post("http://localhost:5000/send_email", {
OTP,
recipient_email: userEmail,
})
.then(() => setPage("otp"))
.catch(console.log);
} else {
alert("User with this email does not exist!");
console.log(response.data.message);
}}).catch(console.log);
} else {
alert("Please enter your email");
}}Deze code creëert een functie die een eenmalig wachtwoord (OTP) naar het e-mailadres van een gebruiker verzendt. Het verifieert eerst de gebruiker door zijn e-mail in de database te controleren voordat het OTP wordt gegenereerd en verzonden. Ten slotte wordt de gebruikersinterface bijgewerkt met de OTP-pagina.
Voltooi de login-component door code toe te voegen om het login JSX-formulierelement weer te geven:
return (
<div>
<h2>Login</h2>
<form>
<label /> Email:
<input type="email" value={userEmail} onChange={(e) => { setUserEmail(e.target.value) }} />
<label /> Password:
<input type="password" />
<button type="submit">login</button>
</form>
<a href="#" onClick={() => sendOtp()}>
Forgot Password
</a>
</div>
);
}Maak een OTP-verificatiecomponent
Om de geldigheid van een door een gebruiker ingevoerde code te garanderen, moet u deze vergelijken met de code die naar zijn of haar e-mail is verzonden.
Maak een nieuw bestand components/OTPInput.js en voeg deze code toe:
import React, { useState, useContext, useEffect } from "react";
import { RecoveryContext } from "../App";
import axios from "axios";
import "./global.component.css";
export default function OTPInput() {
const { email, otp, setPage } = useContext(RecoveryContext);
const [OTPinput, setOTPinput] = useState( "");
function verifyOTP() {
if (parseInt(OTPinput) === otp) {
setPage("reset");
} else {
alert("The code you have entered is not correct, try again re-send the link");
}
}De code creëert een React-component waarin gebruikers hun OTP-code verifiëren. Het controleert of de ingevoerde code overeenkomt met de code die is opgeslagen in het contextobject. Als het geldig is, wordt de pagina voor het opnieuw instellen van het wachtwoord weergegeven. Omgekeerd wordt er een waarschuwing weergegeven waarin de gebruiker wordt gevraagd het opnieuw te proberen of de OTP opnieuw te verzenden.
U kunt de code in deze repository controleren die een functie implementeert voor het opnieuw verzenden van OTP's en een vervaltimer voor de OTP-code.
Geef ten slotte de invoer-JSX-elementen weer.
return (
<div>
<h3>Email Verification</h3>
<p>We have sent a verification code to your email.</p>
<form>
<input type="text" value={OTPinput} onChange={(e) => { setOTPinput(e.target.value) }} />
<button onClick={() => verifyOTP()}>Verify Account</button>
<a onClick={() => resendOTP()} > Didn't receive code?
{disable ? `Resend OTP in ${timerCount}s` : " Resend OTP"}
</a>
</form>
</div>
);}Maak de component Wachtwoord opnieuw instellen
Maak een nieuw components/Reset.js bestand en voeg deze code toe:
import React, {useState, useContext} from "react";
import { RecoveryContext } from "../App";
import axios from "axios";
import "./global.component.css";
export default function Reset() {
const [password, setPassword] = useState("");
const { setPage, email } = useContext(RecoveryContext);
function changePassword() {
if (password) {
try {
axios.put("http://localhost:5000/update-password", {
email:email,
newPassword: password,
}).then(() => setPage("login"));
return alert("Password changed successfully, please login!");
} catch (error) {console.log(error);}}
return alert("Please enter your new Password");
}
return (
<div>
<h2> Change Password </h2>
<form>
<label /> New Password:
<input
type="password"
placeholder="........"
required=""
value={password}
onChange={(e) => setPassword(e.target.value)} />
<button onClick={() => changePassword()}>Reset passwod </button>
</form>
</div>
);
}Deze code geeft een formulier weer waarmee gebruikers een nieuw wachtwoord kunnen invoeren. Wanneer de gebruiker op verzenden klikt, wordt er een verzoek naar de server gestuurd om het wachtwoord in de database bij te werken. Vervolgens wordt de gebruikersinterface bijgewerkt als het verzoek succesvol is.
Update uw App.js-component
Breng de onderstaande wijzigingen aan in uw src/App.js-bestand:
import { useState, createContext } from "react";
import Login from "./components/Login";
import OTPInput from "./components/OTPInput";
import Reset from "./components/Reset";
import "./App.css";
export const RecoveryContext = createContext();
export default function App() {
const [page, setPage] = useState("login");
const [email, setEmail] = useState("");
const [otp, setOTP] = useState("");
function NavigateComponents() {
if (page === "login") return <Login />;
if (page === "otp") return <OTPInput />;
if (page === "reset") return <Reset />;
}
return (
<div className="App-header">
<RecoveryContext.Provider
value={{ page, setPage, otp, setOTP, email, setEmail }}>
<div>
<NavigateComponents />
</div>
</RecoveryContext.Provider>
</div>
);
}Deze code definieert een contextobject dat de status van de app beheert, waaronder het e-mailadres van de gebruiker, de OTP-code en de verschillende pagina's binnen de app. In wezen maakt het contextobject het mogelijk om de vereiste toestanden tussen verschillende componenten door te geven – een alternatief voor het gebruik van rekwisieten.
Het bevat ook een functie die de paginanavigatie gemakkelijk afhandelt zonder hele componenten opnieuw te hoeven renderen.
Stel een Express.js-server in
Configureer tijdens de clientconfiguratie een backend-authenticatieservice om de functionaliteit voor het opnieuw instellen van het wachtwoord af te handelen.
Maak om te beginnen een Express-webserver en installeer deze pakketten:
npm install cors dotenv nodemailer mongooseMaak vervolgens een MongoDB-database of configureer een MongoDB-cluster in de cloud. Kopieer vervolgens de meegeleverde verbindingsreeks, maak een ENV-bestand in de hoofdmap en plak de verbindingsreeks.
Ter afsluiting moet u de databaseverbinding configureren en de datamodellen voor uw gebruikersgegevens definiëren. Gebruik de code in deze repository om de databaseverbinding in te stellen en de datamodellen te definiëren.
Definieer de API-routes
Een backend-service heeft idealiter verschillende routes die de HTTP-verzoeken van klanten afhandelen. In dit geval moet u drie routes definiëren die de API-verzoeken voor het verzenden van e-mail, e-mailverificatie en update-wachtwoord van de React-client beheren.
Maak een nieuw bestand met de naam userRoutes.js in de hoofdmap en voeg de volgende code toe:
const express = require('express');
const router = express.Router();
const userControllers = require('../controllers/userControllers');
router.get('/check_email', userControllers.checkEmail);
router.put('/update-password', userControllers.updatePassword);
router.post('/send_email', userControllers.sendEmail);
module.exports = router;Controllers voor de API-routes
Verwerkingsverantwoordelijken zijn verantwoordelijk voor het verwerken van HTTP-verzoeken van klanten. Zodra een client een verzoek indient voor een bepaalde API-route, wordt een controllerfunctie aangeroepen en uitgevoerd om het verzoek te verwerken en een passend antwoord te retourneren.
Maak een nieuw controllers/userControllers.js-bestand en voeg de onderstaande code toe.
Gebruik de code in deze repository om controllers te definiëren voor de API-routes voor e-mailverificatie en het bijwerken van wachtwoorden.
Begin met het definiëren van de controller voor het verzenden van e-mail:
exports.sendEmail = (req, res) => {
const transporter = nodemailer.createTransport({
service: 'gmail',
secure: true,
auth: {
user: process.env.MY_EMAIL,
pass: process.env.APP_PASSWORD,
},
});
const { recipient_email, OTP } = req.body;
const mailOptions = {
from: process.env.MY_EMAIL,
to: recipient_email,
subject: 'PASSWORD RESET',
html: `<html>
<body>
<h2>Password Recovery</h2>
<p>Use this OTP to reset your password. OTP is valid for 1 minute</p>
<h3>${OTP}</h3>
</body>
</html>`,
};
transporter.sendMail(mailOptions, (error, info) => {
if (error) {
console.log(error);
res.status(500).send({ message: "An error occurred while sending the email" });
} else {
console.log('Email sent: ' + info.response);
res.status(200).send({ message: "Email sent successfully" });
}
});
};
Deze code definieert een functie die Nodemailer gebruikt om een e-mail met een OTP-reset naar een opgegeven ontvanger te verzenden. Het stelt een transporter in met uw eigen Gmail-account en wachtwoord.
Om uw Gmail-app-wachtwoord te verkrijgen, moet u een app-wachtwoord genereren in uw Google-accountinstellingen. U gebruikt dit wachtwoord dan in plaats van uw gewone Gmail-wachtwoord om de Nodemailer te authenticeren.
Configureer het serveringangspunt
Maak een server.js-bestand in de hoofdmap en voeg deze code toe:
const express = require('express');
const cors = require('cors');
const app = express();
const port = 5000;
require('dotenv').config();
const nodemailer = require('nodemailer');
const connectDB = require('./utils/dbconfig');
connectDB();
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use(cors());
const userRoutes = require('./routes/userRoutes');
app.use('/', userRoutes);
app.listen(port, () => {
console.log(`Server is listening at http://localhost:${port}`);
});Als zowel de client als de server zijn ingesteld, kunt u de ontwikkelingsservers gebruiken om de wachtwoordfunctionaliteit te testen.
Een aangepaste service voor het opnieuw instellen van wachtwoorden bouwen
Het creëren van een systeem voor het opnieuw instellen van wachtwoorden door het af te stemmen op uw applicatie en de gebruikers ervan is de beste aanpak, ook al bestaan er betaalde, kant-en-klare oplossingen. Bij het ontwerpen van deze functie moet u rekening houden met zowel de gebruikerservaring als de beveiliging, aangezien aanvallen een constante bedreiging vormen.

