مقدمة: لماذا نحتاج OAuth 2.0 و JWT في Go؟
\nتطبيقات الويب وواجهات API الحديثة نادرًا ما تستغني عن نظام الترخيص. إذا كنت تكتب بلغة Go (Golang) وتريد حماية نقاط النهاية الخاصة بك، فأنت بحاجة إلى فهم تقنيتين رئيسيتين: OAuth 2.0 (بروتوكول تفويض الوصول) و JWT (رمز الويب JSON - تنسيق رمز مضغوط).
\nفي هذه المقالة، سنشرح كيفية تنفيذ ترخيص آمن في Go من الصفر. ستتعلم:
\n- \n
- الفرق بين OAuth 2.0 و JWT وكيف يعملان معًا. \n
- كيفية إنشاء والتحقق من رموز JWT في Go. \n
- كيفية بناء ترخيص OAuth 2.0 أساسي (تدفق بيانات الاعتماد الخاصة بالعميل). \n
- كيفية حماية REST API باستخدام الوسيطة (middleware). \n
المقالة موجهة للمطورين المبتدئين الذين لديهم معرفة أساسية بـ Go وخوادم HTTP.
\n\nالأساسيات: OAuth 2.0 و JWT ليسا نفس الشيء
\nكثير من المبتدئين يخلطون بين هذين المفهومين. دعنا نوضح الأمور من البداية.
\n\nما هو OAuth 2.0؟
\nOAuth 2.0 هو بروتوكول ترخيص يسمح لخدمة (عميل) بالحصول على وصول محدود إلى موارد خدمة أخرى (خادم) نيابة عن المستخدم. تخيل أنك تريد تسجيل الدخول إلى موقع عبر Google. الموقع لا يحصل على كلمة مرورك - بل يحصل من Google على رمز مؤقت يمنح الوصول فقط إلى بريدك الإلكتروني (وبموافقتك).
\nالأدوار الرئيسية في OAuth 2.0:
\n- \n
- مالك المورد - صاحب البيانات (عادة المستخدم). \n
- العميل - التطبيق الذي يريد الحصول على الوصول. \n
- خادم الترخيص - الخادم الذي يصدر الرموز بعد التحقق.
- خادم المورد - الخادم الذي يخزن البيانات المحمية ويتحقق من الرموز.
ما هو JWT؟
\nJWT (JSON Web Token) هو تنسيق الرمز نفسه. وهو عبارة عن سلسلة من ثلاثة أجزاء مفصولة بنقاط: header.payload.signature. يمكن أن يحتوي JWT على أي بيانات (مثل معرف المستخدم، الدور، تاريخ الانتهاء) وهو موقع بمفتاح سري لمنع التزوير.
OAuth 2.0 غير مرتبط بـ JWT - يمكن أن يكون الرمز أي سلسلة. لكن عمليًا، يُستخدم JWT في أغلب الأحيان لأنه مكتفي ذاتيًا: لا يحتاج الخادم إلى تخزين الجلسات في قاعدة البيانات، يمكن التحقق من جميع المعلومات فورًا.
\n\nتنفيذ JWT في Go: إنشاء والتحقق من الرموز
\nلنبدأ بالتطبيق العملي. للعمل مع JWT في Go، سنستخدم مكتبة golang-jwt/jwt/v5. قم بتثبيتها:
go get github.com/golang-jwt/jwt/v5\n\nإنشاء رمز الوصول (Access Token)
\nلننشئ دالة تأخذ معرف المستخدم وتعيد رمز JWT موقعًا بصلاحية ساعة واحدة.
\npackage main\n\nimport (\n "time"\n "github.com/golang-jwt/jwt/v5"\n)\n\nvar jwtSecret = []byte("your-secret-key") // في الإنتاج، خزنه في .env!\n\ntype Claims struct {\n UserID uint `json:"user_id"`\n jwt.RegisteredClaims\n}\n\nfunc GenerateAccessToken(userID uint) (string, error) {\n claims := Claims{\n UserID: userID,\n RegisteredClaims: jwt.RegisteredClaims{\n ExpiresAt: jwt.NewNumericDate(time.Now().Add(time.Hour)),\n IssuedAt: jwt.NewNumericDate(time.Now()),\n Issuer: "my-app",\n },\n }\n token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)\n return token.SignedString(jwtSecret)\n}\n\nالتحقق من JWT وتحليله
\nالآن لنكتب وسيطة (middleware) تتحقق من الرمز في العنوان Authorization: Bearer <token>.
func ValidateToken(tokenString string) (*Claims, error) {\n token, err := jwt.ParseWithClaims(tokenString, &Claims{}, func(token *jwt.Token) (interface{}, error) {\n // نتحقق من استخدام طريقة التوقيع الصحيحة\n