Atualizar:
Adicionei este link à minha outra resposta como usar a autenticação JWT para a API da Web do ASP.NET aqui para qualquer pessoa interessada em JWT.
Conseguimos aplicar a autenticação HMAC para proteger a API da Web e funcionou bem. A autenticação HMAC usa uma chave secreta para cada consumidor que, tanto o consumidor quanto o servidor, sabem hmac hash uma mensagem, o HMAC256 deve ser usado. Na maioria dos casos, a senha com hash do consumidor é usada como uma chave secreta.
A mensagem normalmente é criada a partir de dados na solicitação HTTP, ou mesmo dados personalizados que são adicionados ao cabeçalho HTTP, a mensagem pode incluir:
- Registro de data e hora: hora em que a solicitação é enviada (UTC ou GMT)
- Verbo HTTP: GET, POST, PUT, DELETE.
- publicar dados e string de consulta,
- URL
Sob o capô, a autenticação HMAC seria:
O consumidor envia uma solicitação HTTP ao servidor da Web, após criar a assinatura (saída do hmac hash), o modelo da solicitação HTTP:
User-Agent: {agent}
Host: {host}
Timestamp: {timestamp}
Authentication: {username}:{signature}
Exemplo para solicitação GET:
GET /webapi.hmac/api/values
User-Agent: Fiddler
Host: localhost
Timestamp: Thursday, August 02, 2012 3:30:32 PM
Authentication: cuongle:LohrhqqoDy6PhLrHAXi7dUVACyJZilQtlDzNbLqzXlw=
A mensagem para o hash para obter assinatura:
GET\n
Thursday, August 02, 2012 3:30:32 PM\n
/webapi.hmac/api/values\n
Exemplo para solicitação POST com string de consulta (a assinatura abaixo não está correta, apenas um exemplo)
POST /webapi.hmac/api/values?key2=value2
User-Agent: Fiddler
Host: localhost
Content-Type: application/x-www-form-urlencoded
Timestamp: Thursday, August 02, 2012 3:30:32 PM
Authentication: cuongle:LohrhqqoDy6PhLrHAXi7dUVACyJZilQtlDzNbLqzXlw=
key1=value1&key3=value3
A mensagem para o hash para obter assinatura
GET\n
Thursday, August 02, 2012 3:30:32 PM\n
/webapi.hmac/api/values\n
key1=value1&key2=value2&key3=value3
Observe que os dados do formulário e a string de consulta devem estar em ordem; portanto, o código no servidor obtém a string de consulta e os dados do formulário para criar a mensagem correta.
Quando a solicitação HTTP chega ao servidor, um filtro de ação de autenticação é implementado para analisar a solicitação para obter informações: verbo HTTP, carimbo de data e hora, uri, dados do formulário e seqüência de caracteres de consulta, com base neles para criar a assinatura (use o hmac hash) com o segredo chave (senha com hash) no servidor.
A chave secreta é obtida do banco de dados com o nome de usuário na solicitação.
Em seguida, o código do servidor compara a assinatura na solicitação com a assinatura criada; se igual, a autenticação é aprovada, caso contrário, falhou.
O código para criar assinatura:
private static string ComputeHash(string hashedPassword, string message)
{
var key = Encoding.UTF8.GetBytes(hashedPassword.ToUpper());
string hashString;
using (var hmac = new HMACSHA256(key))
{
var hash = hmac.ComputeHash(Encoding.UTF8.GetBytes(message));
hashString = Convert.ToBase64String(hash);
}
return hashString;
}
Então, como evitar ataques de repetição?
Adicione restrição ao carimbo de data / hora, algo como:
servertime - X minutes|seconds <= timestamp <= servertime + X minutes|seconds
(servertime: hora da solicitação chegando ao servidor)
E, armazene em cache a assinatura da solicitação na memória (use o MemoryCache, mantenha o tempo limite). Se a próxima solicitação vier com a mesma assinatura da solicitação anterior, ela será rejeitada.
O código de demonstração é apresentado aqui:
https://github.com/cuongle/Hmac.WebApi
Eu sugeriria começar com as soluções mais diretas primeiro - talvez a autenticação básica HTTP simples + HTTPS seja suficiente no seu cenário.
Caso contrário (por exemplo, você não pode usar https ou precisa de um gerenciamento de chaves mais complexo), consulte as soluções baseadas em HMAC, conforme sugerido por outras pessoas. Um bom exemplo dessa API seria o Amazon S3 ( http://s3.amazonaws.com/doc/s3-developer-guide/RESTAuthentication.html )
Eu escrevi uma postagem no blog sobre autenticação baseada em HMAC na API da Web do ASP.NET. Ele discute o serviço de API da Web e o cliente da API da Web, e o código está disponível no bitbucket. http://www.piotrwalat.net/hmac-authentication-in-asp-net-web-api/
Aqui está uma publicação sobre autenticação básica na API da Web: http://www.piotrwalat.net/basic-http-authentication-in-asp-net-web-api-using-message-handlers/
Lembre-se de que, se você for fornecer uma API a terceiros, provavelmente também será responsável pelo fornecimento de bibliotecas clientes. A autenticação básica tem uma vantagem significativa aqui, pois é suportada na maioria das plataformas de programação prontas para uso. O HMAC, por outro lado, não é tão padronizado e exigirá implementação personalizada. Estes devem ser relativamente diretos, mas ainda exigem trabalho.
PS. Há também uma opção para usar certificados HTTPS +. http://www.piotrwalat.net/client-certificate-authentication-in-asp-net-web-api-and-windows-store-apps/
fonte
Você já tentou o DevDefined.OAuth?
Usei-o para proteger meu WebApi com OAuth de duas pernas. Também testei com sucesso com clientes PHP.
É muito fácil adicionar suporte ao OAuth usando esta biblioteca. Veja como você pode implementar o provedor da API da Web do ASP.NET MVC:
1) Obtenha o código fonte do DevDefined.OAuth: https://github.com/bittercoder/DevDefined.OAuth - a versão mais recente permite
OAuthContextBuilder
extensibilidade.2) Crie a biblioteca e faça referência a ela no seu projeto de API da Web.
3) Crie um construtor de contexto personalizado para suportar a construção de um contexto a partir de
HttpRequestMessage
:4) Use este tutorial para criar um provedor OAuth: http://code.google.com/p/devdefined-tools/wiki/OAuthProvider . Na última etapa (Acessando o exemplo de recurso protegido), você pode usar este código em seu
AuthorizationFilterAttribute
atributo:Eu implementei meu próprio provedor, então não testei o código acima (exceto, é claro, o
WebApiOAuthContextBuilder
que estou usando no meu provedor), mas deve funcionar bem.fonte
A API da Web introduziu um Atributo
[Authorize]
para fornecer segurança. Isso pode ser definido globalmente (global.asx)Ou por controlador:
É claro que seu tipo de autenticação pode variar e você pode querer executar sua própria autenticação. Quando isso ocorrer, poderá ser útil herdar o Authorizate Attribute e estendê-lo para atender aos seus requisitos:
E no seu controlador:
Aqui está um link sobre outra implementação personalizada para autorizações da WebApi:
http://www.piotrwalat.net/basic-http-authentication-in-asp-net-web-api-using-membership-provider/
fonte
AuthorizeAttribute
, pois existem duas classes diferentes com o mesmo nome em espaços para nome diferentes: 1. System.Web.Mvc.AuthorizeAttribute -> para controladores MVC 2. System.Web.Http.AuthorizeAttribute -> para WebApi.Se você deseja proteger sua API em um servidor para servidor (sem redirecionamento para o site para autenticação de duas pernas). Você pode consultar o protocolo de concessão de credenciais do cliente OAuth2.
https://dev.twitter.com/docs/auth/application-only-auth
Eu desenvolvi uma biblioteca que pode ajudá-lo a adicionar facilmente esse tipo de suporte à sua WebAPI. Você pode instalá-lo como um pacote NuGet:
https://nuget.org/packages/OAuth2ClientCredentialsGrant/1.0.0.0
A biblioteca tem como alvo o .NET Framework 4.5.
Depois de adicionar o pacote ao seu projeto, ele criará um arquivo leia-me na raiz do seu projeto. Você pode olhar para esse arquivo leia-me para ver como configurar / usar este pacote.
Felicidades!
fonte
na continuação da resposta de @ Cuong Le, minha abordagem para evitar ataques de repetição seria
// Criptografa o horário do Unix no lado do cliente usando a chave privada compartilhada (ou a senha do usuário)
// Envia como parte do cabeçalho da solicitação para o servidor (WEB API)
// Descriptografar a hora do Unix no servidor (API WEB) usando a chave privada compartilhada (ou a senha do usuário)
// Verifique a diferença horária entre a Hora Unix do Cliente e a Hora Unix do Servidor, não deve ser maior que x s
// se a senha de ID do usuário / hash estiver correta e o UnixTime descriptografado estiver dentro de x segundos do tempo do servidor, é uma solicitação válida
fonte