Eu venho do mundo Asp.Net MVC, onde os usuários que tentam acessar uma página que não estão autorizadas são automaticamente redirecionados para a página de login.
Estou tentando reproduzir esse comportamento no Angular. Eu vim pelo decorador @CanActivate, mas resulta no componente não renderizando, sem redirecionamento.
Minha pergunta é a seguinte:
- O Angular fornece uma maneira de atingir esse comportamento?
- Se sim, como? É uma boa prática?
- Caso contrário, qual seria a melhor prática para lidar com a autorização do usuário no Angular?
login
typescript
angular
angular2-routing
Amaury
fonte
fonte
Respostas:
Atualização: publiquei um projeto esqueleto completo do Angular 2 com integração do OAuth2 no Github que mostra a diretiva mencionada abaixo em ação.
Uma maneira de fazer isso seria através do uso de a
directive
. Ao contrário do Angular 2components
, que são basicamente novas tags HTML (com código associado) que você insere em sua página, uma diretiva de atributo é um atributo que você coloca em uma marca que causa algum comportamento. Documentos aqui .A presença do seu atributo personalizado faz com que as coisas aconteçam com o componente (ou elemento HTML) em que você colocou a diretiva. Considere esta diretiva que eu uso no meu aplicativo Angular2 / OAuth2 atual:
Isso faz uso de um serviço de autenticação que escrevi para determinar se o usuário já está conectado ou não e também se inscreve no evento de autenticação para que ele possa expulsar um usuário se ele se desconectar ou atingir o tempo limite.
Você poderia fazer a mesma coisa. Você criaria uma diretiva como a minha que verifica a presença de um cookie necessário ou outras informações de estado que indiquem que o usuário está autenticado. Se eles não tiverem os sinalizadores que você procura, redirecione o usuário para sua página pública principal (como eu) ou para o servidor OAuth2 (ou o que for). Você colocaria esse atributo de diretiva em qualquer componente que precise ser protegido. Nesse caso, pode ser chamado
protected
como na diretiva que colei acima.Em seguida, você deseja navegar / redirecionar o usuário para uma visualização de login no seu aplicativo e manipular a autenticação lá. Você teria que mudar a rota atual para a que você queria fazer isso. Portanto, nesse caso, você usaria a injeção de dependência para obter um objeto Router na
constructor()
função da diretiva e, em seguida, usaria onavigate()
método para enviar o usuário à sua página de login (como no meu exemplo acima).Isso pressupõe que você tenha uma série de rotas em algum lugar controlando uma
<router-outlet>
tag que se parece com isso, talvez:Se, em vez disso, você precisasse redirecionar o usuário para um URL externo , como o servidor OAuth2, sua diretiva faria algo como o seguinte:
fonte
Aqui está um exemplo atualizado usando Angular 4 (também compatível com Angular 5 - 8)
Rotas com rota doméstica protegidas pelo AuthGuard
AuthGuard redireciona para a página de login se o usuário não estiver logado
Atualizado para passar o URL original nos parâmetros de consulta para a página de login
Para o exemplo completo e a demonstração de trabalho, você pode conferir esta postagem
fonte
currentUser
nolocalStorage
ainda seria capaz de acessar a rota protegida? por exemplo.localStorage.setItem('currentUser', 'dddddd')
?Uso com o roteador final
Com a introdução do novo roteador, ficou mais fácil proteger as rotas. Você deve definir um guarda, que atua como um serviço, e adicioná-lo à rota.
Agora passe o
LoggedInGuard
para a rota e também adicione-o àproviders
matriz do módulo.A declaração do módulo:
Postagem detalhada no blog sobre como funciona com a versão final: https://medium.com/@blacksonic86/angular-2-authentication-revisited-611bf7373bf9
Uso com o roteador obsoleto
Uma solução mais robusta é estender
RouterOutlet
e ao ativar uma rota, verificar se o usuário está conectado. Dessa forma, você não precisa copiar e colar sua diretiva em todos os componentes. Além disso, o redirecionamento com base em um subcomponente pode ser enganoso.A
UserService
representa o lugar onde sua lógica de negócios reside se o usuário está logado ou não. Você pode adicioná-lo facilmente com DI no construtor.Quando o usuário navega para um novo URL no seu site, o método de ativação é chamado com a Instrução atual. A partir dele, você pode pegar o URL e decidir se é permitido ou não. Se não, basta redirecionar para a página de login.
Uma última coisa que resta para fazê-lo funcionar é repassá-lo ao nosso componente principal, em vez do componente interno.
Esta solução não pode ser usada com o
@CanActive
decorador do ciclo de vida, porque se a função passada para ele resolver falsa, o método de ativação doRouterOutlet
não será chamado.Também escreveu uma postagem detalhada no blog: https://medium.com/@blacksonic86/authentication-in-angular-2-958052c64492
fonte
Failed to lint <classname>.router-outlet.ts[15,28]. In the constructor of class "LoggedInRouterOutlet", the parameter "nameAttr" uses the @Attribute decorator, which is considered as a bad practice. Please, consider construction of type "@Input() nameAttr: string".
Não foi possível descobrir o que alterar no construtor ("_parentRounter") para se livrar dessa mensagem. Alguma ideia?_parentRouter: Router, @Input() nameAttr: string,
e tslint não gera mais o erro. Também substituiu a importação "Atributo" para "Entrada" do núcleo angular. Espero que isto ajude.Por favor, não substitua a saída do roteador! É um pesadelo com a versão mais recente do roteador (3.0 beta).
Em vez disso, use as interfaces CanActivate e CanDeactivate e defina a classe como canActivate / canDeactivate na sua definição de rota.
Curtiu isso:
Classe:
Consulte também: https://angular.io/docs/ts/latest/guide/router.html#!#can-activate-guard
fonte
Seguindo as respostas impressionantes acima, eu também gostaria de
CanActivateChild
: guardar rotas para crianças. Ele pode ser usado para adicionarguard
rotas secundárias úteis para casos como ACLsÉ assim
Isso é obtido em https://angular.io/docs/ts/latest/guide/router.html#!#can-activate-guard
fonte
Consulte este código, arquivo auth.ts
fonte
1. Create a guard as seen below. 2. Install ngx-cookie-service to get cookies returned by external SSO. 3. Create ssoPath in environment.ts (SSO Login redirection). 4. Get the state.url and use encodeURIComponent.
fonte