【问题标题】:Angular 5 and Angular Universal state transfer with http interceptor and localstorage使用 http 拦截器和本地存储的 Angular 5 和 Angular Universal 状态传输
【发布时间】:2018-06-23 11:09:03
【问题描述】:

我在服务器端遇到问题,当我刷新页面时,无法从本地存储中检索服务器上的 jwt 令牌,因为本地存储仅存在于浏览器中。另外,当我登录时,我将令牌保存在传输状态,并在页面刷新后状态变量再次消失,这是正常行为吗?这个问题有解决办法吗?

这是我的拦截器:

import { Injectable, Injector, Inject, PLATFORM_ID } from '@angular/core';
import { HttpEvent, HttpInterceptor, HttpHandler, HttpRequest } from '@angular/common/http';
import { Observable } from 'rxjs/Rx';
import 'rxjs/add/observable/throw'
import 'rxjs/add/operator/catch';
import { makeStateKey, TransferState } from '@angular/platform-browser';
import { isPlatformServer, isPlatformBrowser } from '@angular/common';

const AUTH_STATE = makeStateKey<string>('authState');

@Injectable()
export class MyHttpInterceptor implements HttpInterceptor {
    private isServer: boolean;

    constructor(private tstate: TransferState, @Inject(PLATFORM_ID) private platformId) {
        this.isServer = isPlatformServer(platformId);
    }

    intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {

        console.log("intercepted request ... ");
        let authReq: any = req;

        if (this.tstate.hasKey(AUTH_STATE)) {
            // We are in the browser
            authReq = req.clone(
                {
                    headers: req.headers.set("Auth", this.tstate.get(AUTH_STATE, ''))
                }
            );

            console.log("CLIENT")
            console.log(this.tstate.get(AUTH_STATE, ''))
        } else if (this.isServer) {
            // We are on the server
            authReq = req.clone(
                {
                    headers: req.headers.set("Auth", "fromServer")
                }
            );

            console.log("SERVER")
        } else {
            // State not transfered
            let token: any;
            token = window.localStorage.getItem("token");

            if (token) {
                authReq = req.clone(
                    {
                        headers: req.headers.set("Auth", token)
                    })

                this.tstate.set(AUTH_STATE, token);
            }

            console.log("BROWSER")
        }
        console.log("Sending request with new header now ...");

        //send the newly created request
        return next.handle(authReq)
            .catch((error, caught) => {
                //intercept the respons error and displace it to the console 
                console.log("Error Occurred");
                console.log(error);
                //return the error to the method that called it
                return Observable.throw(error);
            }) as any;
    }
}

这部分:headers: req.headers.set("Auth", "fromServer") "fromServer" 应替换为本地存储中的正确令牌...

【问题讨论】:

    标签: local-storage angular5 angular-universal angular-http-interceptors


    【解决方案1】:

    您已经将this.isServer 用于您只想在服务器上运行的代码。任何对 localStorage 的使用都需要类似地包裹在 this.isBrowserif (isPlatformBrowser(this.platformId)) {}

    正如您所说,您将无法将令牌存储在 localStorage 中,然后在服务器端检索它。您可以将其包装在浏览器检查中,或者将令牌存储在您可以读取的位置(例如,数据库)。

    有关另一种存储方式,请参阅此答案:How to use localStorage in angular universal?

    【讨论】:

    • 我知道那是什么。这个问题有解决办法吗?
    • @Vladimir 你能澄清一下吗?您不能使用 localStorage 服务器端,因此您可以将其包装在浏览器检查中,或者将令牌存储在您可以读取的位置(例如数据库)。这是唯一的解决方案。
    • 但是我可以在服务器端发送一个标头,所以身份验证将只在客户端这是主要问题。
    • @Vladimir 我给你举个例子。假设我正在显示用户 Google 日历中的数据。为了进行身份验证,我从 Google 获取了一个令牌并将其存储在 localStorage 中,这样我就不必再次获取它了。我用那个令牌来询问他们的约会。在 Angular Universal 中,我无法将令牌存储在 localStorage 中,因此如果我必须在服务器端代码中拥有该令牌,我要么将其存储在数据库中,要么在每次需要时向 Google 索取它。在显示约会时,我不会在服务器端运行该代码。我将该代码包装在平台检查中,并仅在浏览器中运行。有意义吗?
    • 对不起,没有。要每次在服务器端请求令牌,您还需要将用户和密码存储在服务器端的某个位置,如果您能够将其存储在数据库中,您以后将如何为特定用户检索令牌?同样为了显示约会,您将需要服务器端的令牌,如果您没有令牌,它会闪烁,因为服务器和客户端上的数据不同......
    猜你喜欢
    • 1970-01-01
    • 2023-03-13
    • 1970-01-01
    • 1970-01-01
    • 2018-07-08
    • 1970-01-01
    • 1970-01-01
    • 2019-06-04
    • 2020-11-08
    相关资源
    最近更新 更多