很难理解正在发生的事情,我确实需要一些想法和投入。拜托,我不太擅长用文字描述问题所在,所以请温柔一点。
我有一个 Blazor wasm 前端和一个 Azure Function 后端。
我进行了标准的、没什么特别的 Azure AD 登录。
稍后在代码中,我使用不记名令牌与 AzFunction 连接,并且它有效。 AzFunction 评估令牌并识别用户以进行进一步处理。我应该提到 AzFunction 连接到 Graph 和其他 API。
所以一切都很好并且工作正常,这是我的问题。
我想在登录时连接到 AzFuntion,以获取一些用户配置文件信息。为了调试,我只做了一个按钮,一切正常。
然后,我将“按钮代码”移至 Authenticator.razor 中由 RemoteAuthenticatorView OnLogInSucceeded 调用的方法。
<RemoteAuthenticatorView Action="@Action" LogInFailed="LogInFailedFragment" OnLogInSucceeded="LoginComplete" />
这是我的问题:使用 OnLogInSucceeded 我获得了 2 个必须响应的 Azure AD 登录信息。第一个之后,直接进入第二个。这一切都只是因为我将代码从按钮移至 OnLogInSucceeded。当我调试时,我清楚地看到令牌在连接到 AzFunction 之前就存在。
另外,当我在 Visual Studio 中从 OnLogInSucceeded 调用的 LoginComplete 函数中设置断点并保持几秒钟时,它只需一个登录对话框即可完成登录过程。
谁能帮我理解为什么?
有什么更好的指示可以输入“获取用户个人资料”代码吗?我需要的是要运行的代码,因此当登录完成后,只需一次登录即可检索用户配置文件信息。
Edit:
该代码似乎有更好的解决方案,但是我仍然不明白是什么导致第二次登录出现......这就是我的问题的主要原因。
多亏了 Raymond,我也得到了一个很好的指导,并制作了一个组件来加载此类数据。我必须在组件初始化时将事件和加载结合起来。我仍然觉得 M$ 应该而且可能会找到更好的方法来做到这一点。
对于此应用程序,我使用 Azure B2C 进行身份验证,并且使用重定向而不是弹出窗口。当我初始化用户状态时,我调用 api 来获取用户配置文件,或者如果是新用户则创建一个。
初始 DataLoader.razor
@implements IDisposable
@inject NavigationManager _navigationManager
@inject UserState _userState
@inject AuthenticationStateProvider _authenticationStateProvider
@ChildContent
@code {
[Parameter]
public RenderFragment ChildContent { get; set; }
// The event can trigger multiple times when being redirected from the Authentication page to wherever you're going.
// So we use this to check.
public bool hasRunInit;
protected override async Task OnInitializedAsync()
{
Console.WriteLine(DateTime.Now.ToString("hh:mm:ss:fff") + " InitialDataLoader -> OnInitializedAsync -> " + _navigationManager.Uri);
// This component is already loaded and initialized on the Authentication page, so we have to subscribe to this event to
// check when the user bounces back from Azure B2C and gets logged in. In that case, we do the initial load in on the event
_authenticationStateProvider.AuthenticationStateChanged += this.OnAuthenticationStateChanged;
// If the user is authenticated and reloads the page in the browser, the event won't trigger so we can do the initial load here.
var user = (await _authenticationStateProvider.GetAuthenticationStateAsync()).User;
Console.WriteLine(DateTime.Now.ToString("hh:mm:ss:fff") + " InitialDataLoader -> OnInitializedAsync -> IsUserAuthenticated: " + user.Identity.IsAuthenticated);
Console.WriteLine(DateTime.Now.ToString("hh:mm:ss:fff") + " InitialDataLoader -> OnInitializedAsync -> IsStateInitialized: " + _userState.IsInitialized);
if (user.Identity.IsAuthenticated && !_userState.IsInitialized)
{
hasRunInit = true;
Console.WriteLine(DateTime.Now.ToString("hh:mm:ss:fff") + " InitialDataLoader -> OnInitializedAsync -> InitUser");
await _userState.InitializeAsync(this);
}
}
void IDisposable.Dispose()
{
_authenticationStateProvider.AuthenticationStateChanged -= this.OnAuthenticationStateChanged;
}
private async void OnAuthenticationStateChanged(Task<AuthenticationState> task)
{
Console.WriteLine(DateTime.Now.ToString("hh:mm:ss:fff") + " InitialDataLoader -> OnAuthenticationStateChanged -> " + _navigationManager.Uri);
var user = (await task).User;
Console.WriteLine(DateTime.Now.ToString("hh:mm:ss:fff") + " InitialDataLoader -> OnAuthenticationStateChanged -> IsUserAuthenticated: " + user.Identity.IsAuthenticated);
Console.WriteLine(DateTime.Now.ToString("hh:mm:ss:fff") + " InitialDataLoader -> OnAuthenticationStateChanged -> IsStateInitialized: " + _userState.IsInitialized);
if (user.Identity.IsAuthenticated && !_userState.IsInitialized)
{
if (!hasRunInit)
{
hasRunInit = true;
Console.WriteLine(DateTime.Now.ToString("hh:mm:ss:fff") + " CascadingAppStateProvider -> OnInitializedAsync -> InitUser");
await _userState.InitializeAsync(this);
}
else
{
Console.WriteLine(DateTime.Now.ToString("hh:mm:ss:fff") + " InitialDataLoader -> OnInitializedAsync -> Init has already been triggered!");
}
}
}
}
应用剃刀
<CascadingAuthenticationState>
<InitialDataLoader>
<Router AppAssembly="@typeof(Program).Assembly">
<Found Context="routeData">
<AuthorizeRouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)">
<Authorizing>
------------- Authorizing.. ------------------
</Authorizing>
<NotAuthorized>
@if (!context.User.Identity.IsAuthenticated)
{
<RedirectToLogin />
}
else
{
<p>You are not authorized to access this resource.</p>
}
</NotAuthorized>
</AuthorizeRouteView>
</Found>
<NotFound>
<LayoutView Layout="@typeof(MainLayout)">
<p>Sorry, there's nothing at this address.</p>
</LayoutView>
</NotFound>
</Router>
</InitialDataLoader>
</CascadingAuthenticationState>
当用户从网关返回时,该组件会在应用程序对用户进行身份验证之前进行初始化。然后该事件触发两次,一次针对身份验证页面,一次针对您正在查看的任何页面。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)