Eu sou novo no AngularJS e estou um pouco confuso sobre como posso usar o "ui-router" angular no seguinte cenário:
Estou construindo um aplicativo da web que consiste em duas seções. A primeira seção é a página inicial com suas visualizações de login e inscrição e a segunda seção é o painel (após o login bem-sucedido).
Eu criei uma index.html
seção para a página inicial com seu aplicativo angular e ui-router
configuração para manipular /login
e/signup
exibir, e há outro arquivo dashboard.html
para a seção do painel com seu aplicativo e ui-router
configuração para manipular muitas visualizações secundárias.
Agora terminei a seção do painel e não sei como combinar as duas seções com seus aplicativos angulares diferentes. Como eu poderia dizer ao aplicativo inicial para redirecionar para o aplicativo do painel?
fonte
Respostas:
Estou no processo de criar uma demonstração melhor, além de limpar alguns desses serviços em um módulo utilizável, mas aqui está o que eu propus. Este é um processo complexo para contornar algumas advertências, então fique aí. Você precisará dividir isso em vários pedaços.
Dê uma olhada neste plunk .
Primeiro, você precisa de um serviço para armazenar a identidade do usuário. Eu chamo isso
principal
. Ele pode ser verificado para ver se o usuário está logado e, mediante solicitação, ele pode resolver um objeto que representa as informações essenciais sobre a identidade do usuário. Pode ser o que você precisar, mas o essencial seria um nome para exibição, um nome de usuário, possivelmente um email e as funções às quais um usuário pertence (se isso se aplica ao seu aplicativo). O Principal também possui métodos para fazer verificações de função.Segundo, você precisa de um serviço que verifique o estado em que o usuário deseja ir, verifique se está logado (se necessário; não necessário para entrar, redefinição de senha etc.) e faça uma verificação de função (se seu aplicativo precisa disso). Se eles não estiverem autenticados, envie-os para a página de entrada. Se eles estiverem autenticados, mas falharem na verificação de uma função, envie-os para uma página de acesso negado. Eu chamo esse serviço
authorization
.Agora tudo que você precisa fazer é ouvir em
ui-router
's$stateChangeStart
. Isso permite examinar o estado atual, o estado para o qual eles desejam ir e inserir sua verificação de autorização. Se falhar, você pode cancelar a transição da rota ou mudar para uma rota diferente.A parte complicada de rastrear a identidade de um usuário é procurar se você já se autenticou (por exemplo, você está visitando a página após uma sessão anterior e salvou um token de autenticação em um cookie, ou talvez você tenha atualizado uma página ou caiu para um URL a partir de um link). Por causa da maneira como
ui-router
funciona, você precisa resolver sua identidade uma vez, antes de verificar sua autenticação. Você pode fazer isso usando aresolve
opção na sua configuração de estado. Eu tenho um estado pai para o site que todos os estados herdam, o que força o principal a ser resolvido antes que qualquer outra coisa aconteça.Há outro problema aqui ...
resolve
só é chamado uma vez. Quando sua promessa de pesquisa de identidade for concluída, ela não executará o delegado de resolução novamente. Portanto, precisamos fazer suas verificações de autenticação em dois locais: uma vez de acordo com a promessa de identidade que está sendo resolvidaresolve
, que abrange a primeira vez que o aplicativo é carregado e outra$stateChangeStart
se a resolução foi concluída, que abrange qualquer momento em que você navega pelos estados.OK, então o que fizemos até agora?
Para onde vamos daqui? Bem, você pode organizar seus estados em regiões que necessitam de sinal. Você pode exigir que os usuários autenticados / autorizados pela adição
data
comroles
a estes estados (ou um pai deles, se você quiser usar a herança). Aqui, restringimos um recurso aos administradores:Agora você pode controlar estado por estado o que os usuários podem acessar uma rota. Alguma outra preocupação? Talvez variar apenas parte de uma visualização com base em se eles estão ou não conectados? Sem problemas. Use
principal.isAuthenticated()
ou mesmoprincipal.isInRole()
com qualquer uma das várias maneiras pelas quais você pode exibir condicionalmente um modelo ou elemento.Primeiro, injete
principal
em um controlador ou o que seja, e cole-o no escopo para que você possa usá-lo facilmente em sua visão:Mostrar ou ocultar um elemento:
Etc., etc., etc. De qualquer forma, em seu aplicativo de exemplo, você teria um estado para a página inicial que permitiria a exibição de usuários não autenticados. Eles podem ter links para os estados de entrada ou inscrição ou ter esses formulários incorporados nessa página. O que mais lhe convier.
Todas as páginas do painel podem herdar de um estado que exige que os usuários estejam conectados e, digamos, sejam
User
membros da função. Todo o material de autorização que discutimos fluiria a partir daí.fonte
$location.path
vez de$state.go
.$scope.user
na suathen
função. Você ainda pode fazer referênciauser
em seus pontos de vista; quando for resolvido, a exibição será atualizada.$q.when(angular.noop).then(function(){$state.go('myState')
, tudo funciona como esperado. Se eu ligar$state.go
enquanto outra transição de estado não estiver concluída, ela não funcionará (acho que é por isso que não funcionará).As soluções postadas até agora são desnecessariamente complicadas, na minha opinião. Existe uma maneira mais simples. A documentação do
ui-router
diz ouvir$locationChangeSuccess
e usar$urlRouter.sync()
para verificar uma transição de estado, interrompê-la ou retomar. Mas mesmo isso realmente não funciona.No entanto, aqui estão duas alternativas simples. Escolha um:
Solução 1: ouvindo
$locationChangeSuccess
Você pode ouvir
$locationChangeSuccess
e executar alguma lógica, mesmo lógica assíncrona lá. Com base nessa lógica, você pode deixar a função retornar indefinida, o que fará com que a transição de estado continue normalmente, ou você pode fazê-lo$state.go('logInPage')
, se o usuário precisar ser autenticado. Aqui está um exemplo:Lembre-se de que isso não impede que o estado de destino seja carregado, mas redireciona para a página de logon se o usuário não for autorizado. Tudo bem, já que a proteção real está no servidor.
Solução 2: usando estado
resolve
Nesta solução, você usa o
ui-router
recurso de resolução .Você basicamente rejeita a promessa
resolve
se o usuário não estiver autenticado e, em seguida, redireciona-o para a página de logon.Aqui está como vai:
Diferentemente da primeira solução, essa solução realmente impede que o estado de destino seja carregado.
fonte
state A
. Eles clicam em um link para acessar,protected state B
mas você deseja redirecioná-los paralogInPage
. Se não houver$timeout
,ui-router
simplesmente interromperá todas as transições de estado, para que o usuário fique presostate A
. O$timeout
permiteui-router
impedir primeiro a transição inicial para,protected state B
porque a resolução foi rejeitada e, depois disso, é redirecionada paralogInPage
.authenticate
função é realmente chamada?authenticate
função @Imray é passada como um parâmetro paraui-router
. Você não precisa se chamar.ui-router
chama.$stateChangeStart
?A solução mais fácil é usar
$stateChangeStart
eevent.preventDefault()
cancelar a alteração de estado quando o usuário não estiver autenticado e redirecioná-lo para o estado de autenticação que é a página de logon.fonte
Eu acho que você precisa de um
service
que lide com o processo de autenticação (e seu armazenamento).Neste serviço, você precisará de alguns métodos básicos:
isAuthenticated()
login()
logout()
Este serviço deve ser injetado nos controladores de cada módulo:
service.isAuthenticated()
método). caso contrário, redirecione para / loginservice.login()
métodoUm exemplo bom e robusto para esse comportamento é o aplicativo angular do projeto e, especificamente, seu módulo de segurança, baseado no incrível módulo HTTP Auth Interceptor
Espero que isto ajude
fonte
Criei este módulo para ajudar a tornar esse processo fácil
Você pode fazer coisas como:
Ou também
É novo, mas vale a pena conferir!
https://github.com/Narzerus/angular-permission
fonte
Eu queria compartilhar outra solução trabalhando com o ui router 1.0.0.X
Como você deve saber, stateChangeStart e stateChangeSuccess agora estão obsoletos. https://github.com/angular-ui/ui-router/issues/2655
Em vez disso, você deve usar $ transitions http://angular-ui.github.io/ui-router/1.0.0-alpha.1/interfaces/transition.ihookregistry.html
Foi assim que consegui:
Primeiro eu tenho e AuthService com algumas funções úteis
Então eu tenho esta configuração:
Você pode ver que eu uso
para marcar o estado apenas acessível se estiver autenticado.
então, no .run , uso as transições para verificar o estado autenticado
Eu construo este exemplo usando algum código encontrado na documentação de $ transitions. Eu sou muito novo com o roteador da interface do usuário, mas funciona.
Espero que possa ajudar alguém.
fonte
Aqui está como saímos do loop de roteamento infinito e ainda usamos em
$state.go
vez de$location.path
fonte
Eu tenho outra solução: essa solução funciona perfeitamente quando você tem apenas o conteúdo que deseja mostrar quando está conectado. Defina uma regra em que você verifica se está conectado e não é o caminho das rotas da lista de permissões.
No meu exemplo, pergunto se não estou logado e a rota atual que desejo encaminhar não faz parte de `/ login ', porque minhas rotas da lista de permissões são as seguintes
então eu tenho acesso instantâneo a essas duas rotas e todas as outras rotas serão verificadas se você estiver online.
Aqui está meu arquivo de roteamento completo para o módulo de login
() => { /* code */ }
é a sintaxe do ES6, use em vez dissofunction() { /* code */ }
fonte
Use o $ http Interceptor
Usando um interceptor $ http, você pode enviar cabeçalhos para o Back-end ou o contrário e fazer suas verificações dessa maneira.
Ótimo artigo sobre interceptores $ http
Exemplo:
Coloque isso na sua função .config ou .run.
fonte
Primeiro, você precisará de um serviço que possa injetar nos controladores com alguma idéia do estado de autenticação do aplicativo. Persistir detalhes de autenticação com armazenamento local é uma maneira decente de abordá-lo.
Em seguida, você precisará verificar o estado de autenticação antes de alterar o estado. Como seu aplicativo possui algumas páginas que precisam ser autenticadas e outras que não, crie uma rota pai que verifique a autenticação e faça com que todas as outras páginas que exigem o mesmo sejam filhas desse pai.
Por fim, você precisará de uma maneira de saber se o usuário conectado no momento pode executar determinadas operações. Isso pode ser conseguido adicionando uma função 'can' ao seu serviço de autenticação. O Can possui dois parâmetros: - ação - necessária - (ou seja, 'manage_dashboards' ou 'create_new_dashboard') - objeto - opcional - objeto em operação. Por exemplo, se você tinha um objeto de painel, convém verificar se dashboard.ownerId === logInUser.id. (Obviamente, as informações transmitidas pelo cliente nunca devem ser confiáveis e você sempre deve verificar isso no servidor antes de gravá-las no banco de dados).
** AVISO LEGAL: O código acima é pseudo-código e vem sem garantias **
fonte