实施openidconnect之后,blazor会将访问令牌存储在哪里?如何找回它?
How to add OpenIdConnect via IdentityServer4 to ASP.NET Core ServerSide Blazor web app?
答案 0 :(得分:8)
以下代码段提供了一种方法,该方法可以检索在使用IdentityServer4提供程序对用户进行身份验证时发出的访问令牌。为了得到 访问令牌可以使用HttpContext对象,但是由于Blazor是基于SignalR的,因此与应用程序的连接是HTTP连接而不是WebSocket连接时,只有在HttpContext对象可用时,您才必须这样做。
检索访问令牌后,您需要将其传递给Blazor应用程序,并将其存储在本地存储中。我的代码还提供了一种在必要时解析访问令牌的方法。
将文件添加到Pages文件夹并将其命名为_Host.cshtml.cs
将此代码添加到文件:
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;
在_Host.cshtml文件中,在文件的顶部添加模型指令:
@model HostAuthenticationModel
像这样向组件Tag Helper添加新属性:
param-AccessToken="Model.AccessToken"
最终结果:
<app>
<component type="typeof(App)" render-mode="ServerPrerendered"
param-AccessToken="Model.AccessToken"/>
</app>
param-AccessToken
属性要求您在 App组件中定义一个名为 AccessToken 的属性,该属性将从页面模型获取访问令牌。
,然后重写OnAfterRenderAsync方法,从中调用方法 将访问令牌存储在本地存储中。
@code{
[Parameter]
public string AccessToken { get; set; }
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
await tokenStorage.SetTokenAsync(AccessToken);
}
}
}
还将以下内容放在App组件的顶部:
@inject AccessTokenStorage tokenStorage
接下来,您必须像这样创建AccessTokenStorage服务:
在应用的根目录中创建一个名为 AccessTokenStorage 的类,然后添加 以下代码:
公共类AccessTokenStorage { 私有只读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;
将以下内容添加到Startup.ConfigureServices
services.AddHttpClient();
services.AddScoped<AccessTokenStorage>();
注意:以上代码应与我提供的代码in my answer here
一起使用答案 1 :(得分:1)
我通过添加以下链接中列出的代码解决了这个问题。
注意:上面链接中列出的步骤可以正常工作,但是,我做了一些小的修改,这些修改对我来说更有意义。我还修改了对我来说更有意义的顺序。
步骤:
1。创建TokenProvider类
public class TokenProvider
{
public string AccessToken { get; set; }
}
2。使用以下命令更新_Host.cshtml文件:
@using Microsoft.AspNetCore.Authentication
@{
var accessToken = await HttpContext.GetTokenAsync("access_token");
}
<body>
<app>
<component type="typeof(App)" param-AccessToken="accessToken" render-mode="ServerPrerendered" />
</app>
3。使用DI更新StartUp.cs:
public void ConfigureServices(IServiceCollection services)
{
services.AddRazorPages();
services.AddScoped<TokenProvider>();
4。使用以下命令更新App.razor:
@inject TokenProvider TokenProvider
@code
{
[Parameter]
public string AccessToken { get; set; }
protected override void OnInitialized()
{
//Accept the parameter from _Host.cshtml and move into the Token Provider
TokenProvider.AccessToken = AccessToken;
base.OnInitialized();
}
}
5。必要时,获取AccessToken
注意: _tokenProvider是使用构造函数DI创建的
var accessToken = _tokenProvider.AccessToken;
if (accessToken != null)
{
_httpClient.DefaultRequestHeaders.Add("Authorization", "Bearer " + accessToken);
}
希望上述步骤对其他人有帮助。