Autenticação básica e resumida para um serviço REST com Spring Security

Autenticação básica e resumida para um serviço REST com Spring Security

1. Visão geral

Este artigo descreve comoset up both Basic and Digest Authentication on the same URI structure of a REST API. Em um artigo anterior, discutimos outro método de proteger o serviço REST -form-based authentication, portanto, a autenticação Básica e Digest é a alternativa natural, bem como a mais RESTful.

2. Configuração de autenticação básica

A principal razão pela qual a autenticação baseada em formulário não é ideal para um serviço RESTful é que o Spring Security irámake use of Sessions - este é obviamente o estado no servidor, entãothe statelessness constraints in REST é praticamente ignorado.

Começaremos configurando a autenticação básica - primeiro removemos o antigo ponto de entrada personalizado e o filtro do elemento de segurança<http> principal:


   

   

Observe como o suporte para autenticação básica foi adicionado com uma única linha de configuração -<http-basic /> - que lida com a criação e a fiação deBasicAuthenticationFiltereBasicAuthenticationEntryPoint.

2.1. Satisfazer a restrição sem estado - livrar-se das sessões

Uma das principais restrições do estilo arquitetônico RESTful é que a comunicação cliente-servidor é totalmentestateless, como ooriginal dissertation lê:

5.1.3 Stateless

Em seguida, adicionamos uma restrição à interação cliente-servidor: a comunicação deve ter natureza sem estado, como no estilo cliente-sem estado-servidor (CSS) da Seção 3.4.3 (Figura 5-3), de modo que cada solicitação do cliente para O servidor deve conter todas as informações necessárias para entender a solicitação e não pode tirar proveito de nenhum contexto armazenado no servidor. Session state is therefore kept entirely on the client.

O conceito deSession no servidor tem uma longa história no Spring Security, e removê-lo totalmente tem sido difícil até agora, especialmente quando a configuração foi feita usando o namespace.

No entanto, Spring Securityaugments a configuração do namespace com umnew stateless option para a criação da sessão, o que efetivamente garante que nenhuma sessão será criada ou usada pelo Spring. O que essa nova opção faz é remover todos os filtros relacionados à sessão da cadeia de filtros de segurança, garantindo que a autenticação seja realizada para cada solicitação.

3. Configuração de Autenticação Digest

Começando com a configuração anterior, o filtro e o ponto de entrada necessários para configurar a autenticação Digest serão definidos como beans. Em seguida, odigest entry point substituirá o criado por<http-basic> nos bastidores. Por fim, odigest filter personalizado será introduzido na cadeia de filtros de segurança usando a semânticaafter do namespace de segurança para posicioná-lo diretamente após o filtro de autenticação básico.


   

   
   



   
   



   
   



   
      
         
         
      
   

Infelizmente, não hásupport no namespace de segurança para configurar automaticamente a autenticação digest da maneira como a autenticação básica pode ser configurada com<http-basic>. Por esse motivo, os beans necessários precisavam ser definidos e conectados manualmente na configuração de segurança.

4. Compatível com os dois protocolos de autenticação no mesmo serviço RESTful

Autenticação básica ou Digest sozinha pode ser facilmente implementada no Spring Security; suporta ambos no mesmo serviço da Web RESTful, nos mesmos mapeamentos de URI que introduzem um novo nível de complexidade na configuração e no teste do serviço.

4.1. Pedido anônimo

Com os filtros básico e digest na cadeia de segurança, a forma como umanonymous request - uma solicitação sem credenciais de autenticação (cabeçalho HTTPAuthorization) - é processada pelo Spring Security é - os dois filtros de autenticação encontrarãono credentialse continuará a execução da cadeia de filtros. Em seguida, vendo como a solicitação não foi autenticada, umAccessDeniedException é lançado e capturado noExceptionTranslationFilter, que inicia o ponto de entrada do resumo, solicitando ao cliente as credenciais.

As responsabilidades dos filtros básico e digest são muito limitadas - eles continuarão executando a cadeia de filtros de segurança se não conseguirem identificar o tipo de credenciais de autenticação na solicitação. É por isso que o Spring Security pode ter a flexibilidade de ser configurado com suporte a vários protocolos de autenticação no mesmo URI.

Quando é feita uma solicitação que contém as credenciais de autenticação corretas - básicas ou resumidas - esse protocolo será usado corretamente. No entanto, para uma solicitação anônima, o cliente será solicitado apenas para digitar as credenciais de autenticação. Isso ocorre porque o ponto de entrada digest é configurado como o ponto de entrada principal e único da cadeia Spring Security; como taldigest authentication can be considered the default.

4.2. Solicitar com credenciais de autenticação

Umrequest with credentials para autenticação básica será identificado pelo cabeçalhoAuthorization começando com o prefixo“Basic”. Ao processar essa solicitação, as credenciais serão decodificadas no filtro de autenticação básica e a solicitação será autorizada. Da mesma forma, uma solicitação com credenciais para autenticação Digest usará o prefixo“Digest” para seu cabeçalhoAuthorization.

5. Testando ambos os cenários

Os testes consumirão o serviço REST criando um novo recurso após a autenticação com o básico ou o resumo:

@Test
public void givenAuthenticatedByBasicAuth_whenAResourceIsCreated_then201IsReceived(){
   // Given
   // When
   Response response = given()
    .auth().preemptive().basic( ADMIN_USERNAME, ADMIN_PASSWORD )
    .contentType( HttpConstants.MIME_JSON ).body( new Foo( randomAlphabetic( 6 ) ) )
    .post( paths.getFooURL() );

   // Then
   assertThat( response.getStatusCode(), is( 201 ) );
}
@Test
public void givenAuthenticatedByDigestAuth_whenAResourceIsCreated_then201IsReceived(){
   // Given
   // When
   Response response = given()
    .auth().digest( ADMIN_USERNAME, ADMIN_PASSWORD )
    .contentType( HttpConstants.MIME_JSON ).body( new Foo( randomAlphabetic( 6 ) ) )
    .post( paths.getFooURL() );

   // Then
   assertThat( response.getStatusCode(), is( 201 ) );
}

Observe que o teste usando autenticação básica adiciona credenciais à solicitaçãopreemptively, independentemente se o servidor desafiou a autenticação ou não. Isso é para garantir que o servidor não precise desafiar o cliente por credenciais, porque se precisasse, o desafio seria para credenciais Digest, já que esse é o padrão.

6. Conclusão

Este artigo abordou a configuração e implementação da autenticação Basic e Digest para um serviço RESTful, usando principalmente o suporte ao namespace Spring Security, bem como alguns novos recursos da estrutura.