Blazor项目中的自定义AuthenticationStateProvider在服务器端不起作用 [英] Custom AuthenticationStateProvider in blazor project doesn't work on server side

查看:31
本文介绍了Blazor项目中的自定义AuthenticationStateProvider在服务器端不起作用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

大家好! 我正试着在Blazor WebAssembly App中设置我的自定义身份验证模式(这是Studio创建3个项目的地方--客户端、服务器、共享)。我的想法是避免IS4身份验证,让我的OUN&Quot;内部用户用于测试目的,同时了解身份验证机制的工作。我是通过创建我的自定义AuthenticationStateProvider来做到这一点的吗?如official docs所示。这是我的AuthenticationStateProvider类:

public class CustomAuthStateProvider : AuthenticationStateProvider
{
    private bool _isLoggedIn = true;

    //this is a parameter defininng whether user logged in or not
    //changed by reflection
    public bool IsLoggedIn
    {
        get
        {
            return _isLoggedIn;
        }
        set
        {
            _isLoggedIn = value;
            NotifyAuthenticationStateChanged(GetAuthenticationStateAsync());
        }
    }
    private static CustomAuthStateProvider _myInstance = null;



    public Serilog.ILogger _logger { get; set; }

    public override Task<AuthenticationState> GetAuthenticationStateAsync()
    {
        ClaimsIdentity identity;

        Task<AuthenticationState> rez;

     if (IsLoggedIn)
        {
            identity = new ClaimsIdentity(new[]
            {
            new Claim(ClaimTypes.Name, "User01"),
            }, "Fake authentication type");
        }
        else
        {
            identity = new ClaimsIdentity();
        }
        var user = new ClaimsPrincipal(identity);

        rez = Task.FromResult(new AuthenticationState(user));

        return rez;

    }

    public static CustomAuthStateProvider GetMyInstance(Serilog.ILogger logger = null, string mySide = "")
    {
        //implementing singleton
        if (_myInstance == null)
        {
            _myInstance = new CustomAuthStateProvider();
            _myInstance._logger = logger;
        }
        return _myInstance;
    }
}

这就是我在客户端(Program.cs)插入它的方式

builder.Services.AddSingleton<AuthenticationStateProvider>(x => CustomAuthStateProvider.GetMyInstance(Log.Logger, "Client"));

这就是我在服务器端插入它的方式(startup.cs)

services.AddSingleton<AuthenticationStateProvider, CustomAuthStateProvider>();

问题: 它在客户端运行良好,这意味着我可以登录、注销和使用AutorizeView和类似的标签。但它在服务器端不起作用,这意味着HttpContext.User看不到任何经过身份验证的用户,我不能使用[Authorize]和类似的属性。我做错了什么?HttpContext.User如何连接到ASP.NET核心项目中的AuthenticationStateProvider? 谢谢;-)

推荐答案

这是我最近为服务器端项目散列的一个非常简单的测试身份验证状态提供程序。

using Microsoft.AspNetCore.Components.Authorization;
using System.Security.Claims;
using System.Threading.Tasks;

namespace Blazor.Auth.Test
{
    public class TestAuthenticationStateProvider : AuthenticationStateProvider
    {

        public TestUserType UserType { get; private set; } = TestUserType.None;

        private ClaimsPrincipal Admin
        {
            get
            {
                var identity = new ClaimsIdentity(new[]
                {
                    new Claim(ClaimTypes.Sid, "985fdabb-5e4e-4637-b53a-d331a3158680"),
                    new Claim(ClaimTypes.Name, "Administrator"),
                    new Claim(ClaimTypes.Role, "Admin")
                }, "Test authentication type");
                return new ClaimsPrincipal(identity);
            }
        }

        private ClaimsPrincipal User
        {
            get
            {
                var identity = new ClaimsIdentity(new[]
                {
                    new Claim(ClaimTypes.Sid, "024672e0-250a-46fc-bd35-1902974cf9e1"),
                    new Claim(ClaimTypes.Name, "Normal User"),
                    new Claim(ClaimTypes.Role, "User")
                }, "Test authentication type");
                return new ClaimsPrincipal(identity);
            }
        }

        private ClaimsPrincipal Visitor
        {
            get
            {
                var identity = new ClaimsIdentity(new[]
                {
                    new Claim(ClaimTypes.Sid, "3ef75379-69d6-4f8b-ab5f-857c32775571"),
                    new Claim(ClaimTypes.Name, "Visitor"),
                    new Claim(ClaimTypes.Role, "Visitor")
                }, "Test authentication type");
                return new ClaimsPrincipal(identity);
            }
        }

        private ClaimsPrincipal Anonymous
        {
            get
            {
                var identity = new ClaimsIdentity(new[]
                {
                    new Claim(ClaimTypes.Sid, "0ade1e94-b50e-46cc-b5f1-319a96a6d92f"),
                    new Claim(ClaimTypes.Name, "Anonymous"),
                    new Claim(ClaimTypes.Role, "Anonymous")
                }, null);
                return new ClaimsPrincipal(identity);
            }
        }

        public override Task<AuthenticationState> GetAuthenticationStateAsync()
        {
            var task = this.UserType switch
            {
                TestUserType.Admin => Task.FromResult(new AuthenticationState(this.Admin)),
                TestUserType.User => Task.FromResult(new AuthenticationState(this.User)),
                TestUserType.None => Task.FromResult(new AuthenticationState(this.Anonymous)),
                _ => Task.FromResult(new AuthenticationState(this.Visitor))
            };
            return task;
        }

        public Task<AuthenticationState> ChangeUser(TestUserType userType)
        {
            this.UserType = userType;
            var task = this.GetAuthenticationStateAsync();
            this.NotifyAuthenticationStateChanged(task);
            return task;
        }
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace Blazor.Auth.Test
{
    public enum TestUserType
    {
        None,
        Visitor,
        User,
        Admin
    }
}

启动注册:

services.AddScoped<AuthenticationStateProvider, TestAuthenticationStateProvider>();

我添加到NavMenu以切换用户的简单组件。

<AuthorizeView>
    <Authorized>
        <div class="m-1 p-1 text-white">
            @user.Identity.Name
        </div>
    </Authorized>
    <NotAuthorized>
        <div class="m-1 p-1 text-white">
            Not Logged In
        </div>
    </NotAuthorized>
</AuthorizeView>
<div class="m-1 p-3">
    <select class="form-control" @onchange="ChangeUser">
        @foreach (var value in Enum.GetNames(typeof(TestUserType)))
        {
            <option value="@value">@value</option>
        }
    </select>
</div>

@code {

    [CascadingParameter] public Task<AuthenticationState> AuthTask { get; set; }

    [Inject] private AuthenticationStateProvider AuthState { get; set; }

    private System.Security.Claims.ClaimsPrincipal user;

    protected async override Task OnInitializedAsync()
    {
        var authState = await AuthTask;
        this.user = authState.User;
    }

    private async Task ChangeUser(ChangeEventArgs e)
    {
        var en = Enum.Parse<TestUserType>(e.Value.ToString());
        var authState = await ((TestAuthenticationStateProvider)AuthState).ChangeUser(en);
        this.user = authState.User;
    }
}

这篇关于Blazor项目中的自定义AuthenticationStateProvider在服务器端不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆