如何从blazor(服务器端)Web应用程序获取访问令牌?

问题描述:

实现openidconnect之后,blazor会将访问令牌存储在哪里?如何找回它?

After implementing openidconnect, where does blazor store the access token? how to retrieve it?

如何添加通过IdentityServer4将OpenIdConnect连接到ASP.NET Core ServerSide Blazor Web应用程序?

https://docs.microsoft.com/zh-cn/aspnet/core/security/blazor/?view=aspnetcore-3.1&tabs=visual-studio #customize-unauthorized-content-with-router-component

以下代码段提供了一种方法,该方法可检索在使用IdentityServer4提供程序对用户进行身份验证时发出的访问令牌.为了得到 访问令牌可以使用HttpContext对象,但是由于Blazor是基于SignalR的,因此与应用程序的连接是HTTP连接而不是WebSocket连接时,只有在HttpContext对象可用时,您才必须这样做.

The following code snippets provide a way to retrieve the access token issued when a user is authenticated with IdentityServer4 provider. In order to get the access token you can use the HttpContext object, but since Blazor is SignalR-based, you'll have to do it the only time the HttpContext object is available, when the connection to your application is an HTTP connection, and not a WebSocket connection.

检索访问令牌后,您需要将其传递到Blazor应用程序,并将其存储在本地存储中.我的代码还提供了一种在必要时解析访问令牌的方法.

After retrieving the access token, you need to pass it to your Blazor app, and store it in a local storage. My code also provide a way to parse the access token, if necessary.

  • 将文件添加到Pages文件夹并将其命名为_Host.cshtml.cs

  • Add a file to the Pages folder and name it _Host.cshtml.cs

将此代码添加到文件中:

Add this code to the file:

 public class HostAuthenticationModel : PageModel
 {
     public async Task<IActionResult> OnGet()
     {
         if (User.Identity.IsAuthenticated)
         {
            var token = await HttpContext.GetTokenAsync("access_token");
            AccessToken = token;

         }
    return Page();
 }

 public string AccessToken { get; set; }
 }

注意:我已将PageModel类命名为:HostAuthenticationModel 您将需要其中一些: using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.RazorPages; using System; using System.Linq; using System.Threading.Tasks;

Note: I've name the the PageModel class: HostAuthenticationModel You'll need some of these: using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.RazorPages; using System; using System.Linq; using System.Threading.Tasks;

  • 接下来,我们必须将AccessToken属性中存储的值传递给Blazor App:

在_Host.cshtml文件中,在文件的顶部添加模型指令:

In the _Host.cshtml file add the model directive at the top portion of the file:

@model HostAuthenticationModel

像这样向组件Tag Helper添加新属性:

Add a new attribute to the component Tag Helper like this:

param-AccessToken="Model.AccessToken"

最终结果:

 <app>
        <component type="typeof(App)" render-mode="ServerPrerendered" 
                 param-AccessToken="Model.AccessToken"/>
 </app>

param-AccessToken属性要求您在 App组件中定义一个名为 AccessToken 的属性,该属性将从页面模型中获取访问令牌.

The param-AccessToken attribute requires you to define a property named AccessToken in the App component which will get the access token from the page model.

  • 接下来定义将接收访问令牌的属性
  • ,然后重写OnAfterRenderAsync方法,从中调用方法 将访问令牌存储在本地存储中.

  • Next define the property which will receive the access token
  • And then override the OnAfterRenderAsync method from which we call a method to store the access token in the local storage.

@code{
   [Parameter]
   public string AccessToken { get; set; }

   protected override async Task OnAfterRenderAsync(bool firstRender)
   {
       if (firstRender)
        {
            await tokenStorage.SetTokenAsync(AccessToken);
        }
   }
 }

还将以下内容放在App组件的顶部:

Also place the following at the top of the App component:

@inject AccessTokenStorage tokenStorage

  • 接下来,您必须像这样创建AccessTokenStorage服务:

    • Next you'll have to create the AccessTokenStorage service like this:

      在应用的根目录中创建一个名为 AccessTokenStorage 的类,然后添加 以下代码:

      Create a class named AccessTokenStorage at the root of your app, and add the following code:

      公共类AccessTokenStorage { 私有只读IJSRuntime _jsRuntime;

      public class AccessTokenStorage { private readonly IJSRuntime _jsRuntime;

      public AccessTokenStorage(IJSRuntime jsRuntime)
      {
          _jsRuntime = jsRuntime;
      }
      
      public async Task<string> GetTokenAsync()
          => await _jsRuntime.InvokeAsync<string>("localStorage.getItem", "accessToken");
      
      public async Task SetTokenAsync(string token)
      {
          if (token == null)
          {
              await _jsRuntime.InvokeAsync<object>("localStorage.removeItem", 
                                                              "accessToken");
          }
          else
          {
              await _jsRuntime.InvokeAsync<object>("localStorage.setItem", 
                                                     "accessToken", token);
          }
      
      
       }
      }
      

    • 我想这里不需要解释...这可能是您可能需要的一些使用指令 using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using System.Security.Claims; using Microsoft.AspNetCore.Components.Authorization; using Microsoft.JSInterop;

      I guess no explanation is needed here... Here's some using directives you may need using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using System.Security.Claims; using Microsoft.AspNetCore.Components.Authorization; using Microsoft.JSInterop;

      将以下内容添加到Startup.ConfigureServices

      Add the following to the Startup.ConfigureServices

      services.AddHttpClient(); services.AddScoped<AccessTokenStorage>();

      services.AddHttpClient(); services.AddScoped<AccessTokenStorage>();

      注意:以上代码应与我提供的代码一起使用

      Note: the above code should be used with the code I provide in my answer here