Pergunta

Eu tenho um aplicativo que se comunica com um servidor que usa a autenticação HTTP Digest.

Parece -me que a gerência de 'sessão' no iPhone é bastante "caixa preta" para nós, desenvolvedores. É verdade que não podemos ver como a estrutura lida / persiste sessões HTTP?

Se eu estou apenas sendo escuro aqui, alguém se importaria de explicar como provavelmente lidar com a autenticação HTTP Digest no iPhone?

Minha corrida básica é:

  • Faça um pedido para um URL seguro
  • O servidor envia um 401
  • O cliente cria e persiste uma credencial e o passa de volta ao servidor
  • O servidor verifica a credencial, conclui a solicitação, se verificada, envia outro 401, se não.
  • Faça uma solicitação subsequente para proteger URL
  • O servidor solicita autorização novamente ........

Isso funciona para solicitações únicas, mas se eu fizer solicitações subsequentes adicionais, o servidor solicita autorização novamente. O servidor persistiu uma sessão para o usuário em particular, mas o iPhone não está fazendo uma solicitação na mesma sessão por algum motivo ... portanto, o servidor precisa jogar fora o objeto de autenticação e criar um novo cada vez que o cliente faz uma solicitação para um URL seguro.

Tenho certeza de que isso não é um comportamento correto.

Se olharmos como um navegador se comporta nesta situação:

  • O navegador solicita dados do URL seguro
  • O servidor envia 401
  • O navegador leva o usuário para credencial, persiste, passa para o servidor
  • O servidor verifica a credencial, devolvendo os dados, se verificado, envia outro 401, se não.
  • As solicitações subsequentes feitas para os URLs seguros não são solicitados a credenciais porque o navegador gerencia a sessão.

Estou criando o nsurlcredential e persistindo -o dentro do NSurlCrendTialStorage. Então, quando o aplicativo recebe o 'DidreceiveAuthenticationChallenge', recupero a credencial do armazenamento e o passo de volta, criando a credencial se ele não existir (na primeira solicitação).

Qualquer ajuda seria muito apreciada. Obrigado.

Foi útil?

Solução

A primeira coisa, é esquecer as sessões HTTP, pois elas não interagem com os log-ins de autenticação do Digest (existe uma espécie de capacidade de informação da sessão, mas é diferente).

De fato, uma das principais razões para o uso do Digest é não ter que usar sessões apenas para manter um estado logado. As sessões são pesadas e feridas de escalabilidade.

Eu não poderia dizer com certeza qual é o seu problema, mas sei o que verificaria primeiro, o que é o uso correto da criação obsoleta e correta de Nonces.

Os agentes do usuário podem lidar apenas com a autenticação sem exigir o usuário se forem solicitados a lidar com o mesmo nonce ou, em outro caso, irei mais tarde (mais fácil de explicá-lo nesse pedido).

Se você tiver o mesmo nonce usado em cada solicitação, o agente do usuário continuará a usá-lo junto com o "HA1" do usuário/passagem para solicitar recursos subsequentes. Isso é feito de forma pré -), para que o desafio nunca aconteça.

Obviamente, o uso do mesmo nonce apresenta um elemento de insegurança, pois os ataques de reprodução se tornam triviais para qualquer pessoa que possa cheirar o tráfego. Nonces terão que mudar regularmente.

Portanto, se você receber uma solicitação de um agente de usuário com um cabeçalho de autorização inválido, mas a razão pela qual é inválido é que o nonce está errado (está usando um expirado), então em seu desafio incluir "Stale = True" (Padrões para falso). Isso informa o agente do usuário que o seu motivo para rejeitar é que o Nonce está desatualizado (é claro que as outras informações também podem estar erradas, mas isso não importa, pois você não vai deixá-lo jogar de qualquer maneira).

Ao receber tal obsoleto = True, o agente do usuário saberá que não está autorizado, mas em vez de requisitar o usuário (ou lançar uma exceção se for um componente sem UI-Ui) voltará a tentar os critérios antigos com o novo Nonce.

Não sei dizer se isso é o que está afetando você, mas a maneira como os inquilinos e a robustez são determinados e sinalizados é certamente a primeira coisa que eu olhava.

Outras dicas

Escrevi um aplicativo para iPhone com autenticação HTTP e experimentei o que você descreve. (Meu aplicativo usa autenticação básica em vez de autenticação de digerir, mas isso não faz uma grande diferença aqui.)

A causa do problema está no lado do iPhone. O servidor deve responder com 401 se o iPhone não enviar as credenciais no cabeçalho da solicitação HTTP. E, de fato, não é mesmo que possa facilmente, uma vez que a credencial seja armazenada no armazenamento de credenciais.

Esse comportamento estranho teve um efeito grave na velocidade do aplicativo, pois cada solicitação causou duas viagens de ida e volta ao servidor em vez de uma (a primeira com o status 401, o segundo com 200).

Eu o resolvi definindo manualmente as credenciais no cabeçalho da solicitação HTTP:

NSString* credentials = [NSString stringWithFormat: @"%@:%@", usr, pwd];
const char* credentialsChars = [credentials cStringUsingEncoding: NSUTF8StringEncoding];
credentials = [CommunicationUtil stringBase64WithData: (const UInt8*) credentialsChars length: strlen(credentialsChars)];
NSString* authorizationHeader = [NSString stringWithFormat: @"Basic %@", credentials];

NSMutableURLRequest* request =
    [[NSMutableURLRequest alloc] initWithURL: url 
        cachePolicy: NSURLRequestReloadIgnoringLocalCacheData
        timeoutInterval: 15];

    [request setValue: authorizationHeader forHTTPHeaderField: @"Authorization"];

Agora meu aplicativo funciona muito bem e é muito receptivo.

A solução parecerá um pouco diferente para a autenticação de digestão. Mas você terá a ideia.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top