Habilitando CORS (Compartilhamento de Recursos entre Origens) no Sisk
Esta página foi traduzida automaticamente do inglês. Ler o original
Sisk possui uma ferramenta que pode ser útil para lidar com Cross-Origin Resource Sharing (CORS) ao expor seu serviço publicamente. Esse recurso não faz parte do protocolo HTTP, mas é uma funcionalidade específica dos navegadores web definida pelo W3C. Esse mecanismo de segurança impede que uma página web faça requisições a um domínio diferente daquele que forneceu a página. Um provedor de serviço pode permitir que certos domínios acessem seus recursos, ou apenas um.
Mesma Origem #
Para que um recurso seja identificado como “mesma origem”, uma requisição deve indicar o cabeçalho Origin em sua solicitação:
GET /api/users HTTP/1.1
Host: example.com
Origin: http://example.com
...E o servidor remoto deve responder com um cabeçalho Access-Control-Allow-Origin contendo o mesmo valor da origem solicitada:
HTTP/1.1 200 OK
Access-Control-Allow-Origin: http://example.com
...Essa verificação é explícita: o host, a porta e o protocolo devem ser os mesmos da solicitação. Confira o exemplo:
- Um servidor responde que seu
Access-Control-Allow-Originéhttps://example.com:https://example.net- o domínio é diferente.http://example.com- o esquema é diferente.http://example.com:5555- a porta é diferente.https://www.example.com- o host é diferente.
Na especificação, apenas a sintaxe é permitida para ambos os cabeçalhos, tanto em requisições quanto em respostas. O caminho da URL é ignorado. A porta também é omitida se for a porta padrão (80 para HTTP e 443 para HTTPS).
Origin: null
Origin: <scheme>://<hostname>
Origin: <scheme>://<hostname>:<port>Habilitando CORS #
Nativamente, você tem o objeto CrossOriginResourceSharingHeaders dentro do seu ListeningHost.
Você pode configurar o CORS ao inicializar o servidor:
static async Task Main(string[] args)
{
using var app = HttpServer.CreateBuilder()
.UseCors(new CrossOriginResourceSharingHeaders(
allowOrigin: "http://example.com",
allowHeaders: ["Authorization"],
exposeHeaders: ["Content-Type"]))
.Build();
await app.StartAsync();
}O código acima enviará os seguintes cabeçalhos para todas as respostas:
HTTP/1.1 200 OK
Access-Control-Allow-Origin: http://example.com
Access-Control-Allow-Headers: Authorization
Access-Control-Expose-Headers: Content-TypeEsses cabeçalhos precisam ser enviados em todas as respostas para um cliente web, incluindo erros e redirecionamentos.
Você pode notar que a classe CrossOriginResourceSharingHeaders possui duas propriedades semelhantes: AllowOrigin e AllowOrigins. Observe que uma está no plural, enquanto a outra está no singular.
- A propriedade AllowOrigin é estática: apenas a origem que você especificar será enviada em todas as respostas.
- A propriedade AllowOrigins é dinâmica: o servidor verifica se a origem da requisição está contida nesta lista. Se for encontrada, ela é enviada na resposta daquela origem.
Quando a origem permitida depende da requisição, isto é, quando você usa AllowOrigins ou o valor AutoAllowOrigin descrito abaixo, o Sisk também envia o cabeçalho Vary: Origin para que os caches não reutilizem uma resposta para uma origem diferente.
Curingas e cabeçalhos automáticos #
Alternativamente, você pode usar um curinga (*) na origem da resposta para especificar que qualquer origem tem permissão para acessar o recurso. Contudo, esse valor não é permitido para requisições que contenham credenciais (cabeçalhos de autorização) e essa operação resultará em um erro.
Você pode contornar esse problema listando explicitamente quais origens serão permitidas através da propriedade AllowOrigins ou também usar a constante AutoAllowOrigin no valor de AllowOrigin. Essa propriedade mágica definirá o cabeçalho Access-Control-Allow-Origin com o mesmo valor do cabeçalho Origin da requisição.
Você também pode usar AutoFromRequestMethod e AutoFromRequestHeaders para um comportamento semelhante ao AllowOrigin, que responde automaticamente com base nos cabeçalhos enviados.
using var host = HttpServer.CreateBuilder()
.UseCors(new CrossOriginResourceSharingHeaders(
// Responde com base no cabeçalho Origin da requisição
allowOrigin: CrossOriginResourceSharingHeaders.AutoAllowOrigin,
// Responde com base no cabeçalho Access-Control-Request-Method ou no método da requisição
allowMethods: [CrossOriginResourceSharingHeaders.AutoFromRequestMethod],
// Responde com base no cabeçalho Access-Control-Request-Headers ou nos cabeçalhos enviados
allowHeaders: [CrossOriginResourceSharingHeaders.AutoFromRequestHeaders],
exposeHeaders: [HttpKnownHeaderNames.ContentType, "X-Authenticated-Account-Id"],
allowCredentials: true))
.Build();Outras Formas de Aplicar CORS #
Se você está lidando com service providers, pode sobrescrever valores definidos no arquivo de configuração:
static async Task Main(string[] args)
{
using var app = HttpServer.CreateBuilder()
.UsePortableConfiguration(...)
.UseCors(cors => {
// Substituirá a origem definida na configuração
// do arquivo.
cors.AllowOrigin = "http://example.com";
})
.Build();
await app.StartAsync();
}Desabilitando CORS em Rotas Específicas #
A propriedade UseCors está disponível tanto para rotas quanto para todos os atributos de rota e pode ser desativada com o exemplo a seguir:
[RoutePrefix("api/widgets")]
public class WidgetController : Controller {
// GET /api/widgets/colors
[RouteGet("/colors", UseCors = false)]
public IEnumerable<string> GetWidgets() {
return new[] { "Green widget", "Red widget" };
}
}Substituindo Valores na Resposta #
Você pode substituir ou remover valores explicitamente em uma ação de roteador:
[RoutePrefix("api/widgets")]
public class WidgetController : Controller {
public IEnumerable<string> GetWidgets(HttpRequest request) {
// Remove o cabeçalho Access-Control-Allow-Credentials
request.Context.OverrideHeaders.AccessControlAllowCredentials = string.Empty;
// Substitui o cabeçalho Access-Control-Allow-Origin
request.Context.OverrideHeaders.AccessControlAllowOrigin = "https://contorso.com";
return new[] { "Green widget", "Red widget" };
}
}Requisições Preflight #
Uma requisição preflight é uma requisição do método OPTIONS que o cliente envia antes da requisição real.
Quando uma requisição com o método OPTIONS corresponde ao caminho de uma rota, mas nenhuma rota está configurada explicitamente para OPTIONS, o servidor Sisk responde com um 200 OK e os cabeçalhos CORS aplicáveis, e então o cliente pode prosseguir com a requisição real.
- Se uma rota estiver mapeada explicitamente com RouteMethod.Options, por exemplo com
MapOptions, essa rota trata a requisição em vez da resposta automática. - Se a rota que corresponde ao caminho tem
UseCors = false, a resposta automática ainda é enviada, porém sem os cabeçalhos CORS.
Nota
Antes do Sisk 1.7, a resposta automática de preflight sempre continha os cabeçalhos CORS, mesmo para rotas com UseCors = false.
Desabilitando CORS Globalmente #
Não é possível fazer isso. Para não usar CORS, simplesmente não o configure.