如何在 Angular 8 中检查会话

发布时间:2021-02-25 08:00

我用 angular 8 和 node js 创建了登录表单。我已经在后端使用 node js 设置了会话。我无法检查会话设置或不在 angular 中,以避免在未登录的情况下访问仪表板。请建议使用 angular 8 和 node js 使用登录系统的方法。谢谢....

回答1

一种非常流行的方法是使用 JWT(JSON 网络令牌)npm package 进行身份验证。

流程如下:

  1. 向服务器发送凭据
  2. 服务器生成并发送回 JWT 或不记名令牌
  3. FrontEnd 会将其存储在浏览器 cookie 或 localStorage 中
localStorage.setItem('TOKEN', tokenReceivedFromServer);
  1. 在随后的 Api 调用中,令牌将在标头(授权)中发送到服务器。
Authorization: `JWT ${localStorage.getItem('TOKEN')}`

仅供参考:JWT 关键字在解析令牌之前从服务器上的字符串中删除

前端可以检查令牌是否设置在存储中以显示登录页面/仪表板

回答2

首先我们需要检查应用程序中的登录凭据是否有效。

在 Angular 应用程序组件打字稿文件中,我们在参数中发送了数据服务,该服务使用 httpclient 将值发送到后端。如果凭据有效,我们将在 localstorage 中设置该值。

submitLogin(data:any)
  {
    this.LoginService.loginData(data).subscribe(data =>{
      
      if(data.body.status_code == 404)
      {
        Swal.fire({
          icon: 'warning',
          title: 'Invalid E-Mail/Password!',
        }).then(function(){
          
        });
      }else if(data.body.status_code ==200)
      {
        localStorage.setItem("user_id",data.body.token);
        this.router.navigate(['/Dashboard']);
      }else
      {
        Swal.fire({
          icon: 'error',
          title: 'Process Failed!',
        }).then(function(){
        
        });
      }
    });
  }

在 service.ts 文件中确保导入那些包

import { HttpClient } from '@angular/common/http';
import { Observable, throwError } from 'rxjs';
import {Login} from './login';

在登录数据函数中

url = "http://localhost:3000/loginCheck";

  loginData(Login:Login):Observable<any>
  {
    return this.http.post(this.url,Login,{observe: 'response'});
  }

在后端我使用了 node.js

在文件 app.js 中

首先安装 jsonwebtoken 包并包含在文件中。

npm install jsonwebtoken

然后在where条件满足时设置jsonwebtoken

let payload = {subject:employee_id}
let token = jwt.sign(payload,'secretKey')

var response = { 
               'token': token,
               "status_code":200,
      }
                
res.send(response);
res.end();

每当我们使用 angular 登录时,我们都必须使用 authguard 路由,它有助于在不登录的情况下访问仪表板。

ng generate guard auth

在 auth.guard.ts 文件中,我们必须包含包和服务

import { CanActivate, Router } from '@angular/router';
import {LoginService} from './login.service';

export class AuthGuard implements CanActivate {

  constructor(private LoginService:LoginService,private router:Router) {}

  canActivate(): boolean
  {
    if(this.LoginService.loggedIn())
    {
      return true
    }else
    {
      this.router.navigate(['/login']);
      return false;
    }
  }
  
}

在这个文件中,我们只检查布尔数据类型中是否设置了 localstorage 值。

在服务文件中

布尔类型的get和return添加如下代码

loggedIn()
  {
    return !!localStorage.getItem('user_id')
  }


getToken()
      {
        return localStorage.getItem('user_id')
      }

如果它返回 true 我们可以访问仪表板,否则它会重定向到登录页面。

我们必须在路由中使用这个canActive函数,否则它将无法工作

在 app-routing.module.ts 文件中

import { AuthGuard } from './auth.guard';

    const routes: Routes = [
  {path:'Dashboard',component:DashboardComponent},
  {path:'receipt',component:ReciptComponentComponent,canActivate:[AuthGuard]},
];

这将有助于我们在没有登录的情况下访问仪表板,但我们需要在后端检查令牌是否有效,我们可以使用角度拦截器来做到这一点

我们应该使用拦截器名称创建新服务

ng g service token-interceptor

在拦截器文件中我们需要导入以下内容

import { Injectable,Injector } from '@angular/core';
import { HttpInterceptor } from '@angular/common/http';
import { LoginService } from './login.service';

在拦截器中,服务以与组件不同的方式注入。

export class TokenInterceptorService implements HttpInterceptor{

  constructor(private Injector:Injector) { }
  intercept(req:any,next:any)
  {
    let loginService = this.Injector.get(LoginService);
    let tokenzedReq = req.clone({
      setHeaders:
      {
        Authorization: `Bearer ${loginService.getToken()}`
      }
    });

    return next.handle(tokenzedReq)
  }
}

我们需要在拦截器中创建一个名为interceptor的函数,然后我们需要按照注入器来注入服务。

在后端我们需要创建辅助函数来验证jsonwebtoken

如果未设置授权,我们可以发送响应 401 not found 并且可以重定向到登录页面

function verifyToken(req,res,next)
{
    if(!req.headers.authorization)
    {
        return res.status(401).send('Unauthorized request');
    }

    var token = req.headers.authorization.split(' ')[1];

    if(!token)
    {
        return res.status(401).send('Unauthorized request');
    }

    if(token === 'null')
    {
        return res.status(401).send('Unauthorized request');
    }

    //let payload = jwt.verify(token,'secretKey');
let payload = jwt.decode(token,'secretKey');

    if(!payload)
    {
        return res.status(401).send('Unauthorized request');
    }

    req.userId = payload.subject;

    next();

}

然后我们可以在任何需要的地方使用这个中间件功能

例如

app.get('/dashboard',verifyToken,function(req,res){
    let events = [];
    res.json(events);
});

在仪表板组件 ts 文件中

this.dashboardService.getData().subscribe(data=>this.dashboardData=data,
      err=>{
        if(err instanceof HttpErrorResponse)
        {
          if(err.status===401)
          {
            this.router.navigate(['/login']);
          }
        }
      })

在仪表板服务 ts 文件中

 url = "http://localhost:3000/dashboard";

  getData()
  {
    return this.http.get<any>(this.url);
  }

在 app.module.ts 文件中

    import { AuthGuard } from './auth.guard';
    import { ReciptComponentComponent } from './recipt-component/recipt-component.component';
import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http';
    import { TokenInterceptorService } from './token-interceptor.service';
    import { DashboardServiceService } from './dashboard-service.service';

在供应商中

 providers: [AuthGuard,{provide:HTTP_INTERCEPTORS,useClass:TokenInterceptorService,multi:true},DashboardServiceService],