当前位置: 首页 > 知识库问答 >
问题:

。NET Core 3.1 Web API和Blazor服务器端JWT认证

丘智志
2023-03-14

我想了解,如何为Blazor服务器端应用程序设置JWT身份验证?

让我举一个例子:假设我们有一个。NET Core 3.1 Web API项目。该项目有自己的TokenContler实现,它为有效的用户/密码组合提供了JWT。所有其他控制器都需要每个请求都有这样的令牌。

用于验证身份验证的中间件配置如下:

// enabling JWT bearer scheme
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddJwtBearer(options => 
    {
        options.TokenValidationParameters = new TokenValidationParameters 
        {
            // TOKEN VALIDATION PARAMETERS
        };
    });

// applying default authentication policy
services.AddMvc(o => 
{
    o.EnableEndpointRouting = false;
    var policy = new AuthorizationPolicyBuilder()
        .RequireAuthenticatedUser()
        .Build();
    o.Filters.Add(new AuthorizeFilter(policy));
}).SetCompatibilityVersion(CompatibilityVersion.Version_3_0);

到目前为止,这工作得很好。

现在我想在这个项目中添加一个漂亮的Blazor服务器端用户界面,我只是不知道如何进行身份验证?

根据Microsoft文档,服务器端应用程序的身份验证应该在建立SignalR连接时进行:

Blazor服务器身份验证

Blazor服务器应用程序通过使用SignalR创建的实时连接运行。基于SignalR的应用程序中的身份验证在连接建立时处理。身份验证可以基于cookie或其他某种不记名令牌。

(来源:https://learn.microsoft.com/en-us/aspnet/core/security/blazor/?view=aspnetcore-3.1

不幸的是,我无法弄清楚这是如何工作的 - 我找到的教程和提示要么适用于客户端 Blazor 或使用 Cookie /标识......

有什么想法吗?

共有3个答案

袁炳
2023-03-14

看看微软的这个教程:https://learn . Microsoft . com/en-us/azure/active-directory/develop/tutorial-blazor-server

注意:此调用为您提供 jwt...检查它的内容复制粘贴到 https://jwt.ms/

var token = await TokenAcquisitionService.GetAccessTokenForUserAsync(new string[] { "User.Read", "Mail.Read" });
步德宇
2023-03-14

对于 Blazor 服务器,最佳选择是使用 ProtectedLocalStorage 和某种 AuthenticationStateProvider。看看我的回购。我希望它能帮助 https://github.com/DudnykOleksandr/template-blazor-jwt-authentication

public class BlazorAppLoginService
{
    private readonly string TokenKey = nameof(TokenKey);

    private readonly ProtectedLocalStorage localStorage;
    private readonly NavigationManager navigation;
    private readonly IUsersService usersService;
    private readonly IConfiguration configuration;

    public BlazorAppLoginService(ProtectedLocalStorage localStorage, NavigationManager navigation, IUsersService usersService, IConfiguration configuration)
    {
        this.localStorage = localStorage;
        this.navigation = navigation;
        this.usersService = usersService;
        this.configuration = configuration;
    }

    public async Task<bool> LoginAsync(string userName, string password)
    {
        var isSuccess = false;

        var token = await usersService.LoginAsync(userName, password);
        if (!string.IsNullOrEmpty(token))
        {
            isSuccess = true;
            await localStorage.SetAsync(TokenKey, token);
        }

        return isSuccess;
    }


    public async Task<List<Claim>> GetLoginInfoAsync()
    {
        var emptyResut = new List<Claim>();
        ProtectedBrowserStorageResult<string> token = default;
        try
        {
            token = await localStorage.GetAsync<string>(TokenKey);
        }
        catch (CryptographicException)
        {
            await LogoutAsync();
            return emptyResut;
        }

        if (token.Success && token.Value != default)
        {
            var claims = JwtTokenHelper.ValidateDecodeToken(token.Value, configuration);
            if (!claims.Any())
            {
                await LogoutAsync();
            }
            return claims;
        }
        return emptyResut;
    }

    public async Task LogoutAsync()
    {
        await RemoveAuthDataFromStorageAsync();
        navigation.NavigateTo("/", true);
    }


    private async Task RemoveAuthDataFromStorageAsync()
    {
        await localStorage.DeleteAsync(TokenKey);
    }
public class CustomBlazorAuthStateProvider : AuthenticationStateProvider
{
    private readonly BlazorAppLoginService blazorAppLoginService;

    public CustomBlazorAuthStateProvider(BlazorAppLoginService blazorAppLoginService)
    {
        this.blazorAppLoginService = blazorAppLoginService;
    }

    public override async Task<AuthenticationState> GetAuthenticationStateAsync()
    {
        var claims = await blazorAppLoginService.GetLoginInfoAsync();
        ClaimsIdentity claimsIdentity;
        if (claims.Any())
        {
            claimsIdentity = new ClaimsIdentity(claims, "Bearer");
        }
        else
        {
            claimsIdentity = new ClaimsIdentity();
        }
        var claimsPrincipal = new ClaimsPrincipal(claimsIdentity);
        return new AuthenticationState(claimsPrincipal);
    }
}
邵沛
2023-03-14

我使用身份验证设置了Blazor Server,然后为API添加了JWT身份验证。所以我认为反过来是一样的。

以下是我所做的:

配置服务方法(我认为顺序可能很重要,不确定):

services.AddDefaultIdentity<IdentityUser>()
    .AddRoles<IdentityRole>()
    .AddEntityFrameworkStores<ApplicationDbContext>();

// not sure if this line is required for Blazor auth
services.AddScoped<AuthenticationStateProvider, RevalidatingIdentityAuthenticationStateProvider<IdentityUser>>();

services.AddAuthentication()
    .AddCookie(cfg => cfg.SlidingExpiration = true)
    .AddJwtBearer(x =>
    {
        // options
    });
// SamplePage.razor.cs
[Route("page-path")]
[Authorize]
public partial class SamplePage
{ }

// or like this in SamplePage.razor
@page "page-path"
@attribute [Authorize]
[Route("api/[controller]")]
[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
public class SampleController : ControllerBase
{ }

我发现此页面中的内容对于在开始使用 Blazor 服务器端项目后使 JWT 正常工作非常有帮助。https://jasonwatmore.com/post/2019/10/11/aspnet-core-3-jwt-authentication-tutorial-with-example-api

 类似资料:
  • 到目前为止,我还没有找到使用Blazor服务器(不是WebAssembly)和API网关和微服务的指导。讨论这些Blazor以及API网关和微服务的文章总是提到Blazor WebAssembly(Wasm)。(是不是假设Blazor Server应用程序不会使用微服务?此外,值得一提的是,选择Blazor服务器而不是Blazor WebAssembly的原因是为了更好地保护知识产权。) 无论如何

  • 我试图实现jwt在cookie中的auth在一个单页应用程序的反应前端,它与运行Express的各种节点微服务通信。 我这样做,因为它似乎存储的jwt在sesionstore使应用程序容易受到XSS。 然而,通过使用cookie,API现在容易受到csrf攻击。 传统上,csrf攻击是通过创建csrf令牌,将其存储在服务器会话中,然后将其呈现在隐藏的表单字段中来减轻的。然后,在提交表单时,csrf

  • 是否可以从应用程序中创建JWT令牌,并使用GCP服务帐户在应用程序中验证它?我如何在Python中做到这一点? 这两个应用程序都部署在GCP中。应用程序可以部署在GCF、Cloud Run、AppEngine、GKE甚至GCE中。 我花了一些时间阅读Google Cloud文档,但我没有找到如何处理服务间身份验证的“通用”答案。(很可能是因为它们对每个GCP产品都不相同) 那么,考虑到我们抛开了谷

  • 我正在为我们的应用程序使用Spring boot Microservices体系结构。在我们的项目中,我们使用的是OAuth2、Jwt、Zuul和Eureka服务,我的疑问是,我是否需要将这些服务作为一个独立的服务来实现,或者我是否可以将所有服务开发成一个单一的应用程序。 如果我必须作为单个应用程序实现,那么更好的方法是什么。请澄清

  • 我将使用Laravel框架构建micrservices。我有用户微服务,它处理客户端凭证并验证它们(为客户端创建JWT)。此外,还有另一种需要用户认证的微服务。 问题是,如果秘密访问令牌密钥仅在用户微服务中,我如何验证客户端在微服务(用户微服务除外)中的访问令牌?或者,我应该在每个微服务中保留密钥吗?

  • 我目前正在运行一个Node.js应用程序,有一个应用程序接口和文件服务(我知道nginx可以处理它,但我一开始不应该使用它)。 我只是用它来做一个简单的基本认证,碰巧没那么简单。 这是我的nginx配置: 文件只是,很好。 使用此配置,当我转到我的IP时: 询问我用户和密码 开始加载页面 (有时)再次询问用户和密码 完成以加载页面 到目前为止还不错,即使它问了两次密码。 Node.js应用程序具有