в нашем приложении я бы хотел использовать управление пользователями нашего толстого клиента. Для этого я написал собственный AuthenticationStateProvider:
public class MyAuthenticationStateProvider : ServerAuthenticationStateProvider, IAuthentorizationService, IDisposable
{
public MyAuthenticationStateProvider (IPermissionManager permissionManager)
{
//User management service of the fat client
_permissionManager = permissionManager;
}
public override Task<AuthenticationState> GetAuthenticationStateAsync()
{
if (_permissionManager.PermissionUser == null)
{
var emptyUser = new ClaimsPrincipal(new ClaimsIdentity(new Claim[0]));
return Task.FromResult(new AuthenticationState(emptyUser));
}
var identity = new ClaimsIdentity(new[]
{
new Claim(ClaimTypes.Name, _permissionManager.PermissionUser.User.GetName())
}, "FatClientAuthentication");
var user = new ClaimsPrincipal(identity);
return Task.FromResult(new AuthenticationState(user));
}
public async Task<bool> LoginUser(string userName, string password)
{
//Login via WCF connection
var response = await _clientProxy.Login(new LoginRequest
{
LoginUserName = userName,
Password = password
});
response.LogExceptionIfFaulted(_logger);
if (response.Ok)
{
_permissionManager.Initialize(response.LoggedInUser);
NotifyAuthenticationStateChanged(GetAuthenticationStateAsync());
}
return response.Ok;
}
Логин работает нормально. В целях тестирования я всегда захожу с фиксированными учетными данными пользователя. После успешного входа в систему я запускаю событие NotifyAuthenticationStateChanged, которое приводит к правильному вызову метода GetAuthenticationStateAsyn c. Теперь вошедший в систему пользователь правильно обернут внутри AuthenticationState. При отладке кода я вижу, что Identity with name name является правильным пользователем, а свойство IsAuthenticated имеет значение true.
Однако при использовании компонента AuthorizeView я всегда получаю «пустого пользователя» ( без имени, без имени пользователя, IsAuthenticated имеет значение false)
Теперь у меня есть небольшой компонент только для тестирования:
<AuthorizeView>
<Authorized>
<h2>User @context.User.Identity.Name</h2> is logged in!
Claims:
<ul>
@foreach (var claim in context.User.Claims)
{
<li>Type=@claim.Type; Value=@claim.Value</li>
}
</ul>
@context.User.Claims
<p>Current count: @currentCount</p>
<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
</Authorized>
<NotAuthorized>
<h2>User @context.User.Identity.Name</h2> @*this is an empty string*@
<h2>Authentication Type: @context.User.Identity.AuthenticationType</h2> @*empty*@
<h2>Authenticated: @context.User.Identity.IsAuthenticated</h2>@*false*@
No user is logged in!
</NotAuthorized>
Я использую AuthorizeRouteView и CascadingAuthenticationState в App.razor, как в официальном примере, отображаемом в https://docs.microsoft.com/en-us/aspnet/core/security/blazor/?view=aspnetcore-3.1
Доступ к AuthenticationState через CascadingParameter также приводит к тому же «пустому пользователю».
Оценить любая помощь,
tilt32
EDIT 1
Поэтому я снова посмотрел на поведение при входе, убедившись, что событие называется. Затем я выяснил, что мое событие AuthenticationStateChanged не имеет подписчиков (равно нулю). У меня сложилось впечатление, что что-то в рамках прикрепляется к этому событию при запуске. Может быть, я забыл какой-то вызов метода конфигурации при запуске? Вот что я делаю в сервисах настройки:
services.AddScoped<AuthenticationStateProvider, MyAuthenticationStateProvider>();
services.AddScoped<ServerAuthenticationStateProvider, MyAuthenticationStateProvider>();
//Interface which I use in my LoginCompontent and at Startup to log in with the default user or some real user credentials
services.AddScoped<IAuthenticationService, MyAuthenticationStateProvider>();
Я также попробовал подход, предложенный пользователем enet. К сожалению, безуспешно, результат был тот же. Во время входа в систему выполняется вызов NotifyAuthenticationStateChanged и, следовательно, события без подписчиков.
Служба WCF, которую мы используем в фоновом режиме, требует зарегистрированного пользователя. Следовательно, я сделал гостя с ограниченными правами для решения этой проблемы. Таким образом, приложение входит в GetAuthenticationStateAsyn c и пытается запустить AuthenticationStateEvent непосредственно после запуска (во время экрана загрузки).
EDIT 2
Итак, я попробовал некоторые дополнительные этапы установки, из которых Microsoft написала в документации Blazor, что они не должны быть необходимы для сервера Blazor:
ConfigureServices теперь выглядит следующим образом
//Authentication & Authorization setup
services.AddOptions();
services.AddAuthenticationCore();
services.AddAuthorizationCore();
services.AddScoped<IPermissionManager, SingleUserPermissionManager>();
services.AddScoped<AuthenticationStateProvider, MyAuthenticationStateProvider>();
services.AddScoped<ServerAuthenticationStateProvider, MyAuthenticationStateProvider>();
services.AddScoped<IAuthenticationService, MyAuthenticationStateProvider>();
В методе Configure (приложение IApplicationBuilder, IWebHostEnvironment env) я добавил следующие вызовы:
app.UseAuthentication();
app.UseAuthorization();
Это также не имело никакого эффекта.