ASP.NET Core中基于令牌的身份验证 [英] Token Based Authentication in ASP.NET Core

查看:78
本文介绍了ASP.NET Core中基于令牌的身份验证的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用ASP.NET Core应用程序.我正在尝试实施基于令牌的身份验证,但无法弄清楚如何为我的案例使用新的安全系统 . 我经历了示例,但是它们并没有太大帮助,他们都在使用Cookie身份验证或外部身份验证(GitHub,Microsoft,Twitter).

I'm working with ASP.NET Core application. I'm trying to implement Token Based Authentication but can not figure out how to use new Security System for my case. I went through examples but they didn't help me much, they are using either cookie authentication or external authentication (GitHub, Microsoft, Twitter).

我的情况是:angularjs应用程序应请求/token传递用户名和密码的url. WebApi应该授权用户并返回access_token,它将在随后的请求中由angularjs应用程序使用.

What my scenario is: angularjs application should request /token url passing username and password. WebApi should authorize user and return access_token which will be used by angularjs app in following requests.

我发现了一篇很棒的文章,介绍了有关在当前版本的ASP.NET中完全实现我所需要的内容-

I've found great article about implementing exactly what I need in current version of ASP.NET - Token Based Authentication using ASP.NET Web API 2, Owin, and Identity. But it is not obvious for me how to do the same thing in ASP.NET Core.

我的问题是:如何配置ASP.NET Core WebApi应用程序以与基于令牌的身份验证一起使用?

My question is: how to configure ASP.NET Core WebApi application to work with token based authentication?

推荐答案

.Net Core 3.1更新:

David Fowler(ASP .NET Core团队的架构师)汇集了一套非常简单的任务应用程序,其中包括

Update for .Net Core 3.1:

David Fowler (architect for the ASP .NET Core team) has put together an incredibly simple set of task applications, including a simple application demonstrating JWT. I'll be incorporating his updates and simplistic style to this post soon.

此答案的先前版本使用RSA;如果生成令牌的相同代码也正在验证令牌,则实际上是没有必要的.但是,如果您要分配职责,则可能仍想使用Microsoft.IdentityModel.Tokens.RsaSecurityKey的实例来做到这一点.

Previous versions of this answer used RSA; it's really not necessary if your same code that is generating the tokens is also verifying the tokens. However, if you're distributing the responsibility, you probably still want to do this using an instance of Microsoft.IdentityModel.Tokens.RsaSecurityKey.

  1. 创建一些常量,稍后我们将使用它们;这是我所做的:

  1. Create a few constants that we'll be using later; here's what I did:

const string TokenAudience = "Myself";
const string TokenIssuer = "MyProject";

  • 将此添加到Startup.cs的ConfigureServices中.稍后我们将使用依赖项注入来访问这些设置.我假设您的authenticationConfigurationConfigurationSectionConfiguration对象,以便您可以为调试和生产使用不同的配置.确保您安全地存储密钥!它可以是任何字符串.

  • Add this to your Startup.cs's ConfigureServices. We'll use dependency injection later to access these settings. I'm assuming that your authenticationConfiguration is a ConfigurationSection or Configuration object such that you can have a different config for debug and production. Make sure you store your key securely! It can be any string.

    var keySecret = authenticationConfiguration["JwtSigningKey"];
    var symmetricKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(keySecret));
    
    services.AddTransient(_ => new JwtSignInHandler(symmetricKey));
    
    services.AddAuthentication(options =>
    {
        // This causes the default authentication scheme to be JWT.
        // Without this, the Authorization header is not checked and
        // you'll get no results. However, this also means that if
        // you're already using cookies in your app, they won't be 
        // checked by default.
        options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
    })
        .AddJwtBearer(options =>
        {
            options.TokenValidationParameters.ValidateIssuerSigningKey = true;
            options.TokenValidationParameters.IssuerSigningKey = symmetricKey;
            options.TokenValidationParameters.ValidAudience = JwtSignInHandler.TokenAudience;
            options.TokenValidationParameters.ValidIssuer = JwtSignInHandler.TokenIssuer;
        });
    

    我已经看到其他答案会更改其他设置,例如ClockSkew;设置了默认值,使其适用于时钟不完全同步的分布式环境.这些是您唯一需要更改的设置.

    I've seen other answers change other settings, such as ClockSkew; the defaults are set such that it should work for distributed environments whose clocks aren't exactly in sync. These are the only settings you need to change.

    设置身份验证.在需要User信息的任何中间件(例如app.UseMvc())之前,您应该有这行内容.

    Set up Authentication. You should have this line before any middleware that requires your User info, such as app.UseMvc().

    app.UseAuthentication();
    

    请注意,这不会导致您的令牌与SignInManager或其他任何东西一起发出.您将需要提供自己的输出JWT的机制-见下文.

    Note that this will not cause your token to be emitted with the SignInManager or anything else. You will need to provide your own mechanism for outputting your JWT - see below.

    您可能要指定一个AuthorizationPolicy.这将允许您指定仅允许使用[Authorize("Bearer")]作为身份验证的承载令牌作为身份验证的控制器和操作.

    You may want to specify an AuthorizationPolicy. This will allow you to specify controllers and actions that only allow Bearer tokens as authentication using [Authorize("Bearer")].

    services.AddAuthorization(auth =>
    {
        auth.AddPolicy("Bearer", new AuthorizationPolicyBuilder()
            .AddAuthenticationTypes(JwtBearerDefaults.AuthenticationType)
            .RequireAuthenticatedUser().Build());
    });
    

  • 这是棘手的部分:构建令牌.

  • Here comes the tricky part: building the token.

    class JwtSignInHandler
    {
        public const string TokenAudience = "Myself";
        public const string TokenIssuer = "MyProject";
        private readonly SymmetricSecurityKey key;
    
        public JwtSignInHandler(SymmetricSecurityKey symmetricKey)
        {
            this.key = symmetricKey;
        }
    
        public string BuildJwt(ClaimsPrincipal principal)
        {
            var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
    
            var token = new JwtSecurityToken(
                issuer: TokenIssuer,
                audience: TokenAudience,
                claims: principal.Claims,
                expires: DateTime.Now.AddMinutes(20),
                signingCredentials: creds
            );
    
            return new JwtSecurityTokenHandler().WriteToken(token);
        }
    }
    

    然后,在需要令牌的控制器中,如下所示:

    Then, in your controller where you want your token, something like the following:

    [HttpPost]
    public string AnonymousSignIn([FromServices] JwtSignInHandler tokenFactory)
    {
        var principal = new System.Security.Claims.ClaimsPrincipal(new[]
        {
            new System.Security.Claims.ClaimsIdentity(new[]
            {
                new System.Security.Claims.Claim(System.Security.Claims.ClaimTypes.Name, "Demo User")
            })
        });
        return tokenFactory.BuildJwt(principal);
    }
    

    在这里,我假设您已经有一个校长.如果您使用的是Identity,则可以使用 IUserClaimsPrincipalFactory<> 将您的User转换为ClaimsPrincipal.

    Here, I'm assuming you already have a principal. If you are using Identity, you can use IUserClaimsPrincipalFactory<> to transform your User into a ClaimsPrincipal.

    要对其进行测试:获取令牌,将其放入 jwt的表单中. io .我上面提供的说明还允许您使用配置中的密码来验证签名!

    To test it: Get a token, put it into the form at jwt.io. The instructions I provided above also allow you to use the secret from your config to validate the signature!

    如果要在HTML页面的部分视图中将此视图与.Net 4.5中的仅承载身份验证结合使用,则现在可以使用ViewComponent进行相同的操作.与上面的控制器操作"代码基本相同.

    If you were rendering this in a partial view on your HTML page in combination with the bearer-only authentication in .Net 4.5, you can now use a ViewComponent to do the same. It's mostly the same as the Controller Action code above.

    这篇关于ASP.NET Core中基于令牌的身份验证的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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