← العودة إلى المدونة

رموز الويب JSON (JWT): دليل شامل

تعلم كل شيء عن JWT. البنية، الاستخدام، الأمان، وأفضل الممارسات مع أمثلة عملية.

Big JSON Team15 دقيقة للقراءةsecurity
B

Big JSON Team

Technical Writer

Expert in JSON data manipulation, API development, and web technologies. Passionate about creating tools that make developers' lives easier.

15 دقيقة قراءة

# رموز الويب 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
  • مثالي للمصادقة
  • استخدم بحذر وأمان

اتبع أفضل الممارسات للأمان!

Share:

مقالات ذات صلة

Read in English