1.3
Stateless বনাম Stateful Server, Cookie ও Session
Stateless Protocol কীভাবে তোমাকে মনে রাখে: Session, Cookie, Token, এবং Scale করলে কী ভাঙে।
34 মিনিট পড়া + Animation
টিপস: ডটেড-আন্ডারলাইন করা যেকোনো শব্দে ট্যাপ বা Hover করলে তার অর্থ দেখবে।
এই Lesson শেষে তুমি পারবে
- “HTTP Stateless” মানে কী, এবং Stateful ও Stateless Server-এর পার্থক্য ব্যাখ্যা করতে।
- দ্বিতীয় একটি Server যোগ করলে কেন In-memory Session ভেঙে পড়ে তা দেখাতে, এবং তিনটি সমাধান তুলনা করতে: Sticky Session, কেন্দ্রীয় Session Store, ও Stateless Token।
- Cookie ঠিক কীভাবে কাজ করে তা বর্ণনা করতে, Session বনাম Persistent Cookie এবং Domain, Path, Expires/Max-Age, Secure, HttpOnly ও SameSite Attribute-সহ।
- Server-side Session দিয়ে একটি পূর্ণ লগইন ধাপে ধাপে বলতে: তৈরি, খোঁজা, মেয়াদ শেষ, Logout ও ID বদলানো।
- একটি JWT পড়তে, তার Signature ও মেয়াদ ব্যাখ্যা করতে, এবং তার দুর্বল দিক (বাতিল করা) স্বল্প মেয়াদ ও Refresh Token দিয়ে সামলাতে।
- XSS ও CSRF আক্রমণ ধাপে ধাপে ব্যাখ্যা করতে, Auth-এর জন্য Cookie ও localStorage-এর মধ্যে বেছে নিতে, এবং কখন একটি System সত্যিই Stateful (WebSocket) তা চিনতে।
#সমস্যা: HTTP ভুলে যায়
HTTP Design অনুযায়ীই Stateless। প্রতিটি Request একটি সম্পূর্ণ, স্বাধীন বার্তা, আর Protocol নিজে আগের কোনো Request মনে রাখে না। তুমি লগইন করে পরের Page খুললে HTTP-র কোথাও লেখা থাকে না যে “এ সেই একই ব্যক্তি যে এইমাত্র লগইন করল”।
এই Design ইচ্ছাকৃত। যে Server-কে দুই Request-এর মাঝে কিছু মনে রাখতে হয় না, সে সহজ, যেকোনো মুহূর্তে Restart করা যায়, এবং Load Balancer-এর পেছনে তার একশোটা কপি চালানো যায়। কিন্তু প্রায় প্রতিটি বাস্তব Application-কে কিছু না কিছু মনে রাখতেই হয়: তুমি কে, তোমার Cart-এ কী আছে, কোন ভাষা বেছে নিয়েছ।
তাই State-কে কোথাও না কোথাও থাকতে হয়: Server-এর Memory-তে, একটি ভাগাভাগি করা Store-এ, অথবা Client-এর কাছে, প্রতিটি Request-এর সাথে ঘুরে বেড়িয়ে। কোনটি বেছে নেবে তা System Design-এর সবচেয়ে গুরুত্বপূর্ণ সিদ্ধান্তগুলোর একটি, আর এটাই এই Lesson-এর বিষয়।
#Stateful বনাম Stateless Server
HTTP Protocol Stateless, কিন্তু তার ওপরের Server Application দুইভাবেই Design করা যায়।
Stateless Server:
Req 1 (User ID + Token) ───► [Server] ───► Database lookup ───► Res
Req 2 (User ID + Token) ───► [Server] ───► Database lookup ───► Res
(Server-এর Memory-তে কোনো State জমা থাকে না)
Stateful Server:
Req 1 (Login) ───► [Server] ───► Save session in RAM/disk
Req 2 (Get profile) ───► [Server] ───► Read session from RAM ──► Res
(Server Client-এর বিগত ইতিহাস মনে রাখে)
Stateless বনাম Stateful: স্মৃতি থাকে কোথায়?
একই দুটি Request, দুটি Design। Badge-গুলো দেখো: কোন পক্ষ কী মনে রাখছে তা দেখায়।
পরিস্থিতি
Server দুই Request-এর মাঝে তোমাকে মনে রাখে।
Request ১: তুমি লগইন করলে।
#Stateful Server
Stateful Architecture-এ Server নিজের Memory-তে (RAM বা In-process Store) প্রতিটি Client-এর আগের Request-এর অবস্থা বা State (Session Data) সংরক্ষণ করে রাখে।
- কীভাবে কাজ করে: Client প্রথমবার লগইন করলে Server একটি Session তৈরি করে Memory-তে রেখে দেয়। পরবর্তী যেকোনো Request-এ Server নিজের Memory থেকে Client-এর পরিচয় বা State দেখে নেয়।
- সুবিধা: প্রতিটি Request-এ ভারী Authentication বা নতুন করে Data পাঠানোর প্রয়োজন হয় না। RAM পড়াই সবচেয়ে দ্রুত খোঁজা।
- অসুবিধা:
- Horizontal Scaling সমস্যা। ধরো তোমার ৩টি Server আছে (A, B, C)। User Server A-তে লগইন করল, তাই তার Session থাকে A-এর RAM-এ। পরের Request যদি Load Balancer-এর মাধ্যমে Server B-তে যায়, B তাকে চিনবে না, যদি না Sticky Session বা কেন্দ্রীয় Session Store থাকে।
- Memory খরচ। ব্যবহারকারী বাড়লে Server-এর RAM দ্রুত পূর্ণ হয়ে যায়।
- ভঙ্গুরতা। Restart, Crash বা Deploy RAM মুছে দেয় এবং সবাইকে লগ-আউট করে দেয়।
#Stateless Server
Stateless Architecture-এ Server দুই Request-এর মাঝে Client সম্পর্কে কোনো ইতিহাস বা স্মৃতি রাখে না। প্রতিটি Request-কে সম্পূর্ণ স্বাধীন (Independent) হিসেবে দেখা হয়।
- কীভাবে কাজ করে: Client-কেই প্রতিটি Request-এর সাথে নিজের পরিচয়পত্র পাঠাতে হয়, যেমন একটি JWT বা API Key। Server শুধু সেটি যাচাই করে উত্তর দেয়; Memory-তে কিছু সেভ করে না।
- সুবিধা:
- অসাধারণ Scalability। কোনো Server-এ State না থাকায় ১টি Server-এর জায়গায় ১০০টি বসালেও যেকোনো Server যেকোনো Request প্রক্রিয়া করতে পারে।
- Fault Tolerance। একটি Server Crash করলেও Client-এর Data হারায় না, কারণ State আছে Client-এর কাছে (বা ভাগাভাগি করা Database-এ)।
- অসুবিধা: প্রতিটি Request-এ বাড়তি Data (Token) যায়, যা Network Payload সামান্য বাড়ায়, আর প্রতিটি Request যাচাই করতে হয়।
| বৈশিষ্ট্য | Stateful Server | Stateless Server |
|---|---|---|
| State কোথায় থাকে | Server-এর Memory-তে | Client-এর পাঠানো Token-এ (বা ভাগাভাগি করা Store-এ) |
| Scalability | Scale করা কঠিন ও জটিল | অত্যন্ত সহজ (Microservices-এর জন্য সেরা) |
| Server Memory | Client বৃদ্ধির সাথে বাড়ে | প্রতি Client-এ বাড়তি চাপ নেই |
| Server Crash বা Deploy | তার Session হারিয়ে যায় | কিছুই হারায় না |
| Load Balancing | Sticky Session বা ভাগাভাগি Store লাগে | যেকোনো Server, যেকোনো Request |
| প্রতি Request-এর খরচ | ছোট ID; দ্রুত Memory Lookup | বড় Token; Signature যাচাই |
| Logout / Access বাতিল | সহজ: Session মুছে ফেলো | কঠিন: মেয়াদ শেষ না হওয়া পর্যন্ত Token বৈধ |
| সাধারণ ব্যবহার | Real-time Multiplayer Game, Chat Room, WebSocket Connection | REST API, আধুনিক Web ও Mobile Backend |
#Scaling: Session কোথায় থাকবে?
Load Balancer-এর পেছনে একাধিক Server চালানোর মুহূর্তেই In-memory Session ভেঙে পড়ে। এর তিনটি প্রচলিত সমাধান আছে।
Load Balancer-এর পেছনে Session
তিনটি একই রকম Server। Rahim-এর Session কোথায় থাকলে যেকোনোটি তাকে সেবা দিতে পারবে?
পরিস্থিতি
Rahim লগইন করল। Load Balancer ঘটনাক্রমে তাকে Server A-তে পাঠাল, যে নিজের RAM-এ তার Session রাখল।
| পদ্ধতি | কীভাবে | সুবিধা | অসুবিধা |
|---|---|---|---|
| Sticky Session (Session Affinity) | Load Balancer একটি Cookie বা Client-এর IP দেখে একই User-কে সবসময় একই Server-এ পাঠায় | Code বদলাতে হয় না; দ্রুত | অসম চাপ; Server Crash বা Deploy-এ তার User-রা লগ-আউট; নতুন Server যোগ করলে পুরনো User-দের লাভ নেই |
| কেন্দ্রীয় Session Store | Session থাকে Redis-এ (বা Database-এ), যা সব Server ভাগাভাগি করে | App Server Stateless হয়; Logout ও বাতিল করা সহজ | একটি বাড়তি Network Hop (Redis-এ এক Millisecond-এর অনেক কম); Store-কে সবসময় সচল রাখতে হয় |
| Stateless Token (JWT) | স্বাক্ষরিত Session Data Client-এর সাথে ঘোরে | কোনো Lookup নেই, ভাগাভাগি Store নেই; যেকোনো জায়গায় Scale | বাতিল করা কঠিন; Token-এর আকার; Secret Key সামলানো |
বাস্তবে বেশিরভাগ Web Application কেন্দ্রীয় Store (প্রতিটি Session-এ মেয়াদসহ Redis) বা Token ব্যবহার করে, আর Sticky Session রাখে শুধু স্বভাবগতভাবে Stateful Connection-এর জন্য, যেমন WebSocket।
#Cookie
যেহেতু HTTP Stateless, কোনো User লগইন করে পরের Page-এ গেলে Server ভুলে যায় User-টি কে। এই সমস্যার সমাধান করতেই Cookie ও Session একসাথে কাজ করে।
Cookie হলো Browser-এ কোনো Website-এর জন্য রাখা ছোট ছোট Text Data (প্রতিটি সর্বোচ্চ প্রায় ৪ KB)।
- কীভাবে কাজ করে: Server Response-এ
Set-Cookie: key=valueHeader পাঠিয়ে Browser-কে এটি সেভ করার নির্দেশ দেয়। Browser এটি নিজের Cookie Jar-এ রেখে দেয়। এরপর থেকে ওই Domain-এ যত Request যাবে, Browser স্বয়ংক্রিয়ভাবেCookieHeader-এ সেই Cookie ফেরত পাঠাবে।
HTTP/1.1 200 OK
Set-Cookie: session_id=xyz987; Path=/; HttpOnly; Secure; SameSite=Lax
Set-Cookie: lang=bn; Max-Age=2592000; Path=/
GET /dashboard HTTP/1.1
Host: shop.example.com
Cookie: session_id=xyz987; lang=bn
#Cookie-র প্রকারভেদ
- Session Cookie:
ExpiresবাMax-Ageনেই; Browser বন্ধ করলে মুছে যায়। - Persistent Cookie: একটি নির্দিষ্ট তারিখ (
Expires=<date>) পর্যন্ত বা নির্দিষ্ট সেকেন্ড (Max-Age=<seconds>) পর্যন্ত টিকে থাকে, Browser Restart-এর পরও। “Remember me” এটিই ব্যবহার করে।
Cookie-কে First-party (Address Bar-এ থাকা সাইট যেটি Set করেছে) বা Third-party (Page-এর ভেতরে বসানো অন্য Domain, যেমন বিজ্ঞাপন Network যেটি Set করেছে) হিসেবেও ভাগ করা হয়। আধুনিক Browser ক্রমশ Third-party Cookie আটকাচ্ছে, এজন্যই Cross-site Tracking ও কিছু বসানো Login-এর ধরন বদলে গেছে।
#Cookie Attribute
| Attribute | কী করে | Session Cookie-র জন্য পরামর্শ |
|---|---|---|
Expires / Max-Age | Cookie কখন মরবে। না থাকলে Session Cookie। Max-Age=0 মুছে দেয় | বাদ দাও, বা স্বল্প রাখো |
Domain | কোন Host এটি পাবে। না থাকলে শুধু যে Host Set করেছে সেটিই। Domain=example.com সব Subdomain-কে অন্তর্ভুক্ত করে | বাদ দাও (Host-only) |
Path | শুধু এই Path-এর নিচের URL-এ পাঠানো হয় | Path=/ |
Secure | শুধু HTTPS-এ পাঠানো হয়, সাধারণ HTTP-তে কখনো না | সবসময় |
HttpOnly | JavaScript এটি পড়তে পারে না (document.cookie), ফলে XSS Script চুরি করতে পারে না | সবসময় |
SameSite | অন্য সাইট থেকে শুরু হওয়া Request-এ যাবে কি না: Strict, Lax বা None | Lax (বা Strict) |
SameSite-এর তিনটি মান:
- Strict: Cross-site Request-এ কখনো যায় না, এমনকি অন্য জায়গা থেকে সাইটটির Link-এ ক্লিক করলেও না (তুমি লগ-আউট অবস্থায় আছ মনে হবে)।
- Lax: Cross-site Sub-request বা POST-এ যায় না, কিন্তু Top-level GET দিয়ে সাইটে গেলে (Link-এ ক্লিক) যায়। Attribute না থাকলে আধুনিক Browser-এ এটাই Default।
- None: সবসময় যায়, Cross-site-ও; অবশ্যই
Secure-এর সাথে দিতে হয়। বসানো Widget বা Payment iframe-এর মতো সত্যিকারের Cross-site ব্যবহারে লাগে।
#Session
Session হলো Server Side-এ সংরক্ষিত তথ্যের একটি Data Structure।
- কীভাবে কাজ করে: User সঠিক Username ও Password দিয়ে লগইন করলে Server তার Backend-এ (RAM, Database বা Redis-এ) একটি অনন্য Record তৈরি করে, যেখানে User-এর সব সংবেদনশীল তথ্য থাকে: User ID, Role ইত্যাদি।
- Session ID-র সংযোগ: Server এই Session-এর জন্য একটি দীর্ঘ, এলোমেলো, অনুমান-অযোগ্য String তৈরি করে, যাকে বলে Session ID, এবং সেটি একটি Cookie-র মাধ্যমে Browser-এ পাঠিয়ে দেয়। আসল Data থাকে Server-এ; Client-এর কাছে থাকে শুধু একটি চাবি (Session ID)।
Session flow:
[Client] ─── 1. POST /login (credentials) ─────────────► [Server]
[Client] ◄── 2. Response + Set-Cookie: SessionID=123 ─── [Server] (saves 123 in RAM/DB)
[Client] ─── 3. GET /profile + Cookie: SessionID=123 ──► [Server] (finds 123 in DB)
#পূর্ণ Workflow
- User লগইন Form জমা দেয় (
POST /login)। - Server Password যাচাই করে এবং Store-এ একটি Session তৈরি করে (যেমন
session_id: xyz987)। - Server Response-এ পাঠায়:
Set-Cookie: session_id=xyz987; HttpOnly। - Browser
xyz987Cookie হিসেবে সেভ করে। - পরে User যখন Dashboard-এ যায় (
GET /dashboard), Browser Header-এর সাথে পাঠায়:Cookie: session_id=xyz987। - Server
xyz987দিয়ে Store-এ খুঁজে দেখে এটি কার Session, সেই অনুযায়ী User-কে চিহ্নিত করে Data ফেরত দেয়।
Session Cookie দিয়ে লগইন, ধাপে ধাপে
Data থাকে Server-এ; Browser-এর কাছে থাকে শুধু তার চাবি।
পরিস্থিতি
১. ব্যবহারকারী HTTPS-এ লগইন Form জমা দেয়।
#Session ঠিকভাবে করা
- Session ID হতে হবে এলোমেলো ও দীর্ঘ (Cryptographic Random Generator থেকে অন্তত ১২৮ Bit)। কখনো User ID, Counter বা Timestamp ব্যবহার করবে না: সেগুলো অনুমান করা যায়।
- Session-এর মেয়াদ রাখো: একটি Idle Timeout (যেমন ৩০ মিনিট কোনো কাজ না হলে) এবং একটি Absolute Timeout (যেমন ৭ দিন, তারপর আবার লগইন)। Redis-এ Key-তে TTL দিলেই এটি হয়ে যায়।
- লগইনের সময় Session ID বদলাও, এবং যখনই ক্ষমতা বদলায় তখনও, যাতে লগইনের আগে বসানো ID (Session Fixation) অকেজো হয়ে যায়।
- Logout-কে Server-এর Session মুছতেই হবে, শুধু Browser-এর Cookie নয়। কপি করা Cookie-ও যেন কাজ না করে।
নিজেকে যাচাই করোপ্রশ্ন
তোমার App একটি Round-robin Load Balancer-এর পেছনে তিনটি Server-এ চলে এবং প্রতিটি Server-এর RAM-এ Session রাখে। ব্যবহারকারীরা কী অভিজ্ঞতা পাবে?
#Token: JWT ও API Key
Session-এর Stateless বিকল্প হলো এমন একটি Token যা User-এর পরিচয় নিজেই বহন করে।
#একটি JWT-র গঠন
একটি JWT (JSON Web Token) হলো বিন্দু দিয়ে জোড়া base64url-encode করা তিনটি অংশ: header.payload.signature।
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI0MiIsInJvbGUiOiJjdXN0b21lciIsImV4cCI6MTc2MTMwMDAwMH0.k3Fq…
└──────────────── header ──────────────┘ └──────────────────────── payload ─────────────────────────┘ └ signature ┘
// header
{ "alg": "HS256", "typ": "JWT" }
// payload ("claims")
{ "sub": "42", "role": "customer", "iat": 1761299100, "exp": 1761300000 }
- Header: স্বাক্ষরের Algorithm।
- Payload: User সম্পর্কে দাবি (Claim):
sub(Subject, User ID),role,iat(কখন দেওয়া),exp(মেয়াদ, Unix Timestamp হিসেবে)। - Signature: Header + Payload-এর ওপর একটি Key দিয়ে হিসাব করা।
HS256-এ এটি একটি ভাগাভাগি Secret দিয়ে HMAC;RS256বাES256-এ Auth Server একটি Private Key দিয়ে স্বাক্ষর করে আর যেকোনো Service Public Key দিয়ে যাচাই করতে পারে।
কেউ Payload-এর একটি অক্ষরও বদলালে Signature আর মেলে না, তাই Server Token বাতিল করে। কিন্তু Payload শুধু Encode করা, Encrypt নয়: যে কেউ Decode করে পড়তে পারে। JWT-তে কখনো Password বা ব্যক্তিগত গোপন তথ্য রাখবে না।
JWT: একটি স্বাক্ষরিত পরিচয়পত্র
JWT যে কেউ পড়তে পারে; বৈধ JWT বানাতে পারে শুধু Key-এর মালিক।
পরিস্থিতি
Client Username ও Password দিয়ে লগইন করে।
#মেয়াদ, Refresh Token ও বাতিল করা
JWT-র বড় শক্তি (কোনো Lookup নেই) এটির দুর্বলতাও: Server দেওয়া Token “মুছে” ফেলতে পারে না। চুরি হওয়া Token exp পর্যন্ত কাজ করে। তাই প্রচলিত Design-এ দুটি Token ব্যবহার হয়:
| Access Token | Refresh Token | |
|---|---|---|
| মেয়াদ | স্বল্প: ৫–১৫ মিনিট | দীর্ঘ: কয়েক দিন থেকে সপ্তাহ |
| পাঠানো হয় | প্রতিটি API Request-এ | শুধু Token Endpoint-এ |
| যাচাই করে | Signature + মেয়াদ, Database ছাড়া | Database Lookup, তাই বাতিল করা যায় |
| চুরি হলে | কয়েক মিনিট ব্যবহারযোগ্য | বাতিল করো; Rotation পুনর্ব্যবহার ধরে ফেলে |
একজন User-কে “সব জায়গা থেকে” লগ-আউট করতে তার Refresh Token বাতিল করো (নতুন Access Token আর দেওয়া হবে না), আর জরুরি ক্ষেত্রে Token ID-র (jti) একটি ছোট নিষিদ্ধ তালিকা (Deny List) রাখো, যা ওই Token-গুলোর মেয়াদ শেষ না হওয়া পর্যন্ত API-গুলো দেখে।
API Key হলো Machine Client-এর জন্য (যেমন একটি Server যখন Payment বা Map API ডাকে) আরও সহজ এক ধরনের Token। এগুলো দীর্ঘ এলোমেলো String, Header-এ পাঠানো হয়, প্রতিটি Request-এ খুঁজে দেখা হয়, এবং Server-এ মুছে ফেলে বাতিল করা হয়।
Server-side Session (ID-সহ Cookie)JWT (স্বয়ংসম্পূর্ণ Token)
- State Server-এ (Redis/DB); Client-এর কাছে একটি এলোমেলো ID
- প্রতি Request-এ একটি Lookup
- সঙ্গে সঙ্গে Logout ও বাতিল: Session মুছে ফেলো
- ছোট Cookie
- Browser-ভিত্তিক Website-এর জন্য স্বাভাবিক পছন্দ
- State স্বাক্ষরিত Token-এর ভেতরে, Client-এর কাছে
- কোনো Lookup নেই: Signature যাচাই
- বাতিল করা কঠিন: স্বল্প মেয়াদ + Refresh Token
- বড়: প্রতিটি Request-এ কয়েকশো Byte
- API, Mobile App ও Service-to-service Call-এর জন্য স্বাভাবিক পছন্দ
#নিরাপত্তা: XSS ও CSRF
Cookie পাঠানো হয় স্বয়ংক্রিয়ভাবে, আর Token-কে কোথাও রাখতে হয়। দুটি ক্লাসিক Web আক্রমণ ঠিক এই দুটি বিষয়ের সুযোগ নেয়।
#XSS (Cross-site Scripting)
আক্রমণকারী তোমার সাইটের Page-এর ভেতরে নিজের JavaScript চালাতে সক্ষম হয়, যেমন এমন একটি Comment দিয়ে যা সাইট Escape না করেই দেখায়। সেই Script ভুক্তভোগীর Browser-এ সাইটের পূর্ণ ক্ষমতা নিয়ে চলে।
XSS: যখন আক্রমণকারীর Script তোমার সাইটে চলে
Cross-site Scripting একটি বিশ্বস্ত Page-এ JavaScript ঢুকিয়ে দেয়। সেই Script কী চুরি করতে পারে?
পরিস্থিতি
আক্রমণকারী Script Tag-সহ একটি Product Review পোস্ট করে। সাইট Escape না করেই সেটি সংরক্ষণ করে।
HttpOnlyছাড়া Scriptdocument.cookieপড়ে Session ID আক্রমণকারীর কাছে পাঠিয়ে দেয়।HttpOnlyথাকলে Cookie Script-এর কাছে অদৃশ্য, তাই চুরি করা যায় না, যদিও Page খোলা থাকা অবস্থায় Script সেখানে কাজ চালাতে পারে।localStorage-এ রাখা Token Page-এর যেকোনো Script সবসময় পড়তে পারে।- আসল সমাধান XSS ঠেকানো: সব User Content Escape করো, সরাসরি HTML বসানো এড়াও, আর একটি Content Security Policy (CSP) যোগ করো।
#CSRF (Cross-site Request Forgery)
আক্রমণকারী তোমার Cookie পড়তে পারে না, তবে তার দরকারও নেই। তার সাইটের একটি Page তোমার Browser দিয়ে তোমার ব্যাংকে একটি Request পাঠায়, আর Browser নিজে থেকেই ব্যাংকের Cookie জুড়ে দেয়।
CSRF: তোমার Browser দিয়ে আক্রমণকারীর কাজ করানো
আক্রমণকারী কখনো তোমার Cookie দেখে না। তার শুধু দরকার তোমার Browser যেন সেটি পাঠায়।
পরিস্থিতি
তুমি আগে ব্যাংকে লগইন করেছিলে। তার Cookie অন্য সাইট থেকেও পাঠানোর অনুমতি দেয় (SameSite=None)।
প্রতিরক্ষা, একসাথে ব্যবহার করো:
- Session Cookie-তে
SameSite=LaxবাStrict, যাতে Cross-site POST-এ কোনো Cookie না যায়। - CSRF Token: প্রতিটি Form-এ একটি এলোমেলো মান, যা আক্রমণকারীর Page পড়তে পারে না।
- Data বদলানো Request-এ
OriginHeader যাচাই করো। - GET দিয়ে কখনো Data বদলাবে না, কারণ Lax তবুও Top-level GET Navigation-এ Cookie পাঠায়।
#Browser Auth Token কোথায় রাখবে?
| Storage | JavaScript পড়তে পারে (XSS) | স্বয়ংক্রিয়ভাবে যায় (CSRF) | রায় |
|---|---|---|---|
HttpOnly; Secure; SameSite=Lax সহ Cookie | না | হ্যাঁ, তবে SameSite দিয়ে সীমিত | Website-এর জন্য প্রস্তাবিত |
localStorage | হ্যাঁ | না | সুবিধাজনক, কিন্তু একটি XSS Bug-এ সব Token ফাঁস |
sessionStorage | হ্যাঁ | না | localStorage-এর মতোই, Tab বন্ধ করলে মুছে যায় |
| শুধু JavaScript Memory | হ্যাঁ, Page চলা অবস্থায় | না | Reload-এ হারায়; Refresh-token Cookie-র সাথে জুড়ে ব্যবহার করো |
Mobile App-এ Cookie-র স্বয়ংক্রিয় আচরণ নেই; তারা Token রাখে Operating System-এর Secure Storage-এ (iOS-এ Keychain, Android-এ Keystore) এবং Authorization Header-এ পাঠায়।
#যখন Stateful-ই সঠিক উত্তর: WebSocket
কিছু Feature স্বভাবগতভাবেই Stateful। একটি Chat Room, Multiplayer Game বা Live Dashboard-এ ঘটনা ঘটার সঙ্গে সঙ্গে Server-কে Data Push করতে হয়। একটি WebSocket শুরু হয় Upgrade: websocket-সহ একটি HTTP Request হিসেবে, Server উত্তর দেয় 101 Switching Protocols, আর তারপর থেকে একটি দীর্ঘস্থায়ী TCP Connection দুই দিকেই বার্তা বহন করে। Server প্রতিটি Connection মনে রাখে: এটি কে, কোন Room-এ যোগ দিয়েছে।
WebSocket: যখন Connection নিজেই State
Chat Room ও Multiplayer Game-এ Server-কে নিজে বার্তা পাঠাতে হয়, তাই তারা একটি দীর্ঘস্থায়ী Connection খোলা রাখে।
পরিস্থিতি
একটি WebSocket শুরু হয় সাধারণ HTTP Request হিসেবে, যা Connection Upgrade করতে চায়।
এতে সমস্যা নেই, যদি তুমি সেভাবে Design করো:
- Connection একটি Server-এর সাথে বাঁধা, তাই Load Balancer-কে দীর্ঘস্থায়ী Connection সমর্থন করতে হবে।
- ভিন্ন Server-এ থাকা User-দের একে অপরের কাছে পৌঁছাতে একটি ভাগাভাগি Pub/Sub Channel (Redis, Kafka) লাগে।
- Server বন্ধ হয়, তাই Client Backoff-সহ আবার যুক্ত হয়, আবার Authenticate করে, এবং Server-এর যা জানা দরকার তা আবার পাঠায়। Connection State হওয়া উচিত এমন Cache যা স্থায়ী Storage থেকে সবসময় আবার তৈরি করা যায়।
#System Design-এ State: সিদ্ধান্তের নির্দেশিকা
- Default হিসেবে Stateless Application Server রাখো। এতে Load Balancing, Autoscaling, Deploy ও Crash থেকে ফেরা সহজ হয়।
- লগইনসহ Browser Website:
HttpOnly; Secure; SameSite=LaxCookie-তে Session ID, TTL-সহ Redis-এ Session Data। সহজ Logout, ছোট Cookie। - Public API, Mobile App, Microservices: স্বল্পমেয়াদি JWT Access Token, সঙ্গে বাতিলযোগ্য Refresh Token। Machine Client-এর জন্য API Key।
- Real-time Feature: WebSocket Server ইচ্ছাকৃতভাবেই Stateful; Pub/Sub দিয়ে বার্তা ভাগ করো এবং আবার যুক্ত হওয়া সস্তা রাখো।
- Sticky Session: WebSocket-এর জন্য বা সাময়িক সমাধান হিসেবে চলে, প্রধান Session কৌশল হিসেবে কখনো নয়।
- সবসময়: সব জায়গায় HTTPS, Auth Cookie-তে
Secure+HttpOnly+SameSite, Session-এর মেয়াদ, Server-side Logout, এবং XSS প্রতিরোধ।
#নিজে চেষ্টা করো
# ১. একটি Test Server-কে Cookie Set করতে বলো, আর Cookie Jar একটি File-এ রাখো
curl -c jar.txt https://httpbin.org/cookies/set?session_id=xyz987
cat jar.txt
# ২. রাখা Cookie স্বয়ংক্রিয়ভাবে ফেরত পাঠাও, Browser-এর মতো
curl -b jar.txt https://httpbin.org/cookies
# ৩. একটি বাস্তব Response-এ Raw Set-Cookie Header দেখো
curl -sI https://www.google.com/ | grep -i set-cookie
# ৪. একটি JWT-র Payload (মাঝের অংশ) Decode করে দেখো যে যে কেউ এটি পড়তে পারে
echo 'eyJzdWIiOiI0MiIsInJvbGUiOiJjdXN0b21lciJ9' | base64 -d
# ৫. ৩০ মিনিট TTL-সহ Redis-এ একটি Session (redis-cli থাকলে)
redis-cli SET session:xyz987 '{"userId":42}' EX 1800
redis-cli TTL session:xyz987
Browser-এ Developer Tools খোলো (F12) → Application (Chrome) বা Storage (Firefox) → Cookies। সাইটের প্রতিটি Cookie তার Domain, Path, Expires, HttpOnly, Secure ও SameSite কলামসহ দেখতে পাবে। কোনো সাইট থেকে লগ-আউট করে দেখো কোন Cookie উধাও হয়। তারপর Console-এ document.cookie চালাও: ফলাফলে HttpOnly Cookie-গুলো নেই।
#সারসংক্ষেপ
মূল শিক্ষা
- HTTP Stateless: প্রতিটি Request স্বাধীন। Application User-দের মনে রাখে State-কে Server-এ (Session), ভাগাভাগি Store-এ, বা Client-এর কাছে (Token) রেখে।
- Stateful Server RAM-এ Session রাখে: দ্রুত ও সহজ, কিন্তু Horizontal Scaling ভেঙে দেয়, Memory খায়, আর Restart-এ সব হারায়। Stateless Server-এর যেকোনো কপি যেকোনো Request সামলাতে পারে: Scalable ও Fault-tolerant, বিনিময়ে প্রতিবার Token পাঠাতে ও যাচাই করতে হয়।
- একাধিক Server থাকলে In-memory Session ঠিক করো কেন্দ্রীয় Store (Redis) বা Stateless Token দিয়ে; Sticky Session অসম চাপ তৈরি করে এবং Server বন্ধ হলে User হারায়।
- Cookie হলো
Set-Cookieদিয়ে রাখা ছোট (~৪ KB) Text মান, যা স্বয়ংক্রিয়ভাবে ফেরত যায়। Session না Persistent তা নির্ভর করেExpires/Max-Age-এর ওপর; পরিসর ঠিক করেDomainওPath; সুরক্ষা দেয়Secure,HttpOnlyওSameSite(Default Lax)। - Session Data রাখে Server-এ, আর Browser-কে দেয় শুধু একটি এলোমেলো Session ID। মেয়াদ রাখো, লগইনে ID বদলাও, Logout-এ মুছে ফেলো।
- JWT = header.payload.signature: যে কেউ পড়তে পারে, Key ছাড়া জাল করা যায় না, বাতিল করা কঠিন। স্বল্পমেয়াদি Access Token ও বাতিলযোগ্য Refresh Token ব্যবহার করো।
- XSS পড়া যায় এমন Token চুরি করে (HttpOnly Cookie, Escaping, CSP ব্যবহার করো); CSRF স্বয়ংক্রিয় Cookie-র অপব্যবহার করে (SameSite, CSRF Token, Origin যাচাই, নিরাপদ GET)। WebSocket স্বভাবগতভাবে Stateful: Pub/Sub দিয়ে ভাগ করো এবং আবার যুক্ত হওয়ার জন্য Design করো।
আগে নিজে উত্তর দাও, তারপর ব্যাখ্যাটা পড়ো। ঠিক হলেও পড়ো, কারণ ভুল Option-গুলো কেন ভুল, সেটাও ওখানে আছে।
নিজেকে যাচাই করোপ্রশ্ন
HTTP Stateless, এ কথার মানে কী?
নিজেকে যাচাই করোপ্রশ্ন
একটা Cookie-তে মোটামুটি কতটা Data রাখা যায়?
নিজেকে যাচাই করোপ্রশ্ন
Server পাঠাল Set-Cookie: theme=dark; Path=/, কোনো Expires বা Max-Age নেই। এটা কোন ধরনের Cookie?
নিজেকে যাচাই করোপ্রশ্ন
একটা JWT-এর তিনটা অংশ, ক্রমানুসারে কী কী?
নিজেকে যাচাই করোপ্রশ্ন
একটা Session Cookie-তে SameSite দেওয়াই হয়নি। আধুনিক Browser এটাকে কীভাবে ধরে?
নিজেকে যাচাই করোপ্রশ্ন
Cookie জমা রাখতে Server কোন Header পাঠায়, আর Browser কোন Header-এ সেটা ফেরত পাঠায়?
নিজেকে যাচাই করোপ্রশ্ন
নিচের কোন Token Database-এ খুঁজে যাচাই করা হয়, যাতে দরকার হলে বাতিল করা যায়?
নিজেকে যাচাই করোপ্রশ্ন
একটা WebSocket Connection শুরু হয় কীভাবে?
নিজেকে যাচাই করোপ্রশ্ন
একজন ব্যবহারকারী সোমবার সকাল ৯টায় লগইন করল। Site-এ Idle Timeout ৩০ মিনিট, Absolute Timeout ৭ দিন। সে পুরো সপ্তাহ সক্রিয়, কখনো ১০ মিনিটের বেশি চুপ থাকে না। কখন তাকে আবার লগইন করতে হবে?
নিজেকে যাচাই করোপ্রশ্ন
তুমি session:xyz987-কে Redis-এ ১৮০০ সেকেন্ড মেয়াদ দিয়ে রাখলে। ১০ মিনিট পরে redis-cli TTL session:xyz987 চালালে। মোটামুটি কোন সংখ্যা দেখবে?
নিজেকে যাচাই করোপ্রশ্ন
Server পাঠাল Set-Cookie: lang=bn; Max-Age=2592000; Path=/। Cookie-টা কতদিন থাকবে?
নিজেকে যাচাই করোপ্রশ্ন
একজন Developer JWT Payload-এ ব্যবহারকারীর ফোন নম্বর আর Password Hash রাখল, বলল ‘Sign করা আছে, তাই নিরাপদ’। সমস্যাটা কী?
নিজেকে যাচাই করোপ্রশ্ন
একজন আক্রমণকারী নিজের JWT Decode করে role customer থেকে admin বানাল, আবার Encode করে পাঠাল। কী হবে?
নিজেকে যাচাই করোপ্রশ্ন
দশটা Microservice-কে ব্যবহারকারীর Token যাচাই করতে হবে, কিন্তু Token দিতে পারবে শুধু Auth Server। কোন Signing ব্যবস্থা মানানসই?
নিজেকে যাচাই করোপ্রশ্ন
আক্রমণকারী একজনের Access Token (মেয়াদ ১৫ মিনিট) চুরি করল। কয়েক সেকেন্ড পরে তুমি তার Refresh Token-গুলো বাতিল করলে। চুরি হওয়া Access Token আর কতক্ষণ কাজ করবে?
নিজেকে যাচাই করোপ্রশ্ন
Logout শুধু Browser-এর Session Cookie মুছে দেয়। আগেই এক আক্রমণকারী Session ID-টা কপি করে রেখেছিল। Logout-এর পরে সে সেটা ব্যবহার করলে কী হবে?
নিজেকে যাচাই করোপ্রশ্ন
ব্যবহারকারী লগইন করার আগেই আক্রমণকারী তার Browser-এ নিজের জানা একটা Session ID বসিয়ে দিল। কোন অভ্যাস ওই ID-কে অকেজো করে?
নিজেকে যাচাই করোপ্রশ্ন
একজন Developer ব্যবহারকারীর সংখ্যাভিত্তিক ID-কেই Session ID বানাল: session_id=42। ভুলটা কোথায়?
নিজেকে যাচাই করোপ্রশ্ন
Notes-এ লেখা ‘HttpOnly XSS আক্রমণ ঠেকায়’। কোন কথাটা সঠিক?
নিজেকে যাচাই করোপ্রশ্ন
evil.example-এর একটা Page নিজে থেকেই একটা Form Submit করে bank.example/transfer-এ POST পাঠায়। ব্যাংকের Session Cookie-তে আছে SameSite=Lax। কী হবে?
নিজেকে যাচাই করোপ্রশ্ন
একটা ব্যাংক টাকা পাঠায় GET /transfer?to=…&amount=… দিয়ে, আর Session Cookie-তে SameSite=Lax। আক্রমণকারী ওই URL-এর একটা Link পোস্ট করল, লগইন করা এক ব্যবহারকারী তাতে ক্লিক করল। বিপদটা কোথায়?
নিজেকে যাচাই করোপ্রশ্ন
একটা Single-page App তার JWT রাখে localStorage-এ। Comment অংশে একটা Stored XSS Bug পাওয়া গেল। ফল কী?
নিজেকে যাচাই করোপ্রশ্ন
এক সহকর্মী বলল: ‘আমাদের API Stateless, তাই Database লাগবে না।’ কথাটায় ভুল কোথায়?
নিজেকে যাচাই করোপ্রশ্ন
API Key নিয়ে কোন কথাটা সঠিক?
নিজেকে যাচাই করোপ্রশ্ন
একটা Chat App-এ ব্যবহারকারী A WebSocket দিয়ে Server 1-এ, আর B Server 2-তে যুক্ত, দুজনেই একই Room-এ। A-এর Message B-এর কাছে পৌঁছায় কীভাবে?
নিজেকে যাচাই করোপ্রশ্ন
একটা Payment Form অনেক দোকানের Website-এ iframe হিসেবে বসানো, আর সেখানে তার নিজের Cookie লাগবে। কোন Cookie Setting দরকার?
নিজেকে যাচাই করোপ্রশ্ন
তুমি Session-গুলো প্রতিটা Server-এর RAM থেকে সরিয়ে একটা কেন্দ্রীয় Redis Store-এ নিলে। কোন নতুন ঝুঁকির কথা ভেবে ডিজাইন করতে হবে?
নিজেকে যাচাই করোপ্রশ্ন
প্রতিটা Session Cookie-তে সবসময় কোন দুটো Attribute থাকা উচিত? (দুটো বেছে নাও।)
বেছে নাও ২
নিজেকে যাচাই করোপ্রশ্ন
Stateless Application Server নিয়ে কোন দুটো কথা সত্য? (দুটো বেছে নাও।)
বেছে নাও ২
নিজেকে যাচাই করোপ্রশ্ন
Sticky Session-এর সত্যিকারের দুটো দুর্বলতা কোনগুলো? (দুটো বেছে নাও।)
বেছে নাও ২
নিজেকে যাচাই করোপ্রশ্ন
JWT নিয়ে কোন দুটো কথা সত্য? (দুটো বেছে নাও।)
বেছে নাও ২
নিজেকে যাচাই করোপ্রশ্ন
কোন দুটো প্রতিরক্ষা সরাসরি CSRF ঠেকায়? (দুটো বেছে নাও।)
বেছে নাও ২