2017-04-10 52 views
0

我想實現認證/授權(拉開序幕,這一點:https://github.com/aspnet/JavaScriptServices角2/.NET的核心 - 授權內容進行預渲染的角2和.NET核心

什麼是我的身份驗證令牌存儲選項(JWT ) - 所以它可能是訪問?:

  • 從客戶端:在登錄寫,需要更新令牌時,讀使GET/POST請求時
  • 從服務器:在讀取時節點預渲染的應用程序(相同的請求,但來自節點上下文)

我明白,預渲染受保護的內容沒有多大意義 - 因爲它不會被編入索引 - 但這會帶來閃爍問題。由於節點不能訪問此令牌(在我的情況) - 服務器返回的內容少的HTML(如果內容需要授權)

目前我儲存我的令牌在瀏覽器本地存儲:

localStorage.setItem('currentUser', JSON.stringify({ username: username, token: token })); 

.. 。顯然節點沒有這樣的事情,不能訪問它...

簡單的GET請求:

let headers = new Headers({ 'Authorization': 'Bearer ' + this.authenticationService.token }); 
let options = new RequestOptions({ headers: headers }); 
this.http.get(url, options).subscribe(response => callback(<any>response)); 

我真的很早就學習/採用此 - 我也要考慮任何其他auth方法,但必須遵守規則才能預先渲染授權內容。

回答

1

我能夠通過使用cookie作爲令牌存儲,然後將cookie從cookie傳遞到asp-prerender-module來解決此問題。

存儲服務客戶端和服務器:

declare var tokenStorage: NodeTokenStorage;  

@Injectable() 
export class TokenStorageService implements NodeTokenStorage { 

    getItem(key: string): string { 
     if (!isBrowser) { 
      return tokenStorage.getItem(key); 
     } 
     else { 
      return getCookie(key); 
     } 
    } 

    setItem(key: string, value: string): void { 
     if (!isBrowser) { 
      tokenStorage.setItem(key, value); 
     } 
     else { 
      setCookie(key, value, 1); 
     } 
    } 

    removeItem(key: string): void { 
     if (!isBrowser) { 
      tokenStorage.removeItem(key); 
     } 
     else { 
      removeCookie(key); 
     } 
    } 
} 

interface NodeTokenStorage { 
    getItem(key: string): string; 
    setItem(key: string, value: string): void; 
    removeItem(key: string): void; 
} 

注入cookie來預先渲染模塊:

<app 
    asp-prerender-module="ClientApp/dist/main-server" 
    asp-prerender-data='new { token = Context.Request.Cookies["token"] }'> 
    Loading... 
</app> 

閱讀它通過以下方式(ClientApp /啓動server.ts):

(global as any).tokenStorage = { 
    getItem: function(key) { 
     return this[key]; 
    }, 
    setItem: function (key, value) { 
     this[key] = value; 
    }, 
    removeItem: function(key) { 
     this[key] = undefined; 
    } 
} 

export default createServerRenderer(params => { 

    (global as any).tokenStorage.setItem('token', params.data.token); 

    return new Promise<RenderResult>((resolve, reject) => { 
     const requestZone = Zone.current.fork({ 
      name: 'angular-universal request', 
      properties: { 
       baseUrl: '/', 
       requestUrl: params.url, 
       originUrl: params.origin, 
       preboot: false, 
       document: '<app></app>' 
      }, 
      onHandleError: (parentZone, currentZone, targetZone, error) => { 
       // If any error occurs while rendering the module, reject the whole operation 
       reject(error); 
       return true; 
      } 
     }); 

     return requestZone.run<Promise<string>>(() => platform.serializeModule(AppModule)).then(html => { 
      resolve({ html: html }); 
     }, reject); 
    }); 
}); 

然後 - 當應用程序啓動時(在路由和在服務器端的redux存儲設置之前):我會讀第e令牌爲獲得認證的用戶獲取必要的數據。這樣,完整的html從服務器返回,包括所有auth內容和用戶特定的數據。

參考號: https://github.com/aspnet/JavaScriptServices/tree/dev/src/Microsoft.AspNetCore.SpaServices#server-side-prerendering