Как подключить JWT защищенный Express.js Rest API с угловым приложением - PullRequest
0 голосов
/ 24 июня 2019

Я защитил свой API с помощью веб-токена JSON.Как я могу подключить это к моему угловому приложению.В приложении не будет логина и регистрации.

Я провел много исследований в Google, YouTube и StackOverflow.Но я так и не нашел желаемого результата.

Я просто хочу показать данные людям, которые заходят на сайт.Я не хочу, чтобы кто-то за пределами веб-сайта имел доступ к файлу Json.

Вот мой express.js

const app = require('express')()
const express = require('express')
const bodyParser = require('body-parser')
const cors = require('cors')
const fs = require('fs')
const jwt = require('jsonwebtoken')

const PORT = 3002

app.use(cors())
app.use(bodyParser.json())

app.get('/', (req, res) => {
    res.json({message: 'Api'})
  })

  app.post('/api/login',(req, res)=> {
    const user = { id: 3 }
    const token = jwt.sign({ user }, 'our_key')
    res.json({
      token: token
    })
  })

  app.get('/api/protected', ensureToken,(req, res)=>  {
    jwt.verify(req.token, 'our_key',function (err, data) {
      if (err) {
        res.sendStatus(403)
      } else {
        fs.readFile('data.json','utf-8',(err,data)=>{
          res.setHeader("Content-Type", "application/json;     charset=utf-8")
          data = JSON.parse(data)
          console.log(data)
          res.end(JSON.stringify(data,null,4))
      })
      }
    })
  })

  function ensureToken(req, res, next) {
    const bearerHeader = req.headers["authorization"]
    if (typeof bearerHeader !== 'undefined') {
      const bearer = bearerHeader.split(" ")
      const bearerToken = bearer[1]
      req.token = bearerToken
      next()
    } else {
      res.sendStatus(403)
    }
  }

app.listen(PORT, function(){
    console.log('Server http://localhost:'+ PORT + ' OK')  
  })

Везде, где angular и jwt подключены через систему входа / регистрации.Можем ли мы сделать это без этого?

1 Ответ

0 голосов
/ 24 июня 2019

В этом случае единственное решение, которое я вижу, заключается в следующем (и это не на 100% безопасно, если честно)

первое, что вы должны сделать на бэкэнд-стороне:

app.use(cors({
     origin: 'http://yourapp.com'
}));

, чтобы ограничить cors другими доменами.

Вторая часть на угловой стороне состоит в том, чтобы заставить токен работать и взаимодействовать с бэкэндом на стороне перехватчика.

После просмотра Кодекса это должно выглядеть следующим образом:

index.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <title>Stackoverflow - Test</title>
    <base href="/" />
  </head>
  <body>
    <app-root></app-root>
  </body>
</html>

appModule.ts

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http';
import { TokenInterceptor } from './data.service';
import { RouterModule, ROUTES } from '@angular/router';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    HttpClientModule,
  ],
  providers: [ {
    provide: HTTP_INTERCEPTORS,
    useClass: TokenInterceptor,
    multi: true,
}],
  bootstrap: [AppComponent]
})
export class AppModule { }

app.component.ts

import { Component, OnInit } from '@angular/core';
import { User } from './data.model';
import { Value } from './data.model';
import { HttpClient } from '@angular/common/http'
@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {

 users:User[];
 
 constructor(private _http: HttpClient){}

 ngOnInit(){
   this.loadData();
 }

  public async getToken(): Promise<void> {
    console.log('try to get token from api');
    const result: any = await this._http
              .get(`http://localhost:3002/api/login`)
              .toPromise();

    localStorage.setItem('userToken', result.token);
  }

 private async loadData(): Promise<void> {
   if (localStorage.getItem('userToken') == null) {
      await this.getToken();
   }
  
    const result = await this._http.get(`http://localhost:3002/api/protected`)
                .toPromise();

    console.log(result);
 }
}                

и ваш data.service.ts (который обычно для этой цели должен называться token.interceptor.ts или как-то так.

import { Injectable } from '@angular/core';
import {
  HttpEvent,
  HttpHandler,
  HttpInterceptor,
  HttpRequest,
  HttpClient
} from '@angular/common/http';
import { Observable, of } from 'rxjs';
import { User } from './data.model';
import {map, switchMap} from 'rxjs/operators';
@Injectable({
  providedIn: 'root'
})

export class TokenInterceptor implements HttpInterceptor {
  constructor(private _http: HttpClient) {}
  intercept(
      request: HttpRequest<any>,
      next: HttpHandler
  ): Observable<HttpEvent<any>> {
      let currentToken =
          localStorage.getItem('userToken') ||
          sessionStorage.getItem('userToken');
        const authReq = request.clone({
            setHeaders: {
                Authorization: 'Bearer ' + currentToken || []
            }
        });
        return next.handle(authReq);
}
}
...