2016-02-13 53 views
8

所以我試圖使用JSON網絡令牌進行身份驗證,並試圖弄清楚如何將它們附加到標頭併發送請求。如何將json Web令牌添加到每個標頭?

我試圖使用https://github.com/auth0/angular2-jwt,但我無法讓它與Angular一起工作並放棄了,並且我想我可以弄清楚如何在每個請求中發送JWT或將它發送到頭部(最好是頭部) 。這比我想象的要難一些。

這裏是我的登錄

submitLogin(username, password){ 
     console.log(username); 
     console.log(password); 
     let body = {username, password}; 
     this._loginService.authenticate(body).subscribe(
      response => { 
       console.log(response); 
       localStorage.setItem('jwt', response); 
       this.router.navigate(['UserList']); 
      } 
     ); 

    } 

和我login.service

authenticate(form_body){ 
     return this.http.post('/login', JSON.stringify(form_body), {headers: headers}) 
       .map((response => response.json())); 
    } 

我知道這些都不是真正需要的,但也許它會幫助!一旦這個令牌被創建並且我存儲它,我想做兩件事,把它發送到頭文件中,並提取我放入的到期日期。

一些Node.js的一個登錄碼

var jwt = require('jsonwebtoken'); 
function createToken(user) { 
    return jwt.sign(user, "SUPER-SECRET", { expiresIn: 60*5 }); 
} 

現在我只是想通過一個角度的服務回報節點與此服務傳遞給它。

getUsers(jwt){ 
     headers.append('Authorization', jwt); 
     return this.http.get('/api/users/', {headers: headers}) 
      .map((response => response.json().data)); 
    } 

智威湯遜是我在本地存儲的webtoken,通過我的組件傳遞給服務。

我在任何地方都沒有錯誤,但是當它到達我的節點服務器時,我從來沒有收到它的頭文件。

'content-type': 'application/json', 
accept: '*/*', 
referer: 'http://localhost:3000/', 
'accept-encoding': 'gzip, deflate, sdch', 
'accept-language': 'en-US,en;q=0.8', 
cookie: 'connect.sid=s%3Alh2I8i7DIugrasdfatcPEEybzK8ZJla92IUvt.aTUQ9U17MBLLfZlEET9E1gXySRQYvjOE157DZuAC15I', 
'if-none-match': 'W/"38b-jS9aafagadfasdhnN17vamSnTYDT6TvQ"' } 
+0

yes..angular2,智威湯遜從auth0寫得不好......不能讓工作太 – Tampa

回答

13

創建自定義http類並覆蓋request方法在每個http請求中添加令牌。

http.service.ts

import {Injectable} from '@angular/core'; 
import {Http, XHRBackend, RequestOptions, Request, RequestOptionsArgs, Response, Headers} from '@angular/http'; 
import {Observable} from 'rxjs/Observable'; 
import 'rxjs/add/operator/map'; 
import 'rxjs/add/operator/catch'; 

@Injectable() 
export class HttpService extends Http { 

    constructor (backend: XHRBackend, options: RequestOptions) { 
    let token = localStorage.getItem('auth_token'); // your custom token getter function here 
    options.headers.set('Authorization', `Bearer ${token}`); 
    super(backend, options); 
    } 

    request(url: string|Request, options?: RequestOptionsArgs): Observable<Response> { 
    let token = localStorage.getItem('auth_token'); 
    if (typeof url === 'string') { // meaning we have to add the token to the options, not in url 
     if (!options) { 
     // let's make option object 
     options = {headers: new Headers()}; 
     } 
     options.headers.set('Authorization', `Bearer ${token}`); 
    } else { 
    // we have to add the token to the url object 
     url.headers.set('Authorization', `Bearer ${token}`); 
    } 
    return super.request(url, options).catch(this.catchAuthError(this)); 
    } 

    private catchAuthError (self: HttpService) { 
    // we have to pass HttpService's own instance here as `self` 
    return (res: Response) => { 
     console.log(res); 
     if (res.status === 401 || res.status === 403) { 
     // if not authenticated 
     console.log(res); 
     } 
     return Observable.throw(res); 
    }; 
    } 
} 

現在,我們需要來配置我們的主模塊提供XHRBackend我們的自定義HTTP類。在你的主模塊聲明,添加以下內容提供商陣列:

app.module.ts

import { HttpModule, RequestOptions, XHRBackend } from '@angular/http'; 
import { HttpService } from './services/http.service'; 
... 
@NgModule({ 
    imports: [..], 
    providers: [ 
    { 
     provide: HttpService, 
     useFactory: (backend: XHRBackend, options: RequestOptions) => { 
     return new HttpService(backend, options); 
     }, 
     deps: [XHRBackend, RequestOptions] 
    } 
    ], 
    bootstrap: [ AppComponent ] 
}) 

之後,您現在可以使用自定義HTTP提供您的服務。例如:

user.service.ts

import { Injectable }  from '@angular/core'; 
import {HttpService} from './http.service'; 

@Injectable() 
class UserService { 
    constructor (private http: HttpService) {} 

    // token will added automatically to get request header 
    getUser (id: number) { 
    return this.http.get(`/users/${id}`).map((res) => { 
     return res.json(); 
    }); 
    } 
} 

Source

7

我看到幾個選項來設置透明的標題爲每個請求:

  • 實現一個HttpClient的服務,而不是使用默認的HTTP之一。
  • 自己實現的RequestOptions類
  • 覆蓋在HTTP類是自我

這種方式,你可以設置你的頭在一個地方,這會影響你的AOK HTTP調用的。

請參見下面的問題:

+0

真棒!如果你想攔截每個'HTTP'請求,這非常有用。 – micronyks

+0

謝謝!我真的很感激你花時間回答所有這些問題,一半時間我的谷歌搜索引導我到你的答案時,我卡住了! –

0

下面是從角代碼的例子來獲得,例如計劃,你只是把它寫這樣的,

$scope.getPlans = function(){ 
    $http({ 
     url: '/api/plans', 
     method: 'get', 
     headers:{ 
     'x-access-token': $rootScope.token 
     } 
    }).then(function(response){ 
     $scope.plans = response.data; 
    }); 
    } 

,並在服務器上,你可以做到這一點,

var jwt = require('jsonwebtoken'); // used to create, sign, and verify tokens 
var config = require('./config'); // get our config file 

var secret = {superSecret: config.secret}; // secret variable 

// route middleware to verify a token. This code will be put in routes before the route code is executed. 
PlansController.use(function(req, res, next) { 

    // check header or url parameters or post parameters for token 
    var token = req.body.token || req.query.token || req.headers['x-access-token']; 

    // If token is there, then decode token 
    if (token) { 

    // verifies secret and checks exp 
    jwt.verify(token, secret.superSecret, function(err, decoded) { 
     if (err) { 
     return res.json({ success: false, message: 'Failed to authenticate token.' }); 
     } else { 
     // if everything is good, save to incoming request for use in other routes 
     req.decoded = decoded; 
     next(); 
     } 
    }); 

    } else { 

    // if there is no token 
    // return an error 
    return res.status(403).send({ 
     success: false, 
     message: 'No token provided.' 
    }); 

    } 
}); 

// Routes 
PlansController.get('/', function(req, res){ 
    Plan.find({}, function(err, plans){ 
    res.json(plans); 
    }); 
}); 

如果您還不清楚,你可以看看我的博客張貼在這裏,Node API Authentication with JSON Web Tokens - the right way細節。