Как внедрить сервис (AuthenticationStateProvider) в класс Blazor - PullRequest
2 голосов
/ 14 января 2020

Я пытаюсь внедрить службу (AuthenticationStateProvider) в класс на сервере Blazor. Если я сделаю это в бритвенном компоненте, это будет довольно просто:

@inject AuthenticationStateProvider AuthenticationStateProvider

, а затем

private async Task LogUsername()
{
    var authState = await AuthenticationStateProvider.GetAuthenticationStateAsync();
    var user = authState.User;

    if (user.Identity.IsAuthenticated)
    {
       ClientMachineName = $"{user.Identity.Name}";
    }
    else
    {
       ClientMachineName = "Unknown";
    }
} 

Однако мне нужно это сделать, т.е. получить имя компьютера пользователя, прошедшего проверку подлинности, в классе вместо компонента бритвы.

Я пытался, например:

[Inject]
AuthenticationStateProvider AuthenticationStateProvider { get; set; }

public async Task LogUsername()
{        
    var authState = await AuthenticationStateProvider.GetAuthenticationStateAsync();
    var user = authState.User;

    if (user.Identity.IsAuthenticated)
    {
        ClientMachineName = $"{user.Identity.Name}";
    }
    else
    {
        ClientMachineName = "Unknown";
    }
}

Но, похоже, это не работает.

Любая помощь будет высоко ценится.

Ответы [ 4 ]

1 голос
/ 14 января 2020

с сервером Blazor (. Net Core 3), это сработало для меня:

public class AuthTest
{
    private readonly AuthenticationStateProvider _authenticationStateProvider;

    public AuthTest(AuthenticationStateProvider authenticationStateProvider)
    {
        _authenticationStateProvider = authenticationStateProvider;
    }

    public async Task<IIdentity> GetIdentity()
    {
        var authState = await _authenticationStateProvider.GetAuthenticationStateAsync();
        var user = authState.User;
        return user.Identity;
    }
}

Вам необходимо зарегистрировать это с ASP. Net Core DI в Startup.ConfigureServices:

services.AddScoped<AuthTest>();

А затем внедрите его на свою страницу .razor:

@page "/AuthTest"
@inject AuthTest authTest;
<button @onclick="@LogUsername">Write user info to console</button>

@code{
    private async Task LogUsername()
    {
        var identity= await authTest.IsAuthenticated();
        Console.WriteLine(identity.Name);
    }

Вы должны увидеть имя пользователя, вошедшего в систему, записанное в выходную консоль ASP. Net.

Обновление Если вы хотите получить пользователя, вошедшего в систему в данный момент, из отдельного класса, и вы не внедряете это на страницу блейзора, тогда, похоже, вам просто нужно внедрить IHttpContextAccessor в этот класс (как видно здесь )

Так, например, если вы хотите иметь обычный API или контроллер MVC в приложении Blazor, вы должны сделать это.

например

public class UserService
{
    private readonly IHttpContextAccessor _httpContextAccessor;

    public UserService(IHttpContextAccessor httpContextAccessor)
    {
        _httpContextAccessor = httpContextAccessor;
    }

    public void GetUsername()
    {
        var username = _httpContextAccessor.HttpContext.User.Identity.Name;
        return username;
    }
}

и убедитесь, что вы зарегистрировали его в ConfigureServices:

services.AddHttpContextAccessor();
0 голосов
/ 12 апреля 2020

если вы в вашем startup.cs добавляете некоторые сервисы

services.AddScoped<TokenProvider>();
services.AddTransient<TokenRefreshService>();
services.Add<GraphServiceService>();

вы можете на странице бритвы вводить их по типу

@inject TokenProvider _token
@inject TokenRefreshService _tokenrefresh
@inject GraphServiceService _graphservice

Эти классы сервисов вы вводите в них через конструктор

public GraphServiceClass(AuthenticationStateProvider _AuthenticationStateProvider, TokenProvider _token)
{
    AuthenticationStateProvider = _AuthenticationStateProvider;
    token = _token;
}

Я рекомендую это: ASP. NET Внедрение зависимостей Core Blazor

0 голосов
/ 17 января 2020

Еще раз спасибо @StephenByrne и @Dan - я уже почти со своими требованиями. Это мой класс обслуживания пользователей, и он работает, как и ожидалось:

public class AuthUser
{

    private readonly AuthenticationStateProvider _authenticationStateProvider;

    public AuthUser(AuthenticationStateProvider authenticationStateProvider)
    {
        _authenticationStateProvider = authenticationStateProvider;
        var username = _authenticationStateProvider.GetAuthenticationStateAsync().Result;
        FetchMyUser(username.User.Identity.Name);
    }

    public User MyUser { get; set; }

    public void FetchMyUser(string machineName = "Unknown")
    {
        using (IDbConnection connection = new System.Data.SqlClient.SqlConnection(SettingsService.DBConnectionString2016))
        {
            MyUser = connection.QueryFirstOrDefault<User>($"SELECT FirstName FROM MyTable WHERE MachineName = '{machineName}' ;");
        }
    }
}

А затем в Startup.cs я добавляю этот сервис как Scoped (это важно, как Дэн указал ниже);

services.AddScoped<AuthUser>();

Затем я могу использовать эту службу из компонента .razor следующим образом:

@inject AuthUser authUser

Hello @authUser.MyUser.FirstName

Единственная оставшаяся проблема - я не знаю, как использовать эту службу в другом классе .cs , Я считаю, что я не должен просто создавать объект этого класса (которому я должен был бы передать параметр authenticationStateProvider) - это не имеет особого смысла. Любая идея, как я мог бы достичь того же, что я упоминал в файле .razor, но вместо этого в классе .cs?

Спасибо!

0 голосов
/ 15 января 2020

Ознакомьтесь с решением, которое у меня было для этой проблемы, здесь:

Доступ к аутентифицированному пользователю вне представления в Blazor

Это должно решить вашу проблему.

Редактировать: Если вы хотите получить информацию о состоянии аутентификации, вам нужно создать заявку на состояние аутентификации с именем пользователя или любой другой информацией, которая вам требуется, вместо создания класса и назначения имя к этому. Таким образом, в классах, которым нужна эта информация, вы можете просто внедрить класс обслуживания, который получает все утверждения о текущем состоянии аутентификации. Это действительно все должно быть сделано в пользовательском провайдере состояния аутентификации.

Пример:

public override async Task<AuthenticationState> GetAuthenticationStateAsync()
{
    MyUser = //DB call to get user information
    var claimsIdentity = new ClaimsIdentity(new[] { new 
    Claim(ClaimTypes.Name, MyUser.Name) }, "Authenticated");
    var user = new ClaimsPrincipal(identity);
    return new AuthenticationState(user);
}

Затем в другом сервисе вы получите утверждения с информацией о пользователе и добавите их в любой другие услуги / класс информация необходима.

public ApplicationUser(AuthenticationStateProvider authenticationStateProvider)
{
    _authenticationStateProvider = authenticationStateProvider;
}

public async Task<string> GetLogin()
{
    var authState = await _authenticationStateProvider.GetAuthenticationStateAsync();
    return authState.User.Claims.Where(c => c.Type == ClaimTypes.Name).FirstOrDefault().Value;
}
...