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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 22:06:25  来源:igfitidea点击:

Angular 2 AuthGuard Service with redirect?

javascriptangular

提问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 AuthGuardDo 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 UrlTreefrom 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(['/']);
        }
      }
    ));
}