MEAN - Angular 路由覆盖 NodeJS 路由

MEAN - Angular routes over-riding NodeJS routes

我正在尝试通过 PassportJS 限制对客户端 Angular 应用程序的访问。

基本上,我试图将任何试图访问该应用程序的人重定向到身份验证提供商以进行登录。但是 angular 路由似乎覆盖了 NodeJS Express 路由。

因此,如果我转到“/”,它只会加载 angular 应用程序,而不会重定向它们。对于使用与 angular 路由相同的路由的每条路由,情况都是一样的。

server.js 片段:

以下代码应重定向所有人以登录 facebook。但它只是加载 angular 索引页。

function checkAuthentication(req,res,next){
    if(req.isAuthenticated()){
        //if user is looged in, req.isAuthenticated() will return true 
        console.log("/ " + true);
        res.sendFile(path.join(__dirname, 'dist/index.html'));
    } else{
        console.log("/ " + false);
        res.redirect("/api/passport/login/facebook");
    }
}

app.get('/*', checkAuthentication ,(req, res) => {
});

Angular index.html 片段:

index.html 页面使用与快速路由器中显示的相同的路由。

  <base href="/">

假设我将 index.html 基本 href 更改为使用“/app/”,如下所示:

  <base href="/app/">

并在 express 中设置路由以将登录用户重定向到“/app/”,如下所示:

angular.route 示例:

app.use("/app", express.static(path.join(__dirname, 'dist')));

function checkAuthentication(req,res,next){
    if(req.isAuthenticated()){
        //if user is looged in, req.isAuthenticated() will return true 
        console.log("/app" + true);
        res.sendFile(path.join(__dirname, '../../dist/index.html'));
    } else{
        console.log("/app" + false);
        res.redirect("/api/passport/login/facebook");
    }
}

router.get('/app', checkAuthentication, (req, res) => {
    console.log("approuter hit");
});

module.exports = router;

然后直接转到“/app”。它仍然会加载 angular index.html 页面并且不会重定向您登录。但是如果您转到“/”,它将重定向您登录。

如何阻止 angular 覆盖我的 NodeJS 快速路由?

更新:

app.route.js 片段:

import { Routes } from '@angular/router';
import { HomeComponent } from './home';

export const ROUTES: Routes = [
  { path: '',      component: HomeComponent },
];

您必须在客户端(即 Angular)实施 AuthGuard 和身份验证服务,这将充当客户端和服务器之间的通信器。同时保留一个像 isAuthenticated 这样的变量来跟踪登录状态。

授权卫士:

import { Injectable }     from '@angular/core';
import { CanActivate, CanActivateChild, Router }    from '@angular/router';

import { AuthenticationService } from './auth.service';

@Injectable()
export class AuthGuard implements CanActivate, CanActivateChild {

    constructor(private authService: AuthenticationService, private router: Router) {}
    canActivate() : boolean {
        console.log('AuthGuard#canActivate called ' + this.authService.isAuthenticated );
        return this.checkLoggedIn("random");
    }

    canActivateChild() : boolean {
        return this.canActivate();
    }

    checkLoggedIn(url: string): boolean {
        if (this.authService.isLoggedIn()) {
            return true;
        }
        this.authService.redirectUrl = url;
        this.router.navigate(['/login']);
        return false;
    }

}

身份验证服务:

import { Injectable } from '@angular/core';
import { Router } from '@angular/router';
import { Http, Response, Headers, RequestOptions } from '@angular/http';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';
import { Observable } from 'rxjs/Rx';
import { NgForm } from "@angular/forms";

import { AuthenticationApi } from "../../modules/authentication/authentication-api";
import { IUser } from "app/modules/authentication/user";
var headers = new Headers({ 'Content-Type': 'application/json' });
var options = new RequestOptions({ headers: headers });

@Injectable()
export class AuthenticationService implements AuthenticationApi {
  currentUser: IUser;
  redirectUrl: string;
  changePassoword: () => Observable<any>;
  forgotPassowrd: () => Observable<any>;

  isAuthenticated = false;
  constructor(private router: Router, private http: Http) {
    this.currentUser = null
  }

  isLoggedIn(): boolean {
    return !!this.currentUser;
  }

  logIn(logInUser:any): Observable<any> {
    console.log('UserService.signIn: ' + logInUser.userName + ' ' + logInUser.password + ' ' + logInUser.rememberMe);
    this.isAuthenticated = true;
    this.currentUser = {
      userName: logInUser.userName
    }
    return this.http.post('http://localhost:3000/auth/login',
      JSON.stringify(logInUser),
      options
    )
    .map((resp: Response) => resp.json())
    .catch(this.handleError);
    //return Observable.of({}).delay(2000);
    // return Observable.of({}).delay(2000).flatMap(x=>Observable.throw('Invalid User Name and/or Password'));
  }

  register(registerUser:any): Observable<any> {
    this.isAuthenticated = true;
    console.log(registerUser);
    return this.http.post('http://localhost:3000/auth/register',
      JSON.stringify(registerUser),
      options
    )
    .map((resp: Response) => resp.json())
    .catch(this.handleError);
      //this.router.navigate(['/signin']);
      //return Observable.of({}).delay(2000);
  }

  connectWithFacebook() :Observable<any> {
    this.isAuthenticated = true;
    //return Observable.of({}).delay(2000);
    return this.http.get('http://localhost:3000/auth/facebook')
    .map((resp: Response) => resp.json())
    .catch(this.handleError);
  }

  connectWithGoogle() :Observable<any> {
    this.isAuthenticated = true;
    //return Observable.of({}).delay(2000);
    return this.http.get('http://localhost:3000/auth/google')
    .map((resp: Response) => resp.json())
    .catch(this.handleError);
  }

  handleError(error: any) {
    console.error(error);
    return Observable.throw(error.json().error || 'Server error');
  }

  logOut(): Observable<any>{
    this.isAuthenticated = false;
    this.currentUser = null;
    this.router.navigate(['/login']);
    return Observable.of({})
  }

}

AuthenticationApi:通信常用方法

import { Observable } from 'rxjs';

export abstract class  AuthenticationApi {
    logIn : (loginUser:any) => Observable<any>;
    logOut : () => Observable<any>;
    register : (registerUser:any) => Observable<any>;
    connectWithFacebook : () => Observable<any>;
    connectWithGoogle : () => Observable<any>;
    changePassoword : () => Observable<any>;
    forgotPassowrd : () => Observable<any>;
}