2017-04-10 90 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