简体   繁体   English

Blazor:在没有会话/JWT 令牌时重定向到登录页面?

[英]Blazor: Redirect to Login page when there is no session / JWT token?

I am trying to create a new application in Blazor and am working on authentication.我正在尝试在 Blazor 中创建一个新应用程序并且正在处理身份验证。 I am using a JWT tokens that is stored in Local storage.我正在使用存储在本地存储中的 JWT 令牌。 When the application loads i need to check if there is a token in the storage.当应用程序加载时,我需要检查存储中是否有令牌。 If so, add it to the HTTP headers for all API requests, if not then redirect to the login page before the page loads....... where do i do that?如果是这样,请将其添加到所有 API 请求的 HTTP 标头中,如果没有,则在页面加载之前重定向到登录页面......我在哪里做? There are multiple pages that need this check so this needs to be done in a single location to cover all.有多个页面需要进行此检查,因此需要在一个位置完成以覆盖所有页面。 Should this be done in the Startup?这应该在启动中完成吗?

Searching did not provide a solution and since i am new to Blazor finding the right search terms is a bit difficult :)搜索没有提供解决方案,因为我是 Blazor 的新手,找到正确的搜索词有点困难:)

Create a component and name it RedirectToLogin.razor :创建一个组件并将其命名为RedirectToLogin.razor

@inject NavigationManager Navigation
@code {
    [CascadingParameter]
    private Task<AuthenticationState> AuthenticationStateTask { get; set; }

    protected override async Task OnInitializedAsync()
    {
        var authenticationState = await AuthenticationStateTask;

        if (authenticationState?.User?.Identity is null || !authenticationState.User.Identity.IsAuthenticated)
        {
            var returnUrl = Navigation.ToBaseRelativePath(Navigation.Uri);

            if (string.IsNullOrWhiteSpace(returnUrl))
                Navigation.NavigateTo("YourLoginPath", true);
            else
                Navigation.NavigateTo($"{YourLoginPath}?returnUrl={returnUrl}", true);
        }
    }
}

Modify App.razor :修改App.razor

<Found Context="routeData">
    <AuthorizeRouteView RouteData="@routeData" DefaultLayout="@typeof(HostLayout)">
        <NotAuthorized>
            <RedirectToLogin></RedirectToLogin>
        </NotAuthorized>
    </AuthorizeRouteView>
</Found>

Credits go to: this article学分转到:这篇文章

What I did was to write my own http service to do this.我所做的是编写自己的 http 服务来做到这一点。

It is called Backend and has a property for the token like this:它被称为 Backend 并且具有这样的令牌属性:

    public string ApiToken
    {
        get
        {
            if (!string.IsNullOrEmpty(apitoken))
                return apitoken;

            apitoken = Browser.ReadStorage("apitoken");
            return apitoken;
        }

        set
        {
            Browser.WriteStorage("apitoken", value);
        }
    }

And then in this class implement all the methods that the http class has, while injecting your token.然后在这个类中实现 http 类具有的所有方法,同时注入您的令牌。 for instance:例如:

    public async Task<T> GetJsonAsync<T>(string uri)
    {
            this.InProgress = true;
            var result = await http.GetJsonAsync<ServerResult<T>>(uri, this.ApiToken);
            this.InProgress = false;

            if (!result.Success)
            {
                BlazorExtensions.Browser.Alert($"Error: {result.ErrorMessage}");
                return default(T);
            }

            return result.ValueObject;

    }

And everywhere use the backend service to do your requests.并且到处使用后端服务来处理您的请求。 Also handy for your api url.对于您的 api 网址也很方便。

EDIT For the redirection part: For brevity I left out this part, but this is the full method:编辑对于重定向部分:为简洁起见,我省略了这一部分,但这是完整的方法:

    public async Task<T> GetJsonAsync<T>(string uri)
    {
        try
        {
            this.InProgress = true;
            var result = await http.GetJsonAsync<ServerResult<T>>(uri, this.ApiToken);
            this.InProgress = false;

            if (!result.Success)
            {
                BlazorExtensions.Browser.Alert($"Error: {result.ErrorMessage}");
                return default(T);
            }

            return result.ValueObject;
        }
        catch (UnauthorizedAccessException)
        {
            this.InProgress = false;
            uriHelper.NavigateTo("/bzr/Logon");
            return default(T);
        }
        catch (Exception e)
        {
            BlazorExtensions.Browser.Alert($"Fout bij http fetch: {e.Message}");
            this.InProgress = false;
            return default(T);
        }
    }

The uriHelper is simply injected in the constructor: uriHelper只是简单地注入到构造函数中:

    public IUriHelper uriHelper { get; private set; }

    public Backend(HttpClient httpInstance, IUriHelper uriHelper)
    {
        http = httpInstance;
        this.uriHelper = uriHelper;

Guess that's what you need?猜猜这就是你需要的?

What do you mean Startup ?你是什​​么意思Startup The Startup class, right ?创业班,对吧?

Right now the Razor Components framework does not have application event cycles.现在 Razor 组件框架没有应用程序事件循环。 Be patient...it is coming... Meanwhile, for learning's sake use Components event cycles.耐心点......它即将到来......同时,为了学习,使用组件事件循环。 Generally, you should store yourJWT in the local storage, including data about the user, whether he has been authenticated and such like, and a service which retrieves this data finding out if the user is authenticated.通常,您应该将您的 JWT 存储在本地存储中,包括有关用户的数据、他是否已通过身份验证等,以及检索此数据以确定用户是否已通过身份验证的服务。 You can call this service whenever authentication (or authorization) is necessary.您可以在需要身份验证(或授权)时调用此服务。

Incidentally, you don't mean to stop the process of ... by saying " before the page loads ".顺便说一句,您并不是要通过说“ before the page loads ”来停止...的过程。 You just mean that you don't want the "New Profile Page", as for instance, in online dating website, to be displayed, if the user is not authenticated, right ?您只是说您不希望显示“新个人资料页面”,例如在在线约会网站中,如果用户未通过身份验证,对吗? Well, in that case, call the authenticating local service (which retrieves data from the local storage), from the page (Component) OnInit or OnInitAsync methods.那么,在这种情况下,从页面(组件)的 OnInit 或 OnInitAsync 方法调用身份验证本地服务(从本地存储检索数据)。

Hope this helps...希望这可以帮助...

A solution (for now, not the best i think?) is to create a base class for all component pages to inherit from and override the OnInit method to do the checks and redirects.一个解决方案(目前,我认为不是最好的?)是为所有组件页面创建一个基类,以继承和覆盖 OnInit 方法来执行检查和重定向。 This also works when navigating to a link after the application has loaded.在应用程序加载后导航到链接时,这也适用。

A check in the app.cshtml component only works for the initial startup, not when navigating within the application. app.cshtml 组件中的检查仅适用于初始启动,而不适用于在应用程序中导航时。 This would be nice for other checks, but not to protect routes.这对其他检查很好,但不能保护路由。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM