I den här artikeln ser vi hur du aktiverar CORS (Cross-Origin Resource Sharing) med HTTPOnly cookie för att säkra våra åtkomsttokens.
Nuförtiden är backend-servrar och frontend-klienter utplacerade på olika domäner. Därför måste servern aktivera CORS för att tillåta klienter att kommunicera med servern i webbläsare.
Dessutom implementerar servrar tillståndslös autentisering för bättre skalbarhet. Tokens lagras och underhålls på klientsidan, men inte på serversidan som sessionen. Av säkerhetsskäl är det bättre att lagra tokens i HTTPOnly cookies.
Innehållsförteckning
Varför blockeras Cross-Origin-förfrågningar?
Låt oss anta att vår frontend-applikation distribueras på https://app.adminvista.com.com. Ett skript laddat i https://app.adminvista.com.com kan bara begära resurser med samma ursprung.
Närhelst vi försöker skicka en begäran om korsuppkomst till en annan domän https://api.adminvista.com.com eller en annan port https://app.adminvista.com.com:3000 eller ett annat schema http://app.adminvista.com.com, cross-origin begäran kommer att blockeras av webbläsaren.
Men varför samma begäran som blockerats av webbläsaren skickas från valfri backend-server med curl-begäran eller skickas med hjälp av verktyg som brevbäraren utan några CORS-problem. Det är faktiskt för säkerheten att skydda användare från attacker som CSRF (Cross-Site Request Forgery).
Låt oss ta ett exempel, anta om någon användare loggat in på sitt eget PayPal-konto i sin webbläsare. Om vi kan skicka en cross-origin-begäran till paypal.com från ett skript laddat på en annan domän malicious.com utan något CORS-fel/blockering som att vi skickar samma ursprungsbegäran.
Angripare kan enkelt skicka sin skadliga sida https://malicious.com/transfer-money-to-attacker-account-from-user-paypal-account genom att konvertera den till kort webbadress för att dölja den faktiska webbadressen. När användaren klickar på en skadlig länk kommer skriptet som laddas i domänen malicious.com att skicka en begäran om korsuppkomst till PayPal om att överföra användarbeloppet till angriparens PayPal-konto som kommer att köras. Alla användare som har loggat in på sitt PayPal-konto och klickat på den här skadliga länken kommer att förlora sina pengar. Vem som helst kan enkelt stjäla pengar utan användarkännedom om ett PayPal-konto.
Av ovanstående anledning blockerar webbläsare alla förfrågningar om gränsöverskridande ursprung.
Vad är CORS (Cross-Origin Resource Sharing)?
CORS är en header-baserad säkerhetsmekanism som används av servern för att tala om för webbläsaren att skicka en kors-ursprungsförfrågan från betrodda domäner.
Servern aktiverad med CORS-rubriker som används för att undvika förfrågningar som blockeras av webbläsare.
Hur fungerar CORS?
Eftersom servern redan har definierat sin betrodda domän i sin CORS-konfiguration. När vi skickar en förfrågan till servern kommer svaret att tala om för webbläsaren att den begärda domänen är betrodd eller inte i dess rubrik.
Det finns två typer av CORS-förfrågningar:
- Enkel begäran
- Preflight-förfrågan
Enkel begäran:
- Webbläsaren skickar begäran till en domän med ursprung (https://app.adminvista.com.com).
- Servern skickar tillbaka motsvarande svar med tillåtna metoder och tillåtet ursprung.
- Efter att ha mottagit begäran kommer webbläsaren att kontrollera att det skickade ursprungshuvudvärdet (https://app.adminvista.com.com) och det mottagna access-control-allow-origin-värdet (https://app.adminvista.com.com) är desamma eller jokertecken
. Annars kommer det att ge ett CORS-fel.
- Preflight-förfrågan:
- Beroende på den anpassade begäran-parametern från korsorigin-begäran som metoder (PUT, DELETE) eller anpassade rubriker eller annan innehållstyp, etc. Webbläsaren kommer att besluta att skicka en preflight OPTIONS-begäran för att kontrollera om den faktiska begäran är säker att skicka eller inte.
Efter att ha mottagit svaret (statuskod: 204, vilket betyder inget innehåll), kommer webbläsaren att söka efter parametrarna för åtkomstkontroll-tillåt för den faktiska begäran. Om förfrågningsparametrarna tillåts av servern. Den faktiska korsoriginella begäran som skickas och tas emot
Om access-control-allow-origin: *, är svaret tillåtet för alla ursprung. Men det är inte säkert om du inte behöver det.
Hur aktiverar man CORS?
För att aktivera CORS för vilken domän som helst, aktivera CORS-rubriker för att tillåta ursprung, metoder, anpassade rubriker, autentiseringsuppgifter, etc.
- Webbläsaren läser CORS-huvudet från servern och tillåter faktiska förfrågningar från klienten endast efter att ha verifierat förfrågningsparametrar.
- Access-Control-Allow-Origin: För att ange exakta domäner (https://app.geekflate.com, https://lab.adminvista.com.com) eller jokertecken
- Access-Control-Allow-Methods: För att tillåta HTTP-metoderna (GET, POST, PUT, DELETE, PATCH, HEAD, OPTIONS) som bara vi behöver.
- Access-Control-Allow-Headers: För att endast tillåta specifika rubriker (auktorisering, csrf-token)
- Access-Control-Allow-Credentials: Booleskt värde som används för att tillåta cross-origin-credentials (cookies, auktoriseringshuvud).
Access-Control-Max-Age: Instruerar webbläsaren att cachelagra preflight-svaret under en tid.
Access-Control-Expose-Headers: Ange rubriker som är tillgängliga med skript på klientsidan.
För att aktivera CORS i apache och Nginx webbserver, följ denna handledning.
const express = require('express'); const app = express() app.get('/users', function (req, res, next) { res.json({msg: 'user get'}) }); app.post('/users', function (req, res, next) { res.json({msg: 'user create'}) }); app.put('/users', function (req, res, next) { res.json({msg: 'User update'}) }); app.listen(80, function () { console.log('CORS-enabled web server listening on port 80') })
Aktiverar CORS i ExpressJS
Låt oss ta ett exempel på ExpressJS-app utan CORS:
npm install cors
I exemplet ovan har vi aktiverat användarnas API-slutpunkt för POST, PUT, GET-metoder men inte DELETE-metoden.
För att enkelt aktivera CORS i ExpressJS-appen kan du installera cors
app.use(cors({ origin: '*' }));
Access-Control-Allow-Origin
app.use(cors({ origin: 'https://app.adminvista.com.com' }));
Aktiverar CORS för alla domäner
app.use(cors({ origin: [ 'https://app.geekflare.com', 'https://lab.geekflare.com' ] }));
Aktiverar CORS för en enda domän
Om du vill tillåta CORS för ursprung https://app.adminvista.com.com och https://lab.adminvista.com.com
app.use(cors({ origin: [ 'https://app.geekflare.com', 'https://lab.geekflare.com' ], methods: ['GET', 'PUT', 'POST'] }));
Access-Control-Allow-Methods
För att aktivera CORS för alla metoder, utelämna detta alternativ i CORS-modulen i ExpressJS. Men för att aktivera specifika metoder (GET, POST, PUT).
app.use(cors({ origin: [ 'https://app.geekflare.com', 'https://lab.geekflare.com' ], methods: ['GET', 'PUT', 'POST'], allowedHeaders: ['Content-Type', 'Authorization', 'x-csrf-token'] }));
Access-Control-Allow-Headers
Används för att tillåta andra rubriker än standard att skicka med faktiska förfrågningar.
app.use(cors({ origin: [ 'https://app.geekflare.com', 'https://lab.geekflare.com' ], methods: ['GET', 'PUT', 'POST'], allowedHeaders: ['Content-Type', 'Authorization', 'x-csrf-token'], credentials: true }));
Access-Control-Allow-Redigeringar
Utelämna detta om du inte vill tala om för webbläsaren att tillåta referenser på begäran även om withCredentials är satt till true.
app.use(cors({ origin: [ 'https://app.geekflare.com', 'https://lab.geekflare.com' ], methods: ['GET', 'PUT', 'POST'], allowedHeaders: ['Content-Type', 'Authorization', 'x-csrf-token'], credentials: true, maxAge: 600 }));
Access-Control-Max-Age
Att uppmana webbläsaren att cachelagra preflight-svarsinformationen i cachen under en angiven sekund. Uteslut detta om du inte vill cachelagra svaret.
app.use(cors({ origin: [ 'https://app.geekflare.com', 'https://lab.geekflare.com' ], methods: ['GET', 'PUT', 'POST'], allowedHeaders: ['Content-Type', 'Authorization', 'x-csrf-token'], credentials: true, maxAge: 600, exposedHeaders: ['Content-Range', 'X-Content-Range'] }));
Det cachade preflight-svaret kommer att vara tillgängligt i 10 minuter i webbläsaren.
app.use(cors({ origin: [ 'https://app.geekflare.com', 'https://lab.geekflare.com' ], methods: ['GET', 'PUT', 'POST'], allowedHeaders: ['Content-Type', 'Authorization', 'x-csrf-token'], credentials: true, maxAge: 600, exposedHeaders: ['*', 'Authorization', ] }));
Access-Control-Expose-Headers
Om vi sätter jokertecknet
i exposedHeaders kommer det inte att exponera auktoriseringshuvudet. Så vi måste explicit explicit som nedan
Ovanstående kommer också att exponera alla rubriker och auktoriseringsrubriker.
- Vad är en HTTP-cookie?
- En cookie är en liten bit data som servern skickar till klientens webbläsare. Vid senare förfrågningar kommer webbläsaren att skicka alla cookies relaterade till samma domän vid varje begäran.
- Cookie har sitt attribut, som kan definieras för att få en cookie att fungera annorlunda som vi behöver.
- Namn Namn på kakan.
- värde: data för cookie respektive cookie-namn
- Domän: cookies skickas endast till den definierade domänen
- Sökväg: cookies skickas endast efter den definierade sökvägen för URL-prefixet. Anta att om vi har definierat vår cookie-sökväg som path=’admin/’. Cookies skickas inte för webbadressen https://adminvista.com.com/expire/ utan skickas med URL-prefix https://adminvista.com.com/admin/
- Max-Age/Expires(antal i sekund): När ska cookien förfalla. En livstid av cookien gör cookien ogiltig efter den angivna tiden. [Strict, Lax, None]HTTPOnly(Boolean): Backend-servern kan komma åt den HTTPOnly-cookien men inte skriptet på klientsidan när det är sant. Säker (boolesk): Cookies skickas endast över en SSL/TLS-domän när sant.sameSite(sträng
): Används för att aktivera/begränsa cookies som skickas över förfrågningar mellan webbplatser. För mer information om cookies se sameSite
MDN
. Den accepterar tre alternativ Strict, Lax, None. Cookie säkert värde satt till sant för cookie-konfigurationen sameSite=Ingen.
Varför HTTPOnly cookie för tokens?
Att lagra åtkomsttoken som skickats från servern i lagring på klientsidan som lokal lagring, indexerad DB och cookie (HTTTPOnly inte satt till true) är mer sårbara för XSS-attack. Anta att om någon av dina sidor är svag för en XSS-attack. Angripare kan missbruka användartokens som lagras i webbläsaren.
Endast HTTP-cookies sätts/getas av servern/backend men inte på klientsidan.
- Skript på klientsidan är begränsat för åtkomst till den endast HTTP-cookien. Så HTTPOnly cookies är inte sårbara för XSS-attacker och är säkrare. Eftersom det bara är tillgängligt av servern.
- Aktivera HTTPOnly-cookie i CORS-aktiverad backend
- Aktivering av Cookie i CORS kräver konfigurationen nedan i applikationen/servern.
- Ställ in Access-Control-Allow-Credentials-huvudet till sant.
Access-Control-Allow-Origin och Access-Control-Allow-Headers ska inte vara ett jokertecken
const express = require('express'); const app = express(); const cors = require('cors'); app.use(cors({ origin: [ 'https://app.geekflare.com', 'https://lab.geekflare.com' ], methods: ['GET', 'PUT', 'POST'], allowedHeaders: ['Content-Type', 'Authorization', 'x-csrf-token'], credentials: true, maxAge: 600, exposedHeaders: ['*', 'Authorization' ] })); app.post('/login', function (req, res, next) { res.cookie('access_token', access_token, { expires: new Date(Date.now() + (3600 * 1000 * 24 * 180 * 1)), //second min hour days year secure: true, // set to true if your using https or samesite is none httpOnly: true, // backend only sameSite: 'none' // set to none for cross-request }); res.json({ msg: 'Login Successfully', access_token }); }); app.listen(80, function () { console.log('CORS-enabled web server listening on port 80') });
.
Cookie sameSite-attribut ska vara None.
För att aktivera sameSite-värdet till none, ställ in det säkra värdet till true: Aktivera backend med SSL/TLS-certifikat för att fungera i domännamnet.
Låt oss se en exempelkod som ställer in en åtkomsttoken i HTTPOnly-cookien efter att ha kontrollerat inloggningsuppgifterna.
Du kan konfigurera CORS- och HTTPOnly-cookies genom att implementera ovanstående fyra steg i ditt backend-språk och webbserver.
var xhr = new XMLHttpRequest(); xhr.open('GET', 'http://api.adminvista.com.com/user', true); xhr.withCredentials = true; xhr.send(null);
Du kan följa denna handledning för apache och Nginx för att aktivera CORS genom att följa stegen ovan.
fetch('http://api.adminvista.com.com/user', { credentials: 'include' });
med inloggningsuppgifter för Cross-Origin-begäran
$.ajax({ url: 'http://api.adminvista.com.com/user', xhrFields: { withCredentials: true } });
Inloggningsuppgifter (cookie, auktorisering) skickas som standard med begäran om samma ursprung. För cross-origin måste vi specificera withCredentials till true.
axios.defaults.withCredentials = true
XMLHttpRequest API
Hämta API
JQuery AjaxAxiosSlutsats Jag hoppas att artikeln ovan hjälper dig att förstå hur CORS fungerar och aktivera CORS för förfrågningar om gränsöverskridande ursprung i servern. Varför det är säkert att lagra cookies i HTTPOnly och hur med inloggningsuppgifter som används i klienter för förfrågningar med flera ursprung.