رموز الويب JSON (JWT): دليل شامل
تعلم كل شيء عن JWT. البنية، الاستخدام، الأمان، وأفضل الممارسات مع أمثلة عملية.
Big JSON Team
• Technical WriterExpert in JSON data manipulation, API development, and web technologies. Passionate about creating tools that make developers' lives easier.
# رموز الويب JSON (JWT): دليل شامل
JWT هو معيار مفتوح (RFC 7519) لإنشاء رموز وصول آمنة.
ما هو JWT؟
التعريف
JWT (JSON Web Token) هو رمز مشفر يحتوي على معلومات المستخدم بتنسيق JSON.
الاستخدامات
- المصادقة - تسجيل الدخول
- التفويض - التحقق من الصلاحيات
- تبادل المعلومات - بشكل آمن
مثال JWT
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
بنية JWT
JWT يتكون من ثلاثة أجزاء مفصولة بنقاط:
1. Header (الرأس)
{
"alg": "HS256",
"typ": "JWT"
}
- alg: الخوارزمية (HS256, RS256, etc.)
- typ: النوع (دائماً JWT)
2. Payload (الحمولة)
{
"sub": "1234567890",
"name": "أحمد محمد",
"admin": true,
"iat": 1516239022,
"exp": 1516242622
}
المطالبات (Claims):
- sub: Subject (معرف المستخدم)
- name: الاسم
- admin: صلاحيات
- iat: وقت الإصدار
- exp: وقت الانتهاء
3. Signature (التوقيع)
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret
)
إنشاء JWT
Node.js
const jwt = require('jsonwebtoken');
// السر (احفظه بأمان!)
const SECRET = 'your-secret-key';
// البيانات
const payload = {
userId: 123,
username: 'ahmed',
email: 'ahmed@example.com'
};
// إنشاء Token
const token = jwt.sign(payload, SECRET, {
expiresIn: '1h' // ينتهي بعد ساعة
});
console.log(token);
Python
import jwt
import datetime
# السر
SECRET = 'your-secret-key'
# البيانات
payload = {
'user_id': 123,
'username': 'ahmed',
'email': 'ahmed@example.com',
'exp': datetime.datetime.utcnow() + datetime.timedelta(hours=1)
}
# إنشاء Token
token = jwt.encode(payload, SECRET, algorithm='HS256')
print(token)
مع خيارات إضافية
const token = jwt.sign(
{
userId: 123,
username: 'ahmed'
},
SECRET,
{
expiresIn: '24h', // ينتهي بعد 24 ساعة
issuer: 'myapp', // من أصدره
audience: 'myapp-users' // لمن
}
);
التحقق من JWT
Node.js
const jwt = require('jsonwebtoken');
const token = 'eyJhbGc...';
try {
// التحقق
const decoded = jwt.verify(token, SECRET);
console.log('صالح:', decoded);
console.log('معرف المستخدم:', decoded.userId);
} catch (error) {
console.error('Token غير صالح:', error.message);
}
Python
import jwt
token = 'eyJhbGc...'
try:
# التحقق
decoded = jwt.decode(token, SECRET, algorithms=['HS256'])
print('صالح:', decoded)
print('معرف المستخدم:', decoded['user_id'])
except jwt.ExpiredSignatureError:
print('Token منتهي')
except jwt.InvalidTokenError:
print('Token غير صالح')
الاستخدام في API
Express Middleware
const jwt = require('jsonwebtoken');
// Middleware للمصادقة
function authenticateToken(req, res, next) {
// قراءة Token من Header
const authHeader = req.headers['authorization'];
const token = authHeader && authHeader.split(' ')[1]; // Bearer TOKEN
if (!token) {
return res.status(401).json({ error: 'Token مطلوب' });
}
try {
const user = jwt.verify(token, SECRET);
req.user = user;
next();
} catch (error) {
return res.status(403).json({ error: 'Token غير صالح' });
}
}
// استخدام Middleware
app.get('/api/profile', authenticateToken, (req, res) => {
res.json({
user: req.user
});
});
Flask
from flask import Flask, request, jsonify
import jwt
from functools import wraps
app = Flask(__name__)
SECRET = 'your-secret-key'
def token_required(f):
@wraps(f)
def decorated(args, kwargs):
token = request.headers.get('Authorization')
if not token:
return jsonify({'error': 'Token مطلوب'}), 401
try:
# إزالة "Bearer " من البداية
token = token.split(' ')[1] if ' ' in token else token
data = jwt.decode(token, SECRET, algorithms=['HS256'])
request.user = data
except:
return jsonify({'error': 'Token غير صالح'}), 403
return f(args, *kwargs)
return decorated
@app.route('/api/profile')
@token_required
def profile():
return jsonify({'user': request.user})
نظام تسجيل دخول كامل
Server (Node.js)
const express = require('express');
const jwt = require('jsonwebtoken');
const bcrypt = require('bcrypt');
const app = express();
app.use(express.json());
const SECRET = 'your-secret-key';
const users = []; // في الواقع، استخدم قاعدة بيانات
// تسجيل مستخدم جديد
app.post('/api/register', async (req, res) => {
const { username, password, email } = req.body;
// تشفير كلمة السر
const hashedPassword = await bcrypt.hash(password, 10);
const user = {
id: users.length + 1,
username,
password: hashedPassword,
email
};
users.push(user);
res.status(201).json({
message: 'تم التسجيل بنجاح'
});
});
// تسجيل الدخول
app.post('/api/login', async (req, res) => {
const { username, password } = req.body;
// البحث عن المستخدم
const user = users.find(u => u.username === username);
if (!user) {
return res.status(401).json({ error: 'اسم المستخدم أو كلمة السر خاطئة' });
}
// التحقق من كلمة السر
const validPassword = await bcrypt.compare(password, user.password);
if (!validPassword) {
return res.status(401).json({ error: 'اسم المستخدم أو كلمة السر خاطئة' });
}
// إنشاء Token
const token = jwt.sign(
{
userId: user.id,
username: user.username
},
SECRET,
{ expiresIn: '24h' }
);
res.json({
token,
user: {
id: user.id,
username: user.username,
email: user.email
}
});
});
// مسار محمي
app.get('/api/protected', authenticateToken, (req, res) => {
res.json({
message: 'مرحباً بك!',
user: req.user
});
});
app.listen(3000);
Client (JavaScript)
// تسجيل الدخول
async function login(username, password) {
const response = await fetch('/api/login', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ username, password })
});
const data = await response.json();
if (response.ok) {
// حفظ Token
localStorage.setItem('token', data.token);
console.log('تم تسجيل الدخول');
} else {
console.error('خطأ:', data.error);
}
}
// طلب محمي
async function fetchProtected() {
const token = localStorage.getItem('token');
const response = await fetch('/api/protected', {
headers: {
'Authorization': Bearer ${token}
}
});
const data = await response.json();
console.log(data);
}
// تسجيل الخروج
function logout() {
localStorage.removeItem('token');
console.log('تم تسجيل الخروج');
}
Refresh Tokens
نظام Token مزدوج
// إنشاء Access و Refresh Tokens
function generateTokens(user) {
const accessToken = jwt.sign(
{ userId: user.id, username: user.username },
SECRET,
{ expiresIn: '15m' } // 15 دقيقة
);
const refreshToken = jwt.sign(
{ userId: user.id },
REFRESH_SECRET,
{ expiresIn: '7d' } // 7 أيام
);
return { accessToken, refreshToken };
}
// تجديد Access Token
app.post('/api/refresh', (req, res) => {
const { refreshToken } = req.body;
if (!refreshToken) {
return res.status(401).json({ error: 'Refresh token مطلوب' });
}
try {
const decoded = jwt.verify(refreshToken, REFRESH_SECRET);
// إنشاء access token جديد
const accessToken = jwt.sign(
{ userId: decoded.userId },
SECRET,
{ expiresIn: '15m' }
);
res.json({ accessToken });
} catch (error) {
return res.status(403).json({ error: 'Refresh token غير صالح' });
}
});
الأمان
1. لا تخزن معلومات حساسة
// سيء
const token = jwt.sign({
username: 'ahmed',
password: 'secret123', // خطر!
creditCard: '1234-5678' // خطر جداً!
}, SECRET);
// جيد
const token = jwt.sign({
userId: 123,
username: 'ahmed',
roles: ['user']
}, SECRET);
2. استخدم HTTPS
جميع الطلبات يجب أن تكون عبر HTTPS.
3. حدد وقت انتهاء قصير
const token = jwt.sign(payload, SECRET, {
expiresIn: '15m' // 15 دقيقة (موصى به)
});
4. احفظ السر بأمان
// سيء
const SECRET = 'mySecret123';
// جيد - استخدم متغيرات البيئة
const SECRET = process.env.JWT_SECRET;
5. تحقق من الخوارزمية
// التحقق مع تحديد الخوارزمية
jwt.verify(token, SECRET, { algorithms: ['HS256'] });
الخوارزميات
HMAC (Symmetric)
// HS256 - نفس السر للتوقيع والتحقق
const token = jwt.sign(payload, SECRET, { algorithm: 'HS256' });
const decoded = jwt.verify(token, SECRET);
RSA (Asymmetric)
const fs = require('fs');
// مفاتيح عامة وخاصة
const privateKey = fs.readFileSync('private.key');
const publicKey = fs.readFileSync('public.key');
// التوقيع بالمفتاح الخاص
const token = jwt.sign(payload, privateKey, { algorithm: 'RS256' });
// التحقق بالمفتاح العام
const decoded = jwt.verify(token, publicKey);
المطالبات القياسية
const token = jwt.sign(
{
// معرف الموضوع
sub: '1234567890',
// الاسم
name: 'أحمد محمد',
// وقت الإصدار
iat: Math.floor(Date.now() / 1000),
// وقت الانتهاء
exp: Math.floor(Date.now() / 1000) + (60 60),
// من أصدره
iss: 'https://myapp.com',
// الجمهور
aud: 'https://myapp.com/users',
// معرف فريد
jti: 'unique-token-id'
},
SECRET
);
فك تشفير بدون التحقق
// لعرض المحتوى فقط (غير آمن للاستخدام)
const decoded = jwt.decode(token);
console.log(decoded);
// مع التحقق (آمن)
const verified = jwt.verify(token, SECRET);
معالجة الأخطاء
const jwt = require('jsonwebtoken');
try {
const decoded = jwt.verify(token, SECRET);
} catch (error) {
if (error.name === 'TokenExpiredError') {
console.error('Token منتهي');
} else if (error.name === 'JsonWebTokenError') {
console.error('Token غير صالح');
} else if (error.name === 'NotBeforeError') {
console.error('Token غير نشط بعد');
} else {
console.error('خطأ:', error.message);
}
}
أفضل الممارسات
1. استخدم Refresh Tokens
للأمان الإضافي وتجربة مستخدم أفضل.
2. قائمة سوداء للـ Tokens
const blacklist = new Set();
// إبطال token
function invalidateToken(token) {
blacklist.add(token);
}
// التحقق
function isTokenValid(token) {
return !blacklist.has(token);
}
3. راقب النشاط المشبوه
احفظ سجل لاستخدام الـ tokens.
4. استخدم JTI للتتبع
معرف فريد لكل token.
أدوات مفيدة
jwt.io
موقع لفك تشفير وتصحيح JWT.
Libraries
- Node.js: jsonwebtoken
- Python: PyJWT
- PHP: firebase/php-jwt
- Java: jjwt
الملخص
JWT:
- رمز مشفر آمن
- يحتوي على معلومات JSON
- مثالي للمصادقة
- استخدم بحذر وأمان
اتبع أفضل الممارسات للأمان!
مقالات ذات صلة
JavaScript و JSON: الدليل الكامل
تعلم كيفية العمل مع JSON في JavaScript. JSON.parse، JSON.stringify، وأفضل الممارسات.
فهم JSON Schema: دليل شامل
تعلم كيفية استخدام JSON Schema للتحقق من صحة البيانات. التعريفات، الأمثلة، وأفضل الممارسات.
JSON APIs وخدمات REST
تعلم كيفية العمل مع JSON في REST APIs. أفضل الممارسات، أمثلة، وتقنيات متقدمة.