owned this note
owned this note
Published
Linked with GitHub
---
title: Cross-Origin Resource Sharing (CORS)
tags: Templates, Talk
description: View the slide with "Slide Mode".
---
# Cross-Origin Resource Sharing (CORS)
---
## Para acompanhar a apresentação

---
Mecanismo que trabalha via HTTP headers para permitir que aplicações web rodando em uma origem tenham acesso a recursos em outra origem.
---
Por motivos de segurança, os browsers restringem requests para destinos diferentes da origem
---
Essas restrições possuem regras bem definidas e se soubermos exatamente quais são elas e como trata-las, evitamos o famigerado "Erro de CORS"
---
## Como isso funciona?
---
Requests de origens diferentes são separados em dois grupos principais: Requests Simples e Preflighted Requests
---
### Requests Simples
---
Requests que não ativam o CORS preflight são chamados de Requests Simples.
---
Para determinar se um request é simples, ele deve atender a TODOS os critérios a seguir
---
#### Métodos:
- GET
- POST
- HEAD
---
#### Headers personalizados podem ser apenas:
- Accept
- Accept-Language
- Content-Language
- Content-Type
- Valores podem ser apenas
- application/x-www-form-urlencoded
- multipart/form-data
- text/plain
---
#### Headers personalizados podem ser apenas:
- DPR
- Downlink
- Save-Data
- Viewport-Width
- Width
---
Caso o request se enquadre em todos esses requisitos, o único requisito no response do servidor é o header Access-Control-Allow-Origin (onde o valor pode ser um domínio específico ou *)
---
```javascript
const invocation = new XMLHttpRequest();
const url = 'http://bar.other/resources/public-data/';
function callOtherDomain() {
if (invocation) {
invocation.open('GET', url, true);
invocation.onreadystatechange = handler;
invocation.send();
}
}
```
---

---
```
GET /resources/public-data/ HTTP/1.1
Host: bar.other
User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.1b3pre) Gecko/20081130 Minefield/3.1b3pre
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Connection: keep-alive
Referer: http://foo.example/examples/access-control/simpleXSInvocation.html
Origin: http://foo.example
```
---
```
HTTP/1.1 200 OK
Date: Mon, 01 Dec 2008 00:23:53 GMT
Server: Apache/2.0.61
Access-Control-Allow-Origin: *
Keep-Alive: timeout=2, max=100
Connection: Keep-Alive
Transfer-Encoding: chunked
Content-Type: application/xml
[XML Data]
```
---
Caso o request NÃO se enquadre nessas regras, um preflight request será executado
---
### Preflighted Requests
---
Ao contrário dos requests simples, os preflighted requests primeiro enviam um outro request para validar se o request original é seguro de ser enviado
---
Isso acontece em requests para domínios diferentes, pois o request pode ter implicações em dados dos usuários
---
Um request preflight é um request com o método OPTIONS para o mesmo recurso do request original
---
```javascript
const invocation = new XMLHttpRequest();
const url = 'http://bar.other/resources/post-here/';
const body = '<?xml version="1.0"?><person><name>Arun</name></person>';
function callOtherDomain() {
if (invocation) {
invocation.open('POST', url, true);
invocation.setRequestHeader('X-PINGOTHER', 'pingpong');
invocation.setRequestHeader('Content-Type', 'application/xml');
invocation.onreadystatechange = handler;
invocation.send(body);
}
}
```
---

---
```
OPTIONS /resources/post-here/ HTTP/1.1
Host: bar.other
User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.1b3pre) Gecko/20081130 Minefield/3.1b3pre
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Connection: keep-alive
Origin: http://foo.example
Access-Control-Request-Method: POST
Access-Control-Request-Headers: X-PINGOTHER, Content-Type
```
---
```
HTTP/1.1 204 No Content
Date: Mon, 01 Dec 2008 01:15:39 GMT
Server: Apache/2.0.61 (Unix)
Access-Control-Allow-Origin: http://foo.example
Access-Control-Allow-Methods: POST, GET, OPTIONS
Access-Control-Allow-Headers: X-PINGOTHER, Content-Type
Access-Control-Max-Age: 86400
Vary: Accept-Encoding, Origin
Keep-Alive: timeout=2, max=100
Connection: Keep-Alive
```
---
Após o preflight request retornar, o browser valida se o request original pode ser enviado. Se sim, ele o faz
---
```
POST /resources/post-here/ HTTP/1.1
Host: bar.other
User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.1b3pre) Gecko/20081130 Minefield/3.1b3pre
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Connection: keep-alive
X-PINGOTHER: pingpong
Content-Type: text/xml; charset=UTF-8
Referer: http://foo.example/examples/preflightInvocation.html
Content-Length: 55
Origin: http://foo.example
Pragma: no-cache
Cache-Control: no-cache
<?xml version="1.0"?><person><name>Arun</name></person>
```
---
```
HTTP/1.1 200 OK
Date: Mon, 01 Dec 2008 01:15:40 GMT
Server: Apache/2.0.61 (Unix)
Access-Control-Allow-Origin: http://foo.example
Vary: Accept-Encoding, Origin
Content-Encoding: gzip
Content-Length: 235
Keep-Alive: timeout=2, max=99
Connection: Keep-Alive
Content-Type: text/plain
[Some GZIP'd payload]
```
---
#### Requests com Credenciais
---
Uma excelente feature do XMLHttpRequest ou Fetch é a capacidade de enviar requests "credenciados", ou seja, requests com cookies ou headers de autenticação
---
Por padrão, requests XMLHttpRequest ou Fetch para domínios diferentes não enviam credenciais
---
Para enviar credenciais num request XMLHttpRequest ou Fetch para um domínio diferente, é necessário definir uma flag específica `withCredentials`
---
```javascript
const invocation = new XMLHttpRequest();
const url = 'http://bar.other/resources/credentialed-content/';
function callOtherDomain() {
if (invocation) {
invocation.open('GET', url, true);
invocation.withCredentials = true;
invocation.onreadystatechange = handler;
invocation.send();
}
}
```
---

---
```
GET /resources/access-control-with-credentials/ HTTP/1.1
Host: bar.other
User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.1b3pre) Gecko/20081130 Minefield/3.1b3pre
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Connection: keep-alive
Referer: http://foo.example/examples/credential.html
Origin: http://foo.example
Cookie: pageAccess=2
```
---
```
HTTP/1.1 200 OK
Date: Mon, 01 Dec 2008 01:34:52 GMT
Server: Apache/2.0.61 (Unix) PHP/4.4.7 mod_ssl/2.0.61 OpenSSL/0.9.7e mod_fastcgi/2.4.2 DAV/2 SVN/1.4.2
X-Powered-By: PHP/5.2.6
Access-Control-Allow-Origin: http://foo.example
Access-Control-Allow-Credentials: true
Cache-Control: no-cache
Pragma: no-cache
Set-Cookie: pageAccess=3; expires=Wed, 31-Dec-2008 01:34:53 GMT
Vary: Accept-Encoding, Origin
Content-Encoding: gzip
Content-Length: 106
Keep-Alive: timeout=2, max=100
Connection: Keep-Alive
Content-Type: text/plain
[text/plain payload]
```
---
Para requests com credenciais, o response deve OBRIGATORIAMENTE retornar o header Access-Control-Allow-Origin com um domínio específico (e não um wildcard ), assim como o header Access-Control-Allow-Credentials
---
## Referências
---
Boa parte (ou quase tudo) isso que eu falei, pode ser encontrado com mais detalhes em https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
---
# :100: :muscle: :tada:
Chega de sofrer com CORS!
---
### Obrigado :sheep: