Nginx: força SSL em um caminho, não SSL em outros

27

Como configuro o arquivo conf Nginx para forçar o SSL em apenas um dos caminhos do meu site e não SSL no restante?

Por exemplo, eu quero que todos os URLs em / user sejam https, mas todo o restante dos URLs seja http.

Para a primeira parte eu tenho:

rewrite ^/user(.*) https://$http_host$request_uri?;

Eu não quero usar "se". Suponho que tiraria vantagem da ordem de operação, mas não quero terminar em um loop.

Pbreitenbach
fonte

Respostas:

38

Na sua configuração nginx, você deve ter duas áreas de "servidor". Um para a porta 80 e outro para a porta 443 (não SSL e SSL). Basta adicionar um local no seu site não SSL para redirecionar para sua página SSL.

server {
    root /var/www/
    location / {
    }
    location /user {
        rewrite ^ https://$host$request_uri? permanent;
    }
}

encaminhará todo o tráfego que acaba em / user para o seu https: // server.

Então, no seu servidor 443, você faz o oposto.

server {
    listen 443;
    root /var/www/
    location / {
        rewrite ^ http://$host$request_uri? permanent;
    }
    location /user {
    }
}
grufftech
fonte
2
Esta abordagem é bom, mas ele cai em um par de comum armadilhas , especificamente "Root dentro do bloco de localização" e "reescreve Tributação"
kolbyjack
11
Eu editei. Parece bom? Também tirei listen 80 e adicionei http_host.
Pbreitenbach 18/05
Com essa configuração, a conexão alterna de / para ssl / não-ssl quando um usuário navega nas páginas do site, ssl para URLs iniciados com /usere non-ssl para todos os outros URLs. Como resultado, mesmo o usuário digita explicitamente https://www.example.com/na barra de endereços do navegador, a página resultante é http://www.example.com/. Existe uma maneira de implementar a reescrita automática de URL entre ssl / não-ssl, conforme alcançado pelas configurações descritas nesta resposta, mas ainda respeitar a solicitação explícita de ssl, se digitada explicitamente pelo usuário na barra de endereço? Obrigado!
goodbyeera
@goodbyeera yeah. Se a idéia é forçar os usuários a usar SSL em determinadas áreas, podemos substituir seus protocolos lá, mas honrá-los em qualquer outro lugar, simplesmente removendo os comandos de reescrita da configuração do servidor 443. Obviamente, agora, quando eles acessam uma parte segura, ainda navegam com SSL quando vão para outro lugar, mas isso permite que as pessoas escolham usar SSL desde o início.
Chuck Dries
13

O Nginx permite processar HTTP e HTTPS dentro do mesmo serverbloco. Portanto, você não precisa duplicar diretivas para ambas e pode redirecionar o caminho que deseja proteger

server {
  listen 80 default_server;
  listen 443 ssl;
  ... ssl certificate and other configs ...

  location /user {
    if ($scheme = 'http') {
      rewrite ^ https://$http_host$request_uri? permanent;
    }
  }

  ... your basic configuration ...
}

Certifique-se de não colocar a ssl onlinha lá, pois isso quebrará o HTTP simples.

Opcionalmente, você pode redirecionar todas as outras solicitações de HTTPS de volta para HTTP da mesma maneira:

if ($scheme = 'https') {
  rewrite ^ http://$http_host$request_uri? permanent;
}

ATUALIZAÇÃO : como Alexey Ten gentilmente aponta na seção de comentários, verificar schemecada solicitação não é uma idéia muito brilhante. Você deve seguir a maneira declarativa de configurar seu nginx. Nesse caso, declare dois blocos de servidor com redirecionamentos por location, mova a lógica comum para um arquivo separado e includeem ambos. Então a resposta da GruffTech é melhor.

Hnatt
fonte
2
É ineficaz criar um esquema de verificação nginx para cada solicitação.
Alexey Ten
11
Eu sei que a pergunta foi respondida há 3 anos, mas eu a encontrei lutando para fazer o que fiz gradualmente e só queria compartilhar meus resultados com pessoas que seguirão meus passos.
Hnatt
11
Bem, você deve ler wiki.nginx.org/IfIsEvil
Alexey Dez
11
@AlexeyTen não é o caso "quando você não pode evitar o uso de um if"? Existe outra maneira de ter a mesma configuração para HTTP e HTTPS sem duplicar diretivas?
Hnatt
2
Use includediretiva para diretivas comuns. Alguma duplicação está correta.
Alexey Ten