رموز JWT في Go (Golang): دليل كامل مع مكتبة golang-jwt
JSON Web Token (JWT) هو معيار مفتوح (RFC 7519) لإنشاء رموز الوصول بناءً على JSON. يُستخدم JWT على نطاق واسع للمصادقة وتبادل المعلومات بين الأطراف. في Go (Golang)، المكتبة الأكثر شيوعًا والمدعومة بنشاط للعمل مع JWT هي golang-jwt/jwt/v5. في هذه المقالة، سنشرح بالتفصيل كيفية تثبيت هذه المكتبة وتكوينها واستخدامها لإنشاء تطبيقات ويب آمنة.
تثبيت مكتبة golang-jwt
للبدء، أضف المكتبة إلى مشروعك باستخدام go get:
go get github.com/golang-jwt/jwt/v5بعد التثبيت، قم باستيراد الحزمة إلى الكود الخاص بك:
import ( "github.com/golang-jwt/jwt/v5")المكونات الأساسية لـ JWT
يتكون JWT من ثلاثة أجزاء مفصولة بنقاط: Header (الرأس)، Payload (الحمولة)، وSignature (التوقيع). توفر مكتبة golang-jwt هياكل مناسبة للعمل مع كل منها:
- Header — يحتوي على بيانات وصفية حول نوع الرمز وخوارزمية التوقيع (مثل HS256، RS256).
- Payload — يحتوي على claims (المطالبات)، مثل معرف المستخدم ووقت الانتهاء والأدوار والبيانات الأخرى.
- Signature — يتم إنشاؤه باستخدام مفتاح سري أو زوج من المفاتيح (خاص/عام).
إنشاء رمز وصول JWT (Access Token)
لنلقِ نظرة على مثال لإنشاء رمز وصول باستخدام خوارزمية HS256 (تشفير متماثل). أولاً، نحدد هيكلًا مع claims مخصصة:
type CustomClaims struct { UserID int `json:"user_id"` Username string `json:"username"` jwt.RegisteredClaims}الآن، لننشئ دالة لتوليد الرمز:
func GenerateAccessToken(userID int, username string, secretKey []byte) (string, error) { claims := CustomClaims{ UserID: userID, Username: username, RegisteredClaims: jwt.RegisteredClaims{ ExpiresAt: jwt.NewNumericDate(time.Now().Add(15 * time.Minute)), IssuedAt: jwt.NewNumericDate(time.Now()), Subject: "access", }, }
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) return token.SignedString(secretKey)}هنا، نضبط عمر الرمز ليكون 15 دقيقة، وهي ممارسة قياسية لرمز الوصول. استخدم jwt.NewNumericDate() لتنسيق الوقت بشكل صحيح.
التحقق من الرمز وتحليله (Parsing)
للتحقق من صحة الرمز، يجب استخراج claims والتحقق من التوقيع:
func ValidateToken(tokenString string, secretKey []byte) (*CustomClaims, error) { token, err := jwt.ParseWithClaims(tokenString, &CustomClaims{}, func(token *jwt.Token) (interface{}, error) { // نتحقق من استخدام خوارزمية التوقيع المتوقعة if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok { return nil, fmt.Errorf("طريقة توقيع غير متوقعة: %v", token.Header["alg"]) } return secretKey, nil })
if err != nil { return nil, err }
if claims, ok := token.Claims.(*CustomClaims); ok && token.Valid { return claims, nil }
return nil, fmt.Errorf("رمز غير صالح")}من المهم التحقق من خوارزمية التوقيع في دالة الاستدعاء (callback) لتجنب الهجمات المتعلقة باستبدال الخوارزمية.
إنشاء وتحديث Refresh Token
لتعزيز الأمان، غالبًا ما يُستخدم زوج من الرموز: رمز وصول قصير العمر ورمز تحديث طويل العمر. يسمح رمز التحديث بالحصول على رمز وصول جديد دون إعادة إدخال اسم المستخدم وكلمة المرور.
func GenerateRefreshToken(userID int, secretKey []byte) (string, error) {