بسیاری از برنامه های وب و API ها از نوعی تأیید اعتبار برای محافظت از منابع استفاده می کنند و دسترسی خود را فقط برای کاربران تأیید شده محدود می کنند. این راهنما نحوه اجرای احراز هویت برای یک API را با استفاده از JSON Web Tokens (JWTs) و Passport ، یک میان افزار تأیید اعتبار برای Node مطرح می کند.
آشنایی با JSON Web Tokens
JSON Web Token (JWT) یک استاندارد باز است که روشی کم حجم و مختصر برای انتقال ایمن اطلاعات بین طرفین به عنوان یک شی JSON را تعریف می کند.
JWT ها به دلیل اینکه به صورت دیجیتالی امضا میشوند ، امن هستند و و اگر اطلاعات موجود در داخل به هر شکلی دستکاری شود، نشانه نامعتبر را ارائه می کند. در ادامه خواهیم دید که چگونه این کار امکان پذیر است.
JWT از سه تعریف جداگانه ساخته شده است: header (هدر)، Payload (لود) و Signature (امضا).
header: هدر نوع الگوریتم مورد استفاده برای تأیید نشانه و نوع نشانه را تعریف می کند:
{
“type” : “JWT”,
“alg” : “HS256”
}
* Payload : شامل ادعاها (Claims) میباشد. ادعاها اطلاعاتی در مورد کاربر به همراه سایر ابرداده های اضافی مانند موارد زیر است:
{
id : 1
name : ‘devgson’
iat : 1421211952
}
Signature: امضا اطلاعات را در header و Payload در فرمت base64 با یک کلید مخفی کدگذاری می کند. تمام این اطلاعات توسط الگوریتم مشخص شده در سربرگ امضا می شود. در مثال ما ، از HMACSHA256 استفاده می کنیم. امضا تأیید می کند که پیام ارسال شده در طول مسیر دستکاری نشده است.
HMACSHA256(
base64UrlEncode(header) + “.” +
base64UrlEncode(payload),
secret
)
توجه: از JWT نباید برای انتقال یا ذخیره اطلاعات ایمن استفاده شود ، زیرا هر کسی که قادر به رهگیری توکن باشد ، می تواند هدر و لود را در داخل آن رمزگشایی کند. تمام کاری که امضا انجام میدهد، تأیید این است که نشانه به هیچ وجه دستکاری نشده است. این امر نمی تواند مانع از دست یابی به توکن شود.
تنظیم Passport
Passport یک میان افزار تأیید اعتبار است که برای تأیید اعتبار درخواست ها استفاده می شود. این امکان را به توسعه دهندگان می دهد تا برای تأیید اعتبار کاربران از استراتژی های مختلفی استفاده کنند ، از جمله استفاده از یک پایگاه داده محلی یا اتصال به شبکه های اجتماعی از طریق API . در این راهنما ، ما از استراتژی محلی (ایمیل / رمز عبور) استفاده خواهیم کرد.
بیایید یک ساختار پوشه را برای فایل هایی که از آنها استفاده خواهیم کرد ایجاد کنیم:
-model
—model.js
-routes
—routes.js
—secure-routes.js
-auth
—auth.js
-app.js
-package.json
بسته های لازم را با این دستور نصب کنید:
⦁ npm install –save bcrypt body-parser express jsonwebtoken mongoose passport passport-local passport-jwt
⦁
برای درهم سازی رمزهای عبور کاربر به bcrypt ، برای امضای نشانه ها به jsonwebtoken ، برای اجرای استراتژی محلی به passport-local و برای دریافت و تأیید JWT به passport-jwt نیاز خواهیم داشت.
در اینجا نحوه کار برنامه آمده است:
• کاربر با sign up و log in وارد سیستم شده و پس از ورود کاربر به سیستم ، یک نشانه وب JSON به کاربر داده می شود.
• از کاربر انتظار می رود این نشانه را به صورت محلی ذخیره کند.
• این نشانه هنگام تلاش برای دستیابی به برخی از مسیرهای امن توسط کاربر ارسال می شود ، پس از تأیید این نشانه ، به کاربر اجازه دسترسی به مسیر داده میشود.
تنظیم پایگاه داده
اول از همه ، ما طرح کاربر را ایجاد می کنیم. کاربر فقط باید ایمیل و رمز عبور خود را ارائه کند ، این اطلاعات کافی است.
model/model.js
const mongoose = require(‘mongoose’)
const bcrypt = require(‘bcrypt’);
const Schema = mongoose.Schema;
const UserSchema = new Schema({
email : {
type : String,
required : true,
unique : true
},
password : {
type : String,
required : true
}
});
…
اکنون ما نمی خواهیم رمزهای عبور را با متن ساده ذخیره کنیم ، زیرا اگر یک حمله کننده موفق به دسترسی به بانک اطلاعاتی شود ، می تواند رمز عبور را بخواند ، بنابراین می خواهیم از این امر جلوگیری کنیم. از بسته ای به نام “bcrypt” استفاده می کنیم تا کلمه عبور کاربر را در هم سازی (hash) کند و آنها را با خیال راحت ذخیره کند.
model/model.js
….
//This is called a pre-hook, before the user information is saved in the database
//this function will be called, we’ll get the plain text password, hash it and store it.
UserSchema.pre(‘save’, async function(next){
//’this’ refers to the current document about to be saved
const user = this;
//Hash the password with a salt round of 10, the higher the rounds the more secure, but the slower
//your application becomes.
const hash = await bcrypt.hash(this.password, 10);
//Replace the plain text password with the hash and then store it
this.password = hash;
//Indicates we’re done and moves on to the next middleware
next();
});
//We’ll use this later on to make sure that the user trying to log in has the correct credentials
UserSchema.methods.isValidPassword = async function(password){
const user = this;
//Hashes the password sent by the user for login and checks if the hashed password stored in the
//database matches the one sent. Returns true if it does else false.
const compare = await bcrypt.compare(password, user.password);
return compare;
}
const UserModel = mongoose.model(‘user’,UserSchema);
module.exports = UserModel;
تنظیم ثبت نام و ورود به میان افزار
ما از استراتژی محلی passport برای ایجاد میان افزار استفاده خواهیم کرد که ثبت نام کاربر و ورود را انجام میدهد. سپس به مسیرهای خاصی وصل شده و برای احراز هویت استفاده می شود.
auth/auth.js
const passport = require(‘passport’);
const localStrategy = require(‘passport-local’).Strategy;
const UserModel = require(‘../model/model’);
//Create a passport middleware to handle user registration
passport.use(‘signup’, new localStrategy({
usernameField : ’email’,
passwordField : ‘password’
}, async (email, password, done) => {
try {
//Save the information provided by the user to the the database
const user = await UserModel.create({ email, password });
//Send the user information to the next middleware
return done(null, user);
} catch (error) {
done(error);
}
}));
//Create a passport middleware to handle User login
passport.use(‘login’, new localStrategy({
usernameField : ’email’,
passwordField : ‘password’
}, async (email, password, done) => {
try {
//Find the user associated with the email provided by the user
const user = await UserModel.findOne({ email });
if( !user ){
//If the user isn’t found in the database, return a message
return done(null, false, { message : ‘User not found’});
}
//Validate password and make sure it matches with the corresponding hash stored in the database
//If the passwords match, it returns a value of true.
const validate = await user.isValidPassword(password);
if( !validate ){
return done(null, false, { message : ‘Wrong Password’});
}
//Send the user information to the next middleware
return done(null, user, { message : ‘Logged in Successfully’});
} catch (error) {
return done(error);
}
}));
….
ایجاد مسیرها
اکنون که میان افزاری برای مدیریت ثبت نام و ورود به سیستم داریم ، بیایید مسیری ایجاد کنیم که از این میان افزار استفاده کند.
routes/routes.js
const express = require(‘express’);
const passport = require(‘passport’);
const jwt = require(‘jsonwebtoken’);
const router = express.Router();
//When the user sends a post request to this route, passport authenticates the user based on the
//middleware created previously
router.post(‘/signup’, passport.authenticate(‘signup’, { session : false }) , async (req, res, next) => {
res.json({
message : ‘Signup successful’,
user : req.user
});
});
…
امضای JWT
هنگامی که کاربر وارد سیستم میشود ، اطلاعات کاربر به callback سفارشی ما ارسال می شود که به نوبه خود یک نشانه ایمن با اطلاعات ایجاد می کند. پس از دستیابی به مسیرهای ایمن (که بعداً ایجاد خواهیم کرد) باید این نشانه به عنوان یک پارامتر پرس و جو منتقل شود.
routes/routes.js
….
router.post(‘/login’, async (req, res, next) => {
passport.authenticate(‘login’, async (err, user, info) => { try {
if(err || !user){
const error = new Error(‘An Error occurred’)
return next(error);
}
req.login(user, { session : false }, async (error) => {
if( error ) return next(error)
//We don’t want to store the sensitive information such as the
//user password in the token so we pick only the email and id
const body = { _id : user._id, email : user.email };
//Sign the JWT token and populate the payload with the user email and id
const token = jwt.sign({ user : body },’top_secret’);
//Send back the token to the user
return res.json({ token });
}); } catch (error) {
return next(error);
}
})(req, res, next);
});
module.exports = router;
توجه: ما { session : false } را تنظیم کردیم زیرا نمی خواهیم جزئیات کاربر را در یک بخش ذخیره کنیم. انتظار داریم که کاربر در صورت درخواست هر یک از موارد را به مسیرهای امن ارسال کند. این امر به ویژه برای API مفید است ، اما به دلایل عملکردی روش پیشنهادی برای برنامه وب نیست.
تأیید نشانه کاربر
بنابراین اکنون ثبت نام و ورود کاربر به سیستم را مدیریت کرده ایم ، قدم بعدی این است که به کاربران دارای نشانه اجازه دسترسی به مسیرهای خاص ایمن را بدهیم ، اما چگونه می توانیم تأیید کنیم که توکن ارسال شده توسط کاربر معتبر است و به طریقی دستکاری نشده است. بیایید در مرحله بعد این کار را انجام دهیم.
auth/auth.js
….
const JWTstrategy = require(‘passport-jwt’).Strategy;
//We use this to extract the JWT sent by the user
const ExtractJWT = require(‘passport-jwt’).ExtractJwt;
//This verifies that the token sent by the user is valid
passport.use(new JWTstrategy({
//secret we used to sign our JWT
secretOrKey : ‘top_secret’,
//we expect the user to send the token as a query parameter with the name ‘secret_token’
jwtFromRequest : ExtractJWT.fromUrlQueryParameter(‘secret_token’)
}, async (token, done) => {
try {
//Pass the user details to the next middleware
return done(null, token.user);
} catch (error) {
done(error);
}
}));
توجه: اگر به اطلاعات اضافی یا حساسی در مورد کاربر نیاز دارید که در توکن موجود نیست ، می توانید از _id موجود در نشانه برای بازیابی آنها از پایگاه داده استفاده کنید.
ایجاد مسیرهای ایمن
اکنون اجازه می دهیم برخی از مسیرهای ایمن را ایجاد کنید که فقط کاربران دارای نشان های تأیید شده به آنها دسترسی داشته باشند.
routes/secure-routes.js
const express = require(‘express’);
const router = express.Router();
//Let’s say the route below is very sensitive and we want only authorized users to have access
//Displays information tailored according to the logged in user
router.get(‘/profile’, (req, res, next) => {
//We’ll just send back the user details and the token
res.json({
message : ‘You made it to the secure route’,
user : req.user,
token : req.query.secret_token
})
});
module.exports = router;
بنابراین اکنون با ایجاد مسیرها و میان افزار تأیید اعتبار کار ما انجام شده است ، بیایید همه چیز را کنار هم قرار دهیم و سپس آن را آزمایش کنیم.
app.js
const express = require(‘express’);
const mongoose = require(‘mongoose’);
const bodyParser = require(‘body-parser’);
const passport = require(‘passport’);
const app = express();
const UserModel = require(‘./model/model’);
mongoose.connect(‘mongodb://127.0.0.1:27017/passport-jwt’, { useMongoClient : true });
mongoose.connection.on(‘error’, error => console.log(error) );
mongoose.Promise = global.Promise;
require(‘./auth/auth’);
app.use( bodyParser.urlencoded({ extended : false }) );
const routes = require(‘./routes/routes’);
const secureRoute = require(‘./routes/secure-route’);
app.use(‘/’, routes);
//We plugin our jwt strategy as a middleware so only verified users can access this route
app.use(‘/user’, passport.authenticate(‘jwt’, { session : false }), secureRoute );
//Handle errors
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.json({ error : err });
});
app.listen(3000, () => {
console.log(‘Server started’)
تست با Postman
اکنون که همه چیز را کنار هم قرار داده ایم ، بگذارید از Postman برای آزمایش تأیید اعتبار API استفاده کنیم. اول از همه ما باید با یک ایمیل و رمز عبور وارد سیستم شوید. می توانیم این جزئیات را از طریق body درخواست خود ارسال کنیم. پس از اتمام این کار ، برای شروع درخواست POST روی دکمه ارسال کلیک کنید.
می توانیم رمز عبور رمزگذاری شده را ببینیم ، بنابراین هرکسی که به دیتابیس دسترسی دارد فقط به رمز عبور hashed دسترسی خواهد داشت ، ما امنیت را 10 دور افزایش دادیم. در این لینک میتوانید اطلاعات بیشتری در این مورد بیابید.
اکنون بیایید با اعتبارات خود وارد شویم و توکن را دریافت کنیم. مسیر /login را بازدید کنید و ایمیل و رمز عبوری که قبلا استفاده کردید را وارد نمایید و سپس درخواست را آغاز کنید.
اکنون ما نشانه خود را داریم ، هر زمان که بخواهیم به یک مسیر امن دسترسی پیدا کنیم ، این نشانه را ارسال خواهیم کرد. بیایید این کار را با دسترسی به یک مسیر امن user/profile امتحان کنیم ، نشانه خود را در یک پارامتر پرس و جو به نام secret_token ارسال خواهیم کرد ، این نشانه دریافت و بررسی می شود و در صورت صحت اعتبار دسترسی به مسیر را دریافت خواهیم کرد.
همانطور که مشاهده می کنید ، نشانه معتبر به ما امکان دسترسی به مسیر امن را می دهد. می توانید پیش بروید و دسترسی به این مسیر را امتحان کنید. اما در صورت وجود نشانه نامعتبر ، این درخواست یک خطای Unauthorized را برمی گرداند.
نتیجه
JSON web tokens راهی مطمئن برای ایجاد تأیید اعتبار برای API ها ارائه می دهند. با رمزگذاری کلیه اطلاعات موجود در این نشانه می توان یک لایه امنیتی بیشتر اضافه کرد و از این طریق آن را ایمن تر کرد. برخی منابع برای یادگیری بیشتر در مورد JWT عبارتند از:
Getting started with JSON web tokens by Auth0
Using JSON web tokens as API keys by Auth0
از این لینک ها زیر می توانید آمورش های بیشتری برای لینوکس پیدا کنید :
استفاده از nsh برای دستورات از راه دور اوبونتو 18 – میزبانی وب سایت با Caddy اوبونتو 18
تنظیم سرور ذخیره سازی آبجکت با استفاده از Minio در اوبونتو 18 – ضبط و اشتراک گذاری ترمینال با Terminalizer اوبونتو
تنظیم مسیریابی شرطی و پاسخگو با React Router v4 – ایجاد یک URL کوتاه کننده با Django و GraphQL
یک برنامه ردیابی سلامت را با React ،GraphQL و Okta – ساخت برنامه چت زمان حقیقی React و GraphQL
به روزرسانی فیلترهای مرتب سازی Angular (زاویه ای) – با استفاده از React ، Superagent و API اینستاگرام
نحوه ساختن یک برنامه جهانی با Nuxt.js و Django – دکمه دانلود با ریزتعاملات با CSS ، anime.js و segment.js
نحوه اضافه کردن عکسهای پیشرفته در Node و Express – با Vue ،GraphQL و Apollo Client یک وبلاگ ساخت
یک برنامه SSR با روتر Preact ، Unistore و Preact بسازید – ساخت برنامه های وب پیشرونده با Angular
اشکال زدایی JavaScript در تولید با نقشه های منبع – می توان با Koa برنامه “سلام جهانی” ساخت
ساختن یک برنامه با Node ، React ، Okta – مدیریت حالت فرم در React با Redux Form
نحوه تنظیم Laravel ، Nginx و MySQL – ارتقاء از AngularJS به Angular با ngUpgrade
استفاده از ویژوال استودیو از راه دور – احراز هویت API با JSON Web Tokens و Passport
راه اندازی یک پروژه React با Parcel – ایجاد Swiper مانند Netflix را در Vue
ساختن یک ربات تلگرام با Laravel و BotMan – استفاده از map، filter، و reduce در جاوااسکریپت
چگونه می توان موتور جستجوی زمان واقعی را با Vue – ساختن سیستم مستندات (Documentation) با Vue و VuePress
استفاده از اشتراک زنده با کد ویژوال استودیو – ساخت یک مقیاس اندازه گیری قدرت رمز عبور را در React
شروع عملی GraphQL با Node.js و Express – ساخت یک برنامه آب و هوا در Django
نحوه نصب Discourse روی Ubuntu 18 – تأیید رمز عبور با استفاده از درخواست فرم Laravel
نحوه نصب MySQL در CentOS 8 – استفاده از پسوند PDO PHP برای انجام تراکنش MySQL
نصب و پیکربندی SNMP Daemon و Client در Ubuntu 18 – نصب Linux، Nginx، MariaDB،PHP در Debian 10
کلمات کلیدی خرید سرور
خرید vps – خرید سرور مجازی – خرید سرور – سرور هلند – فروش vps – سرور مجازی آمریکا – خریدvps – سرور مجازی هلند – فروش سرور مجازی – سرور آمریکا – vps – سرور مجازی انگلیس – سرور مجازی آلمان – سرور مجازی کانادا – خرید vps آمریکا – خرید وی پی اس – سرور – خرید سرور مجازی هلند – vps خرید – سرور مجازی فرانسه – سرور مجازی هلند – خرید vps آمریکا – خرید سرور مجازی ارزان هلند – vps – خرید vps هلند – خرید سرور مجازی آمریکا – خرید vps فرانسه – تست vps – سرور مجازی تست – سرور مجازی ویندوز – ارزانترین vps – خرید وی پی اس – vps ارزان –
https://vpsgol.net/product/vps-germany/
https://vpsgol.net/product/vps-usa/
https://vpsgol.net/product/vps-france/
https://vpsgol.net/product/vps-canada/
https://vpsgol.net/product/vps-poland/
https://vpsgol.net/product/vps-netherlands/
https://vpsgol.net/product/vps-england/