Course-এর সূচি

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-এর মাঝে তোমাকে মনে রাখে।

Client
ServerRAM
Database
POST /login (rahim, ••••)
ধাপ 1 / 7
1

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 ServerStateless Server
State কোথায় থাকেServer-এর Memory-তেClient-এর পাঠানো Token-এ (বা ভাগাভাগি করা Store-এ)
ScalabilityScale করা কঠিন ও জটিলঅত্যন্ত সহজ (Microservices-এর জন্য সেরা)
Server MemoryClient বৃদ্ধির সাথে বাড়েপ্রতি Client-এ বাড়তি চাপ নেই
Server Crash বা Deployতার Session হারিয়ে যায়কিছুই হারায় না
Load BalancingSticky Session বা ভাগাভাগি Store লাগেযেকোনো Server, যেকোনো Request
প্রতি Request-এর খরচছোট ID; দ্রুত Memory Lookupবড় Token; Signature যাচাই
Logout / Access বাতিলসহজ: Session মুছে ফেলোকঠিন: মেয়াদ শেষ না হওয়া পর্যন্ত Token বৈধ
সাধারণ ব্যবহারReal-time Multiplayer Game, Chat Room, WebSocket ConnectionREST API, আধুনিক Web ও Mobile Backend

#Scaling: Session কোথায় থাকবে?

Load Balancer-এর পেছনে একাধিক Server চালানোর মুহূর্তেই In-memory Session ভেঙে পড়ে। এর তিনটি প্রচলিত সমাধান আছে।

Load Balancer-এর পেছনে Session

তিনটি একই রকম Server। Rahim-এর Session কোথায় থাকলে যেকোনোটি তাকে সেবা দিতে পারবে?

পরিস্থিতি

Rahim
Load Balancer
Server ARAM: abc → Rahim
Server B
Server C
Session StoreRedis
POST /login
ধাপ 1 / 4
1

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 StoreSession থাকে 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।

যেহেতু HTTP Stateless, কোনো User লগইন করে পরের Page-এ গেলে Server ভুলে যায় User-টি কে। এই সমস্যার সমাধান করতেই Cookie ও Session একসাথে কাজ করে।

Cookie হলো Browser-এ কোনো Website-এর জন্য রাখা ছোট ছোট Text Data (প্রতিটি সর্বোচ্চ প্রায় ৪ KB)।

  • কীভাবে কাজ করে: Server Response-এ Set-Cookie: key=value Header পাঠিয়ে Browser-কে এটি সেভ করার নির্দেশ দেয়। Browser এটি নিজের Cookie Jar-এ রেখে দেয়। এরপর থেকে ওই Domain-এ যত Request যাবে, Browser স্বয়ংক্রিয়ভাবে Cookie Header-এ সেই 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
  • 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-এর ধরন বদলে গেছে।

Attributeকী করেSession Cookie-র জন্য পরামর্শ
Expires / Max-AgeCookie কখন মরবে। না থাকলে Session Cookie। Max-Age=0 মুছে দেয়বাদ দাও, বা স্বল্প রাখো
Domainকোন Host এটি পাবে। না থাকলে শুধু যে Host Set করেছে সেটিই। Domain=example.com সব Subdomain-কে অন্তর্ভুক্ত করেবাদ দাও (Host-only)
Pathশুধু এই Path-এর নিচের URL-এ পাঠানো হয়Path=/
Secureশুধু HTTPS-এ পাঠানো হয়, সাধারণ HTTP-তে কখনো নাসবসময়
HttpOnlyJavaScript এটি পড়তে পারে না (document.cookie), ফলে XSS Script চুরি করতে পারে নাসবসময়
SameSiteঅন্য সাইট থেকে শুরু হওয়া Request-এ যাবে কি না: Strict, Lax বা NoneLax (বা 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

  1. User লগইন Form জমা দেয় (POST /login)।
  2. Server Password যাচাই করে এবং Store-এ একটি Session তৈরি করে (যেমন session_id: xyz987)।
  3. Server Response-এ পাঠায়: Set-Cookie: session_id=xyz987; HttpOnly।
  4. Browser xyz987 Cookie হিসেবে সেভ করে।
  5. পরে User যখন Dashboard-এ যায় (GET /dashboard), Browser Header-এর সাথে পাঠায়: Cookie: session_id=xyz987।
  6. Server xyz987 দিয়ে Store-এ খুঁজে দেখে এটি কার Session, সেই অনুযায়ী User-কে চিহ্নিত করে Data ফেরত দেয়।

Session Cookie দিয়ে লগইন, ধাপে ধাপে

Data থাকে Server-এ; Browser-এর কাছে থাকে শুধু তার চাবি।

পরিস্থিতি

Browser
Server
Session StoreRedis / Database
POST /login {user: rahim, password: ••••}
ধাপ 1 / 8
1

১. ব্যবহারকারী 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
Auth ServerToken স্বাক্ষর করে
API ServerToken যাচাই করে
POST /login
ধাপ 1 / 6
1

Client Username ও Password দিয়ে লগইন করে।

#মেয়াদ, Refresh Token ও বাতিল করা

JWT-র বড় শক্তি (কোনো Lookup নেই) এটির দুর্বলতাও: Server দেওয়া Token “মুছে” ফেলতে পারে না। চুরি হওয়া Token exp পর্যন্ত কাজ করে। তাই প্রচলিত Design-এ দুটি Token ব্যবহার হয়:

Access TokenRefresh 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 কী চুরি করতে পারে?

পরিস্থিতি

ভুক্তভোগীর Browseron shop.example.com
shop.example.com
আক্রমণকারীevil.example
Review: <script>…</script>
ধাপ 1 / 5
1

আক্রমণকারী Script Tag-সহ একটি Product Review পোস্ট করে। সাইট Escape না করেই সেটি সংরক্ষণ করে।

  • HttpOnly ছাড়া Script document.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 যেন সেটি পাঠায়।

পরিস্থিতি

ভুক্তভোগীর Browserbank sid=abc
evil.exampleআক্রমণকারীর Page
bank.exampleভুক্তভোগী লগইন করা
Set-Cookie: sid=abc; SameSite=None; Secure
ধাপ 1 / 5
1

তুমি আগে ব্যাংকে লগইন করেছিলে। তার Cookie অন্য সাইট থেকেও পাঠানোর অনুমতি দেয় (SameSite=None)।

প্রতিরক্ষা, একসাথে ব্যবহার করো:

  1. Session Cookie-তে SameSite=Lax বা Strict, যাতে Cross-site POST-এ কোনো Cookie না যায়।
  2. CSRF Token: প্রতিটি Form-এ একটি এলোমেলো মান, যা আক্রমণকারীর Page পড়তে পারে না।
  3. Data বদলানো Request-এ Origin Header যাচাই করো।
  4. GET দিয়ে কখনো Data বদলাবে না, কারণ Lax তবুও Top-level GET Navigation-এ Cookie পাঠায়।

#Browser Auth Token কোথায় রাখবে?

StorageJavaScript পড়তে পারে (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 খোলা রাখে।

পরিস্থিতি

Chat App
Load Balancer
Chat Server 1
Chat Server 2
Redis pub/sub
GET /chat · Upgrade: websocket
ধাপ 1 / 5
1

একটি 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=Lax Cookie-তে 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 করো।