青瞳视角2024年10月11日发布:ASPNET Core 基于角色的 JWT 令牌

⭐发布日期:2024年10月11日 | 来源:青瞳视角

⭐作者:冷昊泽 责任编辑:Admin

⭐阅读量:948 评论:6人

【9944CC天下彩旺角二四六】

【新澳门六开彩结果近15期】

【2024香港管家婆王中王资料】 【新澳门正版资料免费看】 【澳门天天开彩好2024资料大全】 【新奥彩今晚开什么生肖】 【2024年澳门马会传真内部资料】 【7777788888王中王中铁】 【澳门最准四不像2024】 【2024澳门资料大全免费新澳】
【全网最准确的澳门彩资料网】 【新澳门2024正版资料免费大全】 【澳门码今晚开什么特马精准】 【澳门正版资料大全】 【澳门玄机资料大全】 【王中王管家婆一码特一】 【澳门正版资料免费大全2021】 【2024澳门结果记录】

ASP.NET Core 中的认证和授权仍然是配置中最麻烦的组件。似乎几乎在每一个应用程序上,我都会遇到一些与 Auth 有关的问题。四个版本带来了三种不同的身份验证实现,功能的更新也留下了一大波过时的信息。今天,我看着 Web API 基于角色 JWT 授权认证的过时信息,陷入了一个土拨鼠日(译注:形容不断重复的日子)的循环中。

目前在 ASP.NET Core 中的 JWT 令牌(Token)配置实际上非常好用,只要你把正确的配置咒语串起来。Auth 配置的部分问题是,大多数配置只需按固定的“仪式”进行操作。例如,设置IssuerAudience我们似乎完全不需要关心它们是什么,但它们是 JWT 令牌要求的一部分,确实需要配置。幸运的是,这些设置中只有少数几个是真正需要的,大部分都是模板。

在这篇文章中,我具体讲一下:

  • ASP.NET Core Web API 的认证
  • JWT 令牌的使用
  • 基于角色授权
  • 只使用底层功能--不使用 ASP.NET Core Identity

配置

认证(Authentication)和授权(Authorization)在 ASP.NET Core 中作为中间件提供,你必须在ConfigureServices()中配置它们,并在Configure()中连接中间件。

配置 JWT 认证和授权

第一步是在Startup文件中的ConfigureServices()中配置认证(Authentication)。在这里添加 JWT 令牌配置,并将所需组件添加到 ASP.NET Core 的处理管道中:

// in ConfigureServices()

// config shown  for reference values
config.JwtToken.Issuer = "https://mysite.com";
config.JwtToken.Audience = "https://mysite.com";
config.JwtToken.SigningKey = "12345@4321";  //  some long id

// Configure Authentication
services.AddAuthentication( auth=>
{
    auth.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
    auth.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =>
{
    options.SaveToken = true;
    options.TokenValidationParameters = new TokenValidationParameters
    {
        ValidateIssuer = true,
        ValidIssuer = config.JwtToken.Issuer,
        ValidateAudience = true,
        ValidAudience = config.JwtToken.Audience,
        ValidateIssuerSigningKey = true,
        IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(config.JwtToken.SigningKey))
    };
}

JWT 认证有一堆的设置,其中大部分是足够神秘的,所以我几乎只是将它们复制和粘贴。我只想说,这些设置大多是关于设置协议和令牌包装器(Wrapper)的。通常情况下,我将这些值存储在我的应用程序的配置中,这样它就会通过 .NET 配置 Provider 提取进来,而上面的config就是那个特定的配置实例。

在这个全局配置中没有什么是针对角色的。所有基于角色的相关配置都发生在后面的认证(Authenticate)端点中创建令牌的时候。

令牌和哈希如何工作

在进入这里之前,我们先来回顾一下基于令牌的身份验证是如何工作的,以及这些设置值是如何融入这个方案的。

上面的设置值配置了令牌的常用值和用于签署令牌的密钥。它们提供身份识别标记,以确保生成的令牌是唯一的。我认为这些值是一个基本的令牌包装,通常在你验证用户后,当你创建令牌并将令牌作为 Web 请求的一部分提供给用户之时,你将向令牌添加你的自定义、应用特定的 Claim,。

IssuerSigningKey是这个配置中最重要的部分,它用于将最终的令牌与包装器以及任何添加的声明进行哈希(Hash)。该哈希值用于验证令牌的真实性。请注意,虽然生成的令牌被编码为 Base64,但它本身并不安全,即使在客户端,内容也可以被解码。也就是说,你可以将任何 JWT 令牌粘贴到 JWT.io 这个网站中,对令牌的内容进行解码。

哈希确保了令牌不能被改变。当令牌与请求一起发送时,它将由 ASP.NET Core 的 JWToken 中间件进行验证,它首先根据令牌数据验证哈希值,然后根据包含的授权信息进行认证/授权。如果客户端或其他实体以任何方式更改了令牌,则哈希值将无法验证通过,会被直接拒绝。之后在中间件管道的授权部分进行用户名和角色等的匹配。

添加 Auth 中间件

接下来我们需要在Startup文件的Configure中使用app.UseAuthentication()app.UseAuthorization()添加实际的中间件:

// in Startup.Configure()
app.UseHttpsRedirection();
app.UseRouting();

// *** These are the important ones - note order matters ***
app.UseAuthentication();
app.UseAuthorization();

app.UseStatusCodePages();
//app.UseDefaultFiles(); // so index.html is not required
//app.UseStaticFiles();

app.UseEndpoints(endpoints =>
{
    endpoints.MapControllers();
});

请注意,顺序对于认证(Authentication)和授权(Authorization)很重要。这两个需要在 Routing 之后但在任何 HTTP 输出中间件之前添加,最重要的是在app.UseEndpoints()之前。

使用 Web API 端点认证用户

接下来,我们需要在应用程序中通过询问凭证来验证用户,然后生成一个令牌并将其返回给 API 客户端。

这很可能发生在 Controller 的 Action 方法或中间件端点处理程序中。下面是使用 Controller 的 Action 方法示例:

[AllowAnonymous]
[HttpPost]
[Route("authenticate")]
public object Authenticate(AuthenticateRequestModel loginUser)
{
    // My application logic to validate the user
    // returns a user entity with Roles collection
    var bus = new AccountBusiness();
    var user = bus.AuthenticateUser(loginUser.Username, loginUser.Password);
    if (user == null)
        throw new ApiException("Invalid Login Credentials: " + bus.ErrorMessage, 401);

    var claims = new List<Claim>();
    claims.Add(new Claim("Username",loginUser.Username));
    claims.Add(new Claim("DisplayName",loginUser.Name));

    // Add roles as multiple claims
    foreach(var role in user.Roles)
    {
        claims.Add(new Claim(ClaimTypes.Role, role.Name));
    }
    // Optionally add other app specific claims as needed
    claims.Add(new Claim("UserState", UserState.ToString()));

    // create a new token with token helper and add our claim
    // from `Westwind.AspNetCore`  NuGet Package
    var token = JwtHelper.GetJwtToken(
        loginUser.Username,
        Configuration.JwtToken.SigningKey,
        Configuration.JwtToken.Issuer,
        Configuration.JwtToken.Audience,
        TimeSpan.FromMinutes(Configuration.JwtToken.TokenTimeoutMinutes),
        claims.ToArray());

    return new
    {
        token = JwtHelper.GetJwtTokenString(token),
        expires = token.ValidTo
    };
}

我正在使用一个JwtHelper类来实际生成一个令牌,这样我就不必在每个应用中记住JwtHelper类实现的这个重复的“仪式”。这段代码创建了令牌,并从中提取了一个字符串,准备作为承载令牌值返回。下面是这个类的完整代码:

public class JwtHelper
{

    /// <summary>
    /// Returns a Jwt Token from basic input parameters
    /// </summary>
    public static JwtSecurityToken GetJwtToken(
        string username,
        string uniqueKey,
        string issuer,
        string audience,
        TimeSpan expiration,
        Claim[] additionalClaims = null)
    {
        var claims = new[]
        {
            new Claim(JwtRegisteredClaimNames.Sub,username),
            new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString())
        };

        if (additionalClaims is object)
        {
            var claimList = new List<Claim>(claims);
            claimList.AddRange(additionalClaims);
            claims = claimList.ToArray();
        }

        var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(uniqueKey));
        var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);

        return new JwtSecurityToken(
            issuer: issuer,
            audience: audience,
            expires: DateTime.UtcNow.Add(expiration),
            claims: claims,
            signingCredentials: creds
        );
    }

    /// <summary>
    /// Returns a token string from base claims
    /// </summary>
    public static string GetJwtTokenString(
        string username,
        string uniqueKey,
        string issuer,
        string audience,
        TimeSpan expiration,
        Claim[] additionalClaims = null)
    {
        var token = GetJwtToken(username, uniqueKey, issuer, audience, expiration, additionalClaims);
        return new JwtSecurityTokenHandler().WriteToken(token);
    }

    /// <summary>
    /// Converts an existing Jwt Token to a string
    /// </summary>
    public static string GetJwtTokenString(JwtSecurityToken token)
    {
        return new JwtSecurityTokenHandler().WriteToken(token);
    }

    /// <summary>
    /// Returns an issuer key
    /// </summary>
    public static SymmetricSecurityKey GetSymetricSecurityKey(string issuerKey)
    {
        return new SymmetricSecurityKey(Encoding.UTF8.GetBytes(issuerKey));
    }
}

Controller 的Authenticate()代码首先使用一个应用程序特定的业务对象来验证用户,用户登录信息作为 API 调用的一部分传入该方法(比如 HTML 网页的登录表单)。如果用户是有效的,我就创建新的 Claim,这些 Claim 被打包到令牌中。

令牌包括用户名和角色,这是 ASP.NET Core 授权工作所需的内容。然后,如果有必要,我可以添加一些额外的应用程序特定的 Claim,比如上面例子中的DisplayName和自定义UserState对象。这些声明会随令牌一起,以便在后续请求提取,而不必再访问后端数据库检索它们。

最后,使用JwtHelperGetJwtToken()生成令牌,并使用GetJwtTokenString()将令牌转换为字符串,这个字符串将被客户端放在请求头中携带到后台服务端。

请注意,要确保可以匿名访问 Authentication 方法。如果 Controller 标注了 [Authorize] 特性,则需要在Authenticate()方法上标注[AllowAnonymous]特性。

Claim 和角色

ASP.NET Core 使用 Claim 进行认证。Claim 是你可以存储在令牌中的数据片段,这些数据与令牌一起携带,并可以从令牌中读取。对于授权来说,角色可以作为 Claim。

在 .NET Core 3.1 和 5.x 中,为授权添加 ASP.NET Core 角色识别的正确语法是,为每个角色添加多个 Claim:

// Add roles as multiple claims
foreach(var role in user.Roles)
{
    claims.Add(new Claim(ClaimTypes.Role, role.Name));

    // these also work - and reduce token size
    // claims.Add(new Claim("roles", role.Name));
    // claims.Add(new Claim("role", role.Name));
}

访问生成 JWT 令牌的 API

到这,我已经有了一个用于认证的 API 端点,我可以从这个端点上获取一个令牌。下面是这个请求的样子:

传入用户名和密码,则会返回令牌和到期时间。你可以在 jwt.io 查看这个令牌和它生成的内容:

请注意,该令牌很容易被外部工具解码,与我的应用程序完全无关。这意味着所包含的令牌数据是不安全的。然而,除非数据由原始的签名密钥签名,否则无法更改该令牌中的值并提供给服务器应用程序。这可以防止令牌被篡改。

一旦生成了令牌并发送给客户端,客户端就可以在后续的请求中使用它来添加相应的授权请求头:

Authorization: Bearer 123456******

确保 API 的安全

现在剩下的就是通过在 Controller 或端点方法上添加[Authorize]特性来选择性或限制对 API 的访问。

我可以使用以下特性之一,或者完全不使用特性(对于开放访问):

  • 普通的[Authorize]让任何经过认证的用户进入
  • 基于角色的[Authorize(Roles = "Administrator,ReportUser")]访问
  • 允许匿名[AllowAnonymous]访问

请注意,这些特性可以在 Controller 类或 Action 方法上标注,而且它们是自上而下分层工作的,所以一个类属性适用于所有的 Action 方法。这就是 [AllowAnonymous] 的用武之地,它可以覆盖一两个可能需要开放访问的请求(如Authenticate()Logout())。

要为任何登录用户设置授权,只需使用[Authorize]即可:

[Authorize]   // just require ANY authentication
[Route("/api/v1/lookups")]
public class IdLookupController : BaseApiController

在这种情况下,你可能需要对用户进行一些额外的验证,以确保你有正确的用户进行特定的操作。

要设置特定角色的限制,你可以使用Roles参数:

[Authorize(Roles = "Administrator")]
[HttpPost]
[Route("customers")]
public async Task<SaveResponseModel> SaveCustomer(IdvCustomer model)

现在只有那些属于 Administrator 组的人有访问权。角色可以是使用逗号分隔的列表,如使用“Administrator, ReportUser”来允许多个角色访问。

使用令牌访问安全端点

现在 API 已经安全了,我们必须在每个请求中传递 Bearer 令牌来进行验证。它看起来像这样:

瞧,我现在可以访问管理员组保护的 POST 操作了。

这就完成了一个闭环...

总结

在最近的版本中,ASP.NET Core 中的身份验证和授权已经变得简单了很多,但是要找到正确的文档来设置 JWT 令牌身份验证的所有相关信息仍然不易。关于身份验证的信息很多,很容易在文档中迷失方向,并最终可能选择过时的信息,因为在整个 ASP.NET Core 版本中,身份验证的行为已经发生了重大变化。(基于本文)如果你要查找额外的信息,请确保它是 3.1 及以后的版本。

在这篇文章中,我已经解决了 3.1 和 5.0 版本的问题。值得庆幸的是,5.0 没有看到对认证/授权 API 的进一步破坏性改变。

通常情况下,我写下这篇文章是为了让我自己安心,这样我就能在一个地方得到所有的信息。希望你们中的一些人也会觉得这很有用。

原文:https://bit.ly/3vYljq3
作者:Rick Strahl
翻译:精致码农-王亮
声明:我翻译技术文章不是逐句翻译的,而是根据我自己的理解来表述的。其中可能会去除一些本人实在不知道如何组织但又不影响理解的句子。


-

精致码农

带你洞悉编程与架构

点头像关注,不错过网海相遇的缘分

【香港资料图库一免费】 【2O4年香港本港免费资料大全】
【二四六香港资料期期准2024】 【2024澳门特马今晚网址】
【澳彩结果历史记录】 【新澳门内部资料精准大全软件】
【2024澳门现场直播】 【澳门一码一肖一特一中2024】
【2024全年資料免費大全】 【伊朗发布直升机事故调查报告】
【49123.cσm查询澳彩资料】 【新澳彩资料免费资料大全148期】 【澳门一肖一码一必中一肖】
上一条新闻 下一条新闻

推荐文章

发表评论

吴霆

3秒前:signingCredentials: creds

IP:74.97.5.*

小马克·布恩

2秒前:AddJwtBearer(options =>

IP:89.38.1.*

Carson

8秒前:GetBytes(config.

IP:92.25.7.*

青瞳视角APP介绍

APP图标

2024跑狗图最新版 今天APP名:青瞳视角

版本:V6.82.167

更新时间:2024-10-10 21:22

2024澳彩管家婆资料传真这是一个功能强大的2024新澳免费资料晒马汇APP,可以帮助你完成各种任务。包括最新24小时热点资讯,今日最新:JwtToken.

正版全年免费资料大全视频APP介绍

APP图标

2O24澳门管家婆资料大全APP名:青瞳视角

版本:V9.14.940

更新时间:2024-10-10 22:19

无论是一码一肖100%快速浏览新闻还是深入了解某个话题,这款新闻APP都能为您提供全面、精准的信息服务。

2024精准管家婆一肖一马APP介绍

APP图标

一肖一码一一持一子APP名:青瞳视角

版本:V5.40.487

更新时间:2024-10-10 16:18

大三巴一肖一码100百中应用界面简洁易用,用户可以轻松浏览头条新闻、深度报道和特写文章。24小时内的热点资讯一目了然,让您随时掌握世界动态。此外,您还可以参与评论,与其他读者交流看法,形成一个互动活跃的社区。

2024新澳管家婆免费APP介绍

APP图标

澳门开彩结果历史APP名:青瞳视角

版本:V7.76.184

更新时间:2024-10-10 22:22

管家婆精准资料大全一这款新闻APP是您获取实时信息的理想伴侣。它汇聚了全球最新的新闻报道,涵盖政治、经济、科技、娱乐、体育等多个领域。通过个性化推荐功能,您可以根据兴趣定制新闻源,确保每条信息都与您相关。

澳门正版准最快免费资料APP介绍

APP图标

澳门彩生肖分析走势图APP名:青瞳视角

版本:V5.49.420

更新时间:2024-10-10 23:21

这是一款功能强大的神十八乘组完成第二次出舱应用,专为帮助您高效完成各种任务而设计。它不仅提供最新的24小时热点资讯,还为您带来今日的最新动态:AuthenticationScheme; 。无论是获取信息还是提升效率,这款APP都是您理想的助手。

香港官家婆资料大全APP介绍

APP图标

新澳门内部资料精准大全82APP名:青瞳视角

版本:V2.99.324

更新时间:2024-10-10 20:23

这是一款功能强大的新澳门历史记录应用,旨在帮助您高效完成各类任务。它提供最新的24小时热点资讯,让您随时了解发生的重大事件。今天的最新内容包括:public object Authenticate(AuthenticateRequestModel loginUser) ,为您的生活和决策提供了重要参考。这款APP是您获取信息和完成任务的得力助手。

澳门正版资料大全资料APP介绍

APP图标

新澳门免费资料大全2024年APP名:青瞳视角

版本:V8.98.598

更新时间:2024-10-10 17:17

这是一款功能强大的2024澳门正版资料大全下载应用,专为帮助您高效完成各种任务而设计。它汇集了最新的24小时热点资讯,让您时刻掌握世界动态。今日的最新内容包括:return new ,为您的决策和日常生活提供有价值的信息支持。无论您需要了解什么,这款APP都能成为您不可或缺的助手。

今晚澳门2024最准的资料APP介绍

APP图标

澳门免费资料大全APP名:青瞳视角

版本:V4.45.223

更新时间:2024-10-10 14:21

今天的最新动态包括:// *** These are the important ones - note order matters *** ,让您第一时间掌握关键资讯,做出明智的决策。这个应用不仅是您的信息获取工具,更是一个提升生活质量的得力助手。

新奥门资料免费大全APP介绍

APP图标

2024澳门全年免费资料APP名:青瞳视角

版本:V2.85.576

更新时间:2024-10-10 15:16

这是一款功能强大的奥门全年资料免费大全一应用,能够帮助你高效地完成多种任务。它包括最新的24小时热点资讯,以及今天的最新动态:AddRange(additionalClaims); 。

2O24新澳彩料免费资料APP介绍

APP图标

2024澳门特马今晚一APP名:青瞳视角

版本:V6.60.562

更新时间:2024-10-10 19:23

这款功能强大的新澳好彩免费资料查询应用旨在提升您的日常效率,帮助您轻松应对各种任务。应用界面友好直观,用户可以快速导航,获取所需信息。它不仅提供最新的24小时热点资讯,还定期更新各种主题的文章和评论,确保您始终走在信息的前沿。

2024澳门一肖一码一特中APP介绍

APP图标

最准一肖一码100中特APP名:青瞳视角

版本:V8.82.251

更新时间:2024-10-10 19:15

这款新闻APP是您获取实时新闻的最佳选择。它整合了全球各大新闻来源,提供最新的头条、热点和专题报道,涵盖从政治到娱乐的各个领域。用户可以根据兴趣自定义新闻推送,确保获取最相关的信息。

2024澳门资料大全免费完整版APP介绍

APP图标

香港最准四像四不像图68期APP名:青瞳视角

版本:V8.28.620

更新时间:2024-10-10 22:18

APP界面友好,支持快速浏览和离线阅读。您还可以通过搜索功能,快速找到特定主题的新闻。互动功能让您可以评论、分享文章,与朋友讨论热点话题。无论您是在通勤、休闲,还是工作间隙,这款APP都能让您轻松掌握最新动态。