0

我正在使用 MEAN 堆栈进行登录身份验证。我在前端使用角度 4。我正在尝试基于登录实现显示/隐藏导航。当用户登录时,它必须显示导航列表,但它不显示它,也没有给出任何错误,但它只在登录前后显示登录按钮。下面是我的代码,任何人都可以在我犯错误的地方帮助我。对于后端登录身份验证,我使用了 passport.js 和 express session。我没有使用 JWT 令牌。

//navbar.component.html

<div class="collapse navbar-collapse" id="myNavbar">
          <ul class="nav navbar-nav">
              <ng-template *ngIf="isAuthenticated()"> <!-- Here I used [ngIf]="isAuthenticated()" as well still it doesn't work-->
                <li><a routerLink="/jobs">Jobs</a></li>
                <li><a routerLink="/users">Users</a></li>
                <li ><a routerLink="/register">Register a User</a></li>
              </ng-template>
          </ul>
          <ul class="nav navbar-nav navbar-right">
            <ng-template *ngIf="isAuthenticated()">
                <li><a (click)="onLogout()">Logout</a></li>
            </ng-template>
            <li *ngIf="!isAuthenticated()" routerLinkActive="active"><a routerLink="/login">Login</a></li>
        </ul>
</div>

//navbar.component.ts

export class NavbarComponent implements OnInit {
  constructor(private authService: AuthService, 
              private router: Router) { }
  ngOnInit() {
  }
  onLogout() {
    this.authService.logout()
      .subscribe(
        (res) => {
          if (res) {
            this.router.navigate(['/login']);
          }
        }
      );
  }
  isAuthenticated() {
    this.authService.isAuthenticated();
  }
}

//auth.service.ts

export class AuthService {
    url = 'http://localhost:3000/api/users'
    constructor(private router: Router,
                private http: HttpClient) {}
    signInWithEmailAndPassword (userDetails) {
        return this.http.post(this.url + '/login', userDetails, { observe: 'body', responseType: 'json'})
            .map(
                (response) => {
                    return response;
                }
            )
    }

    logout() {
        return this.http.get(this.url + '/logout')
            .map((response) => {return response})
    }

    isAuthenticated() {
        return this.http.get(this.url + '/is-logged-in')
            .map((response) => { return response })
    }
}

*********** Node.js 后端代码 ***********

//server.js

const userRoute = require('./routes/user-route');
app.use('/api/users', userRoute);

//user.router.js

userRoute.get('/is-logged-in', authMiddleware.isUserLoggedIn, authMiddleware.isUserActive, user.isLoggedInUser)

//authMiddleware.js

const authMiddleware = {
isUserActive: (req, res, next) => {
        req.user.isActive === true ? next() : res.status(401).send({message: 'No User Found!'});
    },
    isUserLoggedIn: (req, res, next) => {
        console.log('imcalled from auth');
        req.isAuthenticated() ? next() : res.status(401).send({message: 'You must be LoggedIn'});
    }
}

//user.controller.js

const user = {
    isLoggedInUser: (req, res) => {
        res.status(200).send(true);
    }
};
4

1 回答 1

1

尝试使用async位于https://angular.io/api/common/AsyncPipe的管道。

异步管道订阅 Observable 或 Promise 并返回它发出的最新值。当发出新值时,异步管道会标记要检查更改的组件。当组件被销毁时,异步管道会自动取消订阅以避免潜在的内存泄漏。

您可以分配isAuthenticated()给变量并应用于async它。

_isAuthenticated: Observable<any>
ngOnInit() {
  this._isAuthenticated = this.isAuthenticated();
}
isAuthenticated() {
  return this.authService.isAuthenticated();
}

而在 HTML 中,*ngIf="_isAuthenticated | async". (添加return到 isAuthenticated() 作为 RRForUI 和 Chau Tran 感知)。

另一个解决方案是添加一个布尔变量并订阅 observable(这个解决方案更好,因为正如 Benedikt Schmidt 所说,Angular 只调用服务器一次):

_isAuthenticated: boolean;
ngOnInit() {
  this.authService.isAuthenticated().subscribe(res => {
    this._isAuthenticated = res;
  });      
}

在此解决方案中,isAuthenticated()不再需要该功能,而在 HTML 中,您只需使用*ngIf="_isAuthenticated".

最后,返回response.json()auth.service.ts

...
.map((response) => { return response.json() })
于 2017-11-27T19:32:37.523 回答