Օգտագործողի նույնականացում NodeJS-ում Passport-ի և MongoDB-ի միջոցով
Օգտագործողի նույնականացումը կարևոր է զգայուն տեղեկատվության պաշտպանության համար: Բարեբախտաբար, դա իրականացնելը դժվար չէ:
Եթե ցանկանում եք պաշտպանել զգայուն բովանդակությունը ձեր Node հավելվածում, ձեզ անհրաժեշտ է օգտատերերին իսկությունը հաստատելու միջոց: Այնուամենայնիվ, նույնականացման ձեր սեփական համակարգի կառուցումը բարդ է և ժամանակատար, և եթե այն ճիշտ չկատարվի, կարող է անվտանգության խոցելիություններ առաջացնել ձեր հավելվածում: Երրորդ կողմի գործիքները, ինչպիսիք են Passport-ը, հեշտացնում են նույնականացումը:
Այս ձեռնարկում դուք կսովորեք, թե ինչպես իրականացնել նույնականացում Node-ում՝ օգտագործելով Passport-ը և MongoDB-ը:
Որո՞նք են նույնականացումը և թույլտվությունը:
Թեև իսկությունը և թույլտվությունը երբեմն օգտագործվում են փոխադարձաբար, անվտանգության այս երկու հասկացությունները տարբեր իմաստներ ունեն: Նույնականացումն այն գործընթացն է, որը թույլ է տալիս ստուգել, որ օգտատերը, թե ով է նրանք պնդում, թե ով է, մինչդեռ թույլտվությունը որոշում է, թե արդյոք վավերացված օգտատերը մուտք ունի ձեր հավելվածի որոշ մասեր:
Ի՞նչ է Passport.js-ը:
Passport.js-ը (կամ Passport-ը) նույնականացման միջին ծրագիր է NodeJS-ի համար, որն ապահովում է ավելի քան 500 ռազմավարություն օգտատերերի նույնականացման համար, ներառյալ passport-local, որն օգտագործում է օգտանուն և գաղտնաբառ:
Այս ձեռնարկը օգտագործում է passport-local ևpasport-jwt՝ երթուղիները պաշտպանելու համար:
Ինչպես կարգավորել օգտվողի նույնականացումը NodeJS-ում
Այժմ դուք մի փոքր գիտեք օգտվողի նույնականացման և Passport.js-ի մասին, մենք կարող ենք տեսնել, թե ինչպես կարելի է նույնականացումը կարգավորել NodeJS-ում: Ստորև մենք նախանշել ենք այն քայլերը, որոնք դուք պետք է կատարեք:
Քայլ 1. Ստեղծեք հանգույցի սերվեր
Ստեղծեք թղթապանակ user-auth-nodejs և նավարկեք դեպի այն՝ օգտագործելով ձեր տերմինալը:
mkdir user-auth-nodejs
cd user-auth-nodejs
Հաջորդ սկզբնավորելpack.json.
npm init
Քանի որ դուք կօգտագործեք Express-ը՝ NodeJS backend-ի շրջանակը, տեղադրեք այն՝ գործարկելով հետևյալ հրամանը։
npm i express
Այժմ ստեղծեք ֆայլ՝app.js և ավելացրեք հետևյալ կոդը՝ սերվերը ստեղծելու համար:
const express = require("express");
const app = express();
const PORT = 3000;
app.listen(PORT, () => {
console.log(`Listening on port ${PORT}`);
});
Քայլ 2. Ստեղծեք տվյալների բազան
Օգտագործողի տվյալները պահելու համար ձեզ անհրաժեշտ է տվյալների բազա: Դուք կօգտագործեք mongoose-ը MongoDB տվյալների սխեման ստեղծելու համար, որը սահմանում է տվյալների կառուցվածքը և տեսակը, որը դուք կպահեք տվյալների բազայում: Քանի որ դուք պահպանում եք օգտվողի տվյալները, ստեղծեք օգտվողի սխեման:
Տեղադրեք մանգուստ:
npm i mongoose
Ստեղծեք նոր ֆայլ՝userModel.js և ավելացրեք հետևյալը։
const mongoose = require('mongoose')
const {Schema} = mongoose
const UserSchema = new Schema ({
email: {
type: String,
required: true
},
password: {
type: String,
required: true
}
})
const UserModel = mongoose.model('user', UserSchema);
module.exports = UserModel;
Նախքան գաղտնաբառը պահելը, դուք պետք է գաղտնագրեք այն անվտանգության նկատառումներով: Դուք կօգտագործեք bcryptjs՝ շատ օգտակար npm փաթեթ, որը հեշտացնում է կոդավորված գաղտնաբառերի հետ աշխատելը:
Տեղադրեք bcryptjs.
npm i bcryptjs
Փոփոխեք usermodel.js՝ գաղտնաբառը գաղտնագրելու համար, նախքան այն պահելը տվյալների բազայում:
const mongoose = require('mongoose')
const bcrypt = require('bcryptjs');
const {Schema} = mongoose
const UserSchema = new Schema ({
...
})
UserSchema.pre('save', async function(next) {
try {
// check method of registration
const user = this;
if (!user.isModified('password')) next();
// generate salt
const salt = await bcrypt.genSalt(10);
// hash the password
const hashedPassword = await bcrypt.hash(this.password, salt);
// replace plain text password with hashed password
this.password = hashedPassword;
next();
} catch (error) {
return next(error);
}
});
...
const User = mongoose.model('User', UserSchema);
Այստեղ դուք օգտագործում եք նախապահպանման կեռը՝ գաղտնաբառը պահպանվելուց առաջ փոփոխելու համար: Գաղափարը պարզ տեքստային գաղտնաբառի փոխարեն գաղտնաբառի հեշ տարբերակը պահելն է: Հեշը երկար բարդ տող է, որը ստեղծվում է պարզ տեքստային տողից:
Օգտագործեք isModified՝ ստուգելու, թե արդյոք գաղտնաբառը փոխվում է, քանի որ անհրաժեշտ է միայն նոր գաղտնաբառեր հաշել: Հաջորդը, ստեղծեք աղ և փոխանցեք այն պարզ տեքստային գաղտնաբառով hash մեթոդին՝ հեշավորված գաղտնաբառ ստեղծելու համար: Վերջապես, փոխարինեք պարզ տեքստային գաղտնաբառը տվյալների բազայում հաշված գաղտնաբառով:
Ստեղծեք db.js և կարգավորեք տվյալների բազան:
const mongoose = require("mongoose");
mongoose.Promise = global.Promise;
const dbUrl = "mongodb://localhost/user";
const connect = async () => {
mongoose.connect(dbUrl, { useNewUrlParser: true, useUnifiedTopology: true });
const db = mongoose.connection;
db.on("error", () => {
console.log("could not connect");
});
db.once("open", () => {
console.log("> Successfully connected to database");
});
};
module.exports = { connect };
app.js-ում միացեք տվյալների շտեմարանին:
// connect to db
const db = require('./db');
db.connect();
Քայլ 3. Ստեղծեք անձնագիր
Տեղադրեք Passport և passport-local: Դուք կօգտագործեք այս փաթեթները՝ գրանցման և օգտվողներին մուտք գործելու համար:
npm i passport
npm i passport-local
Ստեղծեք նոր ֆայլ՝ passportConfig.js և ներմուծեք passport-local և userModel.js:
const LocalStraregy = require("passport-local").Strategy;
const User = require("./userModel");
Կազմաձևեք անձնագիրը՝ օգտվողի գրանցումը կարգավորելու համար:
const LocalStrategy = require("passport-local");
const User = require("./userModel");
module.exports = (passport) => {
passport.use(
"local-signup",
new LocalStrategy(
{
usernameField: "email",
passwordField: "password",
},
async (email, password, done) => {
try {
// check if user exists
const userExists = await User.findOne({ "email": email });
if (userExists) {
return done(null, false)
}
// Create a new user with the user data provided
const user = await User.create({ email, password });
return done(null, user);
} catch (error) {
done(error);
}
}
)
);
}
Վերոնշյալ կոդում դուք ստուգում եք, թե արդյոք էլփոստն արդեն օգտագործվում է: Եթե էլփոստը գոյություն չունի, գրանցեք օգտվողին: Նկատի ունեցեք, որ դուք նաև կարգավորում եք օգտանունի դաշտը, որպեսզի ընդունի էլ. Լռելյայնորեն, passport-local-ն ակնկալում է օգտվողի անուն, այնպես որ դուք պետք է հայտնեք նրան, որ փոխանցում եք էլ.
Օգտագործեք passport-local՝ նաև օգտատերերի մուտքը կարգավորելու համար:
module.exports = (passport) => {
passport.use(
"local-signup",
new localStrategy(
...
)
);
passport.use(
"local-login",
new LocalStrategy(
{
usernameField: "email",
passwordField: "password",
},
async (email, password, done) => {
try {
const user = await User.findOne({ email: email });
if (!user) return done(null, false);
const isMatch = await user.matchPassword(password);
if (!isMatch)
return done(null, false);
// if passwords match return user
return done(null, user);
} catch (error) {
console.log(error)
return done(error, false);
}
}
)
);
};
Այստեղ ստուգեք, թե արդյոք օգտվողը կա տվյալների բազայում, և եթե կա, ստուգեք, արդյոք տրամադրված գաղտնաբառը համընկնում է տվյալների բազայի հետ: Նկատի ունեցեք, որ դուք նաև զանգահարեք matchPassword() մեթոդը օգտագործողի մոդելի վրա, այնպես որ գնացեք userModel.js ֆայլ և ավելացրեք այն:
UserSchema.methods.matchPassword = async function (password) {
try {
return await bcrypt.compare(password, this.password);
} catch (error) {
throw new Error(error);
}
};
Այս մեթոդը համեմատում է օգտագործողի և տվյալների բազայի գաղտնաբառը և վերադարձնում է true, եթե դրանք համընկնում են:
Քայլ 4. Ստեղծեք նույնականացման երթուղիներ
Այժմ դուք պետք է ստեղծեք այն վերջնակետերը, որոնց օգտատերերը կուղարկեն տվյալները: Առաջին հերթին գրանցման երթուղին է, որը կընդունի նոր օգտատիրոջ էլ.փոստը և գաղտնաբառը:
app.js-ում օգտագործողին գրանցելու համար օգտագործեք անձնագրային նույնականացման միջին ծրագիրը, որը հենց նոր եք ստեղծել:
app.post(
"/auth/signup",
passport.authenticate('local-signup', { session: false }),
(req, res, next) => {
// sign up
res.json({
user: req.user,
});
}
);
Հաջողության դեպքում գրանցման երթուղին պետք է վերադարձնի ստեղծված օգտվողին:
Հաջորդը, ստեղծեք մուտքի երթուղին:
app.post(
"/auth/login",
passport.authenticate('local-login', { session: false }),
(req, res, next) => {
// login
res.json({
user: req.user,
});
}
);
Քայլ 5. Ավելացնել պաշտպանված երթուղիներ
Մինչ այժմ դուք օգտագործել եք Անձնագիր՝ ստեղծելու միջին ծրագիր, որը գրանցում է օգտվողին տվյալների բազայում, և մեկ այլ ծրագիր, որը թույլ է տալիս գրանցված օգտվողին մուտք գործել: Այնուհետև դուք կստեղծեք թույլտվության միջնակարգ ծրագիր՝ պաշտպանելու զգայուն երթուղիները՝ օգտագործելով JSON վեբ նշան (JWT): JWT թույլտվությունն իրականացնելու համար անհրաժեշտ է.
- Ստեղծեք JWT նշան:
- Փոխանցեք նշանը օգտվողին: Օգտագործողը այն հետ կուղարկի թույլտվության հարցումներում:
- Ստուգեք օգտատիրոջ կողմից ուղարկված նշանը:
Դուք կօգտագործեք jsonwebtoken փաթեթը JWT-ների հետ աշխատելու համար:
Այն տեղադրելու համար գործարկեք հետևյալ հրամանը.
npm և jsonwebtoken
Հաջորդը, ստեղծեք նշան յուրաքանչյուր օգտվողի համար, որը հաջողությամբ մուտք է գործում:
app.js-ում ներմուծեք jsonwebtoken և փոփոխեք մուտքի երթուղին, ինչպես ստորև:
app.post(
"/auth/login",
passport.authenticate('local-login', { session: false }),
(req, res, next) => {
// login
jwt.sign({user: req.user}, 'secretKey', {expiresIn: '1h'}, (err, token) => {
if(err) {
return res.json({
message: "Failed to login",
token: null,
});
}
res.json({
token
});
})
}
);
Իրական հավելվածում դուք կօգտագործեք ավելի բարդ գաղտնի բանալի և կպահեք այն կազմաձևման ֆայլում:
Մուտքի երթուղին հաջողության դեպքում վերադարձնում է նշան:
Օգտագործեք passport-jwt պաշտպանված երթուղիներ մուտք գործելու համար:
npm i passport-jwt
passportConfig.js-ում կարգավորեք passport-jwt-ը:
const JwtStrategy = require("passport-jwt").Strategy;
const { ExtractJwt } = require("passport-jwt")
module.exports = (passport) => {
passport.use(
"local-login",
new LocalStrategy(
...
);
passport.use(
new JwtStrategy(
{
jwtFromRequest: ExtractJwt.fromHeader("authorization"),
secretOrKey: "secretKey",
},
async (jwtPayload, done) => {
try {
// Extract user
const user = jwtPayload.user;
done(null, user);
} catch (error) {
done(error, false);
}
}
)
);
};
Ուշադրություն դարձրեք, որ դուք հանում եք JWT-ն թույլտվության վերնագրից՝ հարցման մարմնի փոխարեն: Սա թույլ չի տալիս հաքերներին ընդհատել հարցումը և գրավել նշանը:
Տեսնելու համար, թե ինչպես էpasport-jwt պահպանում երթուղիները, ստեղծեք պաշտպանված երթուղի app.js-ում:
app.get(
"/user/protected",
passport.authenticate("jwt", { session: false }),
(req, res, next) => {
res.json({user: req.user});
}
);
Միայն վավեր JWT-ով հարցումը վերադարձնում է օգտատիրոջ տվյալները:
Այժմ դուք պատրաստ եք ձեր օգտատիրոջ նույնականացումը տեղափոխել հաջորդ մակարդակ
Այս ձեռնարկում դուք իմացաք, թե ինչպես կարող եք նույնականացնել օգտատերերին՝ օգտագործելով էլ. փոստ և գաղտնաբառ՝ Passport-ի օգնությամբ: Սկզբում դա կարող է սարսափելի թվալ, բայց գործընթացը համեմատաբար պարզ է: Դուք կարող եք ավելի հեռուն գնալ և օգտվել երրորդ կողմի ինքնության մատակարարներից, որոնք աջակցվում են անձնագրով, ինչպիսիք են Twitter-ը, Facebook-ը և Google-ը: