【问题标题】:Blazor Windows Auth get User Name Server Side - 405 errorBlazor Windows Auth 获取用户名服务器端 - 405 错误
【发布时间】:2022-01-26 00:41:21
【问题描述】:

我有一个新的 Blazor 服务器应用程序 - 使用默认 VS2019 模板(计数器应用程序示例)。我已在应用程序上启用 Windows 身份验证。当应用程序加载到我的服务器上时,它会在屏幕右上角显示域/用户名,这很棒。我想在我的 c# 代码 sop 中获取用户名,我可以围绕这个构建逻辑,例如,如果用户是 X do Y。

所以我将这个添加到我的启动文件中 services.AddSingleton();

并尝试通过以下方式访问用户名: 字符串用户名 = _httpContextAccessor.HttpContext.User.Identity.Name;

但是,我不断收到 405 错误。请参阅随附的代码、错误和设置屏幕截图

任何帮助将不胜感激

TIA

Screen Shot

【问题讨论】:

    标签: blazor


    【解决方案1】:

    您无法在 Blazor Server App 中访问 HttpContext 对象,因为使用的协议是 SignalR,但始终为 HTTP 的初始请求除外,在这种情况下,您可以获取 HttpContext 对象(在 Blazor App 实例化之前) ,提取值,并将它们传递给您的 Blazor 应用程序。见this 回答怎么做...

    但是,您可以将 AuthenticationStateProvider 服务注入到您的组件中,并访问声明的 ClaimsPrincipal(神奇地从 WindowsPrincipal 转换而来)对象,如下面的代码所示。

    复制、运行和测试...

    @page "/"
    
    @using System.Security.Claims;
    
    <div>@output</div>
    
    @if (claims.Count() > 0)
    {
        <table class="table">
            @foreach (var claim in claims)
            {
                <tr>
                    <td>@claim.Type</td>
                    <td>@claim.Value</td>
                </tr>
            }
        </table>
    }
    
    @code{
    
    
        private string output;
        private IList<Claim> claims;
        [Inject] AuthenticationStateProvider AuthenticationStateProvider { get; set; }
    
        protected override async Task OnInitializedAsync()
        {
    
            var authState = await AuthenticationStateProvider.GetAuthenticationStateAsync();
            var user = authState.User;
    
            if (user.Identity.IsAuthenticated)
            {
                output = $"{user.Identity.Name} is authenticated.";
                claims = user.Claims.ToList();
    
            }
            else
            {
                output = "The user is not authenticated.";
            }
        }
    }
    

    更新:

    实际上,有三种方法可以做到这一点。不推荐使用上面的第一个,因为 AuthenticationState 在被访问后永远不会更新。您需要刷新页面才能访问它的新实例。

    第二种方法是将AuthenticationState的一个Task级联到你的组件中,等待Task,然后访问AuthenticationState。您可以这样做:

    @page "/"
    
    @code {
        [CascadingParameter]
        private Task<AuthenticationState> authenticationStateTask { get; 
                                                                 set; }
        private string UserName {get; set;}
    
       protected async override Task OnInitializedAsync()
        {
            // Await Task<AuthenticationState> 
            // and then retrieve the ClaimsPrincipal
            var user = (await authenticationStateTask).User;
    
            if (user.Identity.IsAuthenticated)
             {
                    // Assign the user name to the 
                    UserName = user.Identity.Name;
             }
        } 
    }
    

    请注意,Task&lt;AuthenticationState&gt;CascadingAuthenticationState 组件级联,位于 App 组件 (App.razor) 中。 CascadingAuthenticationState 组件 包含在新更改的 AuthenticationState 更改时向下流式传输的代码。

    第三种方式是创建一个类服务如下:

    public class UsertService
    {
        private readonly AuthenticationStateProvider authProvider;
       
        public UserService (AuthenticationStateProvider authProvider)
        {
            this.authProvider = authProvider;
        }
    
        public async Task<string> GetUserName()
        {
            var authenticationStateTask = await 
                       authProvider.GetAuthenticationStateAsync();
                     
            var user = authenticationStateTask.User;
            
            if (user.Identity.IsAuthenticated)
            {
                // Executed only when the user is authenticated
                return user.Identity.Name;
            }
    
            return "User not authenticated";
        }
    }
    

    请注意,您可以扩展该类以提供其他值等。

    现在您必须在 Startup 类中将此服务添加为 Scoped,如下所示:

    public void ConfigureServices(IServiceCollection services)
    {
      // Code removed...
         services.AddScoped<UserService>();
    
    }
    

    这就是您在组件中使用它的方式:

    @page "/"
    @inject UserService UserService
    
    
    <div>Your user name: @name</div>
    
    
    @code
    {
        private string name;
    
        protected override async Task OnInitializedAsync()
        {
            name = await UserService.GetUserName();
        }
       
    }
    

    注意:如果您需要更多帮助,可以通过我的电子邮件与我联系。在个人资料中查看...

    【讨论】:

    • 嗨谢谢你,你是明星!它真的很有帮助无论如何我可以将它包装到一个类文件中。所以我只调用一种方法,它将 user.Identity.Name 作为字符串返回。因为我可能需要在我的应用程序的各个组件中检查用户是谁
    • 您可以通过多种方式做到这一点,例如,您可以定义一个类服务,将 AuthenticationStateProvider 服务注入其中,并公开一个名为 UserName 的属性。请您为我的回答点赞:点击位于 0 字符上方的上图。
    • 我不认为你有一个如何创建这样一个类的例子......我是 Blazor 的新手,我不断收到错误。我试着按照这个例子做,但不高兴:stackoverflow.com/questions/59736931/… 当然,我点击了向上箭头,我没有意识到我需要这样做——我的错。非常感谢您的帮助
    • I have clicked the Up arrow 不,你没有。答案的左侧是一个向上的图像,其下方是字符串0,然后是向下的图像,其下方是绿色标记的图像,表示该答案已被接受。当您单击向上的图像时,您会投票赞成答案,除了接受它...您还需要看到字符串 0 更改为 1 .... 我将为您创建课程需要并将其添加到我的答案的末尾。
    • 嗨,我刚刚又试了一次,这次仍然是 1 号。非常感谢您在这方面的帮助 - 这太棒了。祝你圣诞快乐,新年快乐
    猜你喜欢
    • 2019-03-26
    • 1970-01-01
    • 2020-08-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-09
    • 2020-05-14
    • 2021-07-12
    相关资源
    最近更新 更多