Javascript 带重定向的 Angular 2 AuthGuard 服务?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/39002288/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Angular 2 AuthGuard Service with redirect?
提问by Judson Terrell
I have an application that I am building that implements CanActivate on the dashboard route. It works fine accept on page reload, I check a flag in the user service to see if a user is logged in or not. by default this flag is false which kicks the user out to login. Also on page reload I am trying to fetch use data with a token in localStorage, if fetch is successful, I want them to be able to stay on dashboard. The problem is that I am seeing a glimpse of login and having to manually redirect them to dashboard. Is there any way to fix this to where the authGuard doesn't do anything until after it checks the API? Code is here: https://github.com/judsonmusic/tfl
我有一个正在构建的应用程序,它在仪表板路由上实现了 CanActivate。它在页面重新加载时正常工作,我检查用户服务中的标志以查看用户是否已登录。默认情况下,这个标志是假的,它会踢出用户登录。同样在页面重新加载时,我试图在 localStorage 中使用令牌获取使用数据,如果获取成功,我希望它们能够留在仪表板上。问题是我看到了登录的一瞥,不得不手动将它们重定向到仪表板。有什么方法可以解决这个问题,直到 authGuard 在检查 API 之后才执行任何操作?代码在这里:https: //github.com/judsonmusic/tfl
dashboard:
仪表盘:
import{ Component , ViewChild} from '@angular/core';
import {LoginComponent} from "../login.component";
import {UserService} from "../user.service";
import {SimpleChartComponent} from "../charts/simpleChart.component";
import {AppleChartComponent} from "../charts/appleChart.component";
import {BarChartComponent} from "../charts/barChart.component";
import {DonutChartComponent} from "../charts/donutChart.component";
import {AlertComponent} from 'ng2-bootstrap/ng2-bootstrap';
import {ModalDemoComponent} from "../modals/modalDemoComponent";
import {NgInitHelperComponent} from "../helpers/nginit.helper.component";
import {ModalDirective} from "ng2-bootstrap/ng2-bootstrap";
import {MODAL_DIRECTIVES, BS_VIEW_PROVIDERS} from 'ng2-bootstrap/ng2-bootstrap';
@Component({
selector: 'dashboard',
templateUrl: '/app/components/dashboard/dashboard.component.html',
providers: [UserService, BS_VIEW_PROVIDERS],
directives: [SimpleChartComponent, AppleChartComponent, BarChartComponent, DonutChartComponent, AlertComponent, ModalDemoComponent, NgInitHelperComponent, ModalDirective]
})
export class DashboardComponent {
public areas:any;
constructor() {
this.areas = [
"Spiritual",
"Habits",
"Relationships",
"Emotional",
"Eating Habits",
"Relaxation",
"Exercise",
"Medical",
"Financial",
"Play",
"Work/ Life Balance",
"Home Environment",
"Intellectual Well-being",
"Self Image",
"Work Satisfaction"
]
}
}
Routes:
路线:
import { Routes, RouterModule } from '@angular/router';
import { AboutComponent } from './components/about.component';
import {PageNotFoundComponent} from "./components/pageNotFound.component";
import {HomeComponent} from "./components/home.component";
import {DashboardComponent} from "./components/dashboard/dashboard.component";
import {SurveyComponent} from "./components/survey/survey.component";
import {ResourcesComponent} from "./components/resources.component";
import {LogoutComponent} from "./components/logout.component";
import {AuthGuard} from "./components/auth-guard.service";
import { loginRoutes, authProviders } from './login.routing';
import {LoginComponent} from "./components/login.component";
const appRoutes:Routes = [
{ path: '', component: HomeComponent },
{ path: 'dashboard', component: DashboardComponent, canActivate: [AuthGuard] },
{ path: 'logout', component: LogoutComponent },
{ path: 'resources', component: ResourcesComponent },
{ path: 'survey', component: SurveyComponent },
{ path: 'about', component: AboutComponent},
{ path: 'login', component: LoginComponent},
{ path: '**', component: PageNotFoundComponent}
];
export const appRoutingProviders: any[] = [
authProviders
];
export const routing = RouterModule.forRoot(appRoutes);
login route:
登录路径:
import { Routes } from '@angular/router';
import { AuthGuard } from './components/auth-guard.service';
import { AuthService } from './components/auth.service';
import { LoginComponent } from './components/login.component';
export const loginRoutes: Routes = [
{ path: 'login', component: LoginComponent }
];
export const authProviders = [
AuthGuard,
AuthService
];
回答by rashfmnb
in AuthGuard
Do this
在AuthGuard
做这个
@Injectable()
export class AuthGuard implements CanActivate {
auth: any = {};
constructor(private authService: AuthService, private router: Router) {
}
canActivate() {
if (/*user is logged in*/) {
this.router.navigate(['/dashboard']);
return true;
}
else {
this.router.navigate(['/Login']);
}
return false;
}
}
回答by Judson Terrell
I actually changed my service to this and it works:
我实际上将我的服务更改为这个并且它有效:
import { Injectable } from '@angular/core';
import { CanActivate, Router,
ActivatedRouteSnapshot,
RouterStateSnapshot } from '@angular/router';
import { AuthService } from './auth.service';
import {UserService} from "./user.service";
@Injectable()
export class AuthGuard implements CanActivate {
constructor(private authService: AuthService, private router: Router, private userService: UserService) {}
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
if (this.authService.isLoggedIn){
console.log('ATUH GUARD SAYD THEY ARE ALREADY LOGGED IN!');
return true;
}else {
this.userService.getUser().subscribe((user) => {
console.log('AUTH GUARD GETTING USER', user);
if (user._id) {
this.authService.isLoggedIn = true;
// Store the attempted URL for redirecting
this.authService.redirectUrl = state.url;
this.router.navigate(['/dashboard']);
return true;
}else{
console.log('Validation Failed.');
localStorage.clear();
this.router.navigate(['/login']);
return false;
}
}, (error) => {
console.log('There was an error.');
this.router.navigate(['/login']);
return false
});
}
}
}
回答by Simon_Weaver
You can now return a UrlTree
from an AuthGuard, or a boolean true / false.
您现在可以UrlTree
从 AuthGuard 或布尔值 true / false返回 a 。
https://blog.angularindepth.com/new-in-angular-v7-1-updates-to-the-router-fd67d526ad05
https://blog.angularindepth.com/new-in-angular-v7-1-updates-to-the-router-fd67d526ad05
Kind of amazed nobody has mentioned this yet! Sorry no example right now, but the idea is pretty simple.
有点惊讶还没有人提到这个!对不起,现在没有例子,但这个想法很简单。
回答by michelepatrassi
Here's how to correctly handle redirects in a guard by using an UrlTree
以下是如何使用 UrlTree 正确处理警卫中的重定向
@Injectable({
providedIn: 'root'
})
export class AuthGuard implements CanActivateChild {
constructor(
private authService: AuthService,
private logger: NGXLogger,
private router: Router
) {}
canActivateChild(
next: ActivatedRouteSnapshot,
state: RouterStateSnapshot): Observable<boolean | UrlTree> {
return this.authService.isLoggedIn().pipe(
map(isLoggedIn => {
if (!isLoggedIn) {
return this.router.parseUrl('/login');
}
return true;
})
);
}
}
Big thanks to Angular In Depthfor the explanation!
非常感谢Angular In Depth的解释!
回答by daniel gi
I solved it like this and used it in my AuthGuard
我是这样解决的,并在我的 AuthGuard 中使用它
isLoggedIn(): Observable<boolean> {
return this.afAuth.authState
.pipe(
take(1),
map(user => {
return !!user;
},
() => {
return false;
}
),
tap(loggedIn => {
if (!loggedIn) {
this.router.navigate(['/']);
}
}
));
}