在ASP.NET Core中实现一个Token base的身份认证

以前在web端的身份认证都是基于Cookie | Session的身份认证, 在没有更多的终端出现之前,这样做也没有什么问题,
但在Web API时代,你所需要面对的就不止是浏览器了,还有各种客户端,这样就有了一个问题,这些客户端是不知道cookie是什么鬼的。 (cookie其实是浏览器搞出来的小猫腻,用来保持会话的,但HTTP本身是无状态的, 各种客户端能提供的无非也就是HTTP操作的API)

而基于Token的身份认证就是应对这种变化而生的,它更开放,安全性也更高。

基于Token的身份认证有很多种实现方式,但我们这里只使用微软提供的API。

接下来的例子将带领大家完成一个使用微软JwtSecurityTokenHandler完成一个基于beare token的身份认证。

注意:这种文章属于Step by step教程,跟着做才不至于看晕,下载完整代码分析代码结构才有意义。

前期准备

创建项目

在VS中新建项目,项目类型选择ASP.NET Core Web Application(.NET Core), 输入项目名称为CSTokenBaseAuth

Coding

  • 创建一些辅助类

    在项目根目录下创建一个文件夹Auth,并添加RSAKeyHelper.cs以及TokenAuthOption.cs两个文件

    • 在RSAKeyHelper.cs中

    using System.Security.Cryptography;


    namespace CSTokenBaseAuth.Auth

    {

        public class RSAKeyHelper

        {

            public static RSAParameters GenerateKey()

            {

                using (var key = new RSACryptoServiceProvider(2048))

                {

                    return key.ExportParameters(true);

                }

            }

        }

    }

    • 在TokenAuthOption.cs中


  • using System;

  • using Microsoft.IdentityModel.Tokens;


  • namespace CSTokenBaseAuth.Auth

  • {

  •     public class TokenAuthOption

  •     {

  •         public static string Audience { get; } = "ExampleAudience";

  •         public static string Issuer { get; } = "ExampleIssuer";

  •         public static RsaSecurityKey Key { get; } = new RsaSecurityKey(RSAKeyHelper.GenerateKey());

  •         public static SigningCredentials SigningCredentials { get; } = new SigningCredentials(Key, SecurityAlgorithms.RsaSha256Signature);


  •         public static TimeSpan ExpiresSpan { get; } = TimeSpan.FromMinutes(20);

  •     }

  • }

  • Startup.cs

    在ConfigureServices中添加如下代码:

  • services.AddAuthorization(auth =>{
        auth.AddPolicy("Bearer", new AuthorizationPolicyBuilder()
            .AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme‌)
            .RequireAuthenticatedUser().Build());
    });
  • 完整的代码应该是这样

  • public void ConfigureServices(IServiceCollection services)
    {    // Add framework services.    services.AddApplicationInsightsTelemetry(Configuration);    // Enable the use of an [Authorize("Bearer")] attribute on methods and classes to protect.
        services.AddAuthorization(auth =>
        {
            auth.AddPolicy("Bearer", new AuthorizationPolicyBuilder()
                .AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme‌)
                .RequireAuthenticatedUser().Build());
        });
        services.AddMvc();
    }
  • 在Configure方法中添加如下代码


  • 这段代码主要是Handle Error用的,比如当身份认证失败的时候会抛出异常,而这里就是处理这个异常的。

    接下来在相同的方法中添加如下代码,


  • 应用JwtBearerAuthentication

  • app.UseJwtBearerAuthentication(new JwtBearerOptions {
        TokenValidationParameters = new TokenValidationParameters {
            IssuerSigningKey = TokenAuthOption.Key,
            ValidAudience = TokenAuthOption.Audience,
            ValidIssuer = TokenAuthOption.Issuer,
            ValidateIssuerSigningKey = true,
            ValidateLifetime = true,
            ClockSkew = TimeSpan.FromMinutes(0)
        }
    });


  • 完整的代码应该是这样




  • 在Controllers中新建一个Web API Controller Class,命名为TokenAuthController.cs。我们将在这里完成登录授权

    在同文件下添加两个类,分别用来模拟用户模型,以及用户存储,代码应该是这样

  • public class User
    {  
  •    public Guid ID { get; set; }  
  •   public string Username { get; set; }  
      public string Password { get; set; }
    }
    public static class UserStorage
    {  
  •   public static List<User> Users { get; set; } = new List<User> {        new User {ID=Guid.NewGuid(),Username="user1",Password = "user1psd" },        new User {ID=Guid.NewGuid(),Username="user2",Password = "user2psd" },        new User {ID=Guid.NewGuid(),Username="user3",Password = "user3psd" }
        };
    }
  • 接下来在TokenAuthController.cs中添加如下方法

  • private string GenerateToken(User user, DateTime expires)
    {   
  •     var handler = new JwtSecurityTokenHandler();
        
        ClaimsIdentity identity = new ClaimsIdentity(        new GenericIdentity(user.Username, "TokenAuth"),        new[] {            new Claim("ID", user.ID.ToString())
            }
        );    var securityToken = handler.CreateToken(new SecurityTokenDescriptor
        {
            Issuer = TokenAuthOption.Issuer,
            Audience = TokenAuthOption.Audience,
            SigningCredentials = TokenAuthOption.SigningCredentials,
            Subject = identity,
            Expires = expires
        });    return handler.WriteToken(securityToken);
    }


  • 该方法仅仅只是生成一个Auth Token,接下来我们来添加另外一个方法来调用它

    在相同文件中添加如下代码

  • [HttpPost]
    public string GetAuthToken(User user)
    {    var existUser = UserStorage.Users.FirstOrDefault(u => u.Username == user.Username && u.Password == user.Password);    if (existUser != null)
        {        var requestAt = DateTime.Now;      
  •   var expiresIn = requestAt + TokenAuthOption.ExpiresSpan;      
  •   var token = GenerateToken(existUser, expiresIn);        return JsonConvert.SerializeObject(new {
                stateCode = 1,
                requertAt = requestAt,
                expiresIn = TokenAuthOption.ExpiresSpan.TotalSeconds,
                accessToken = token
            });
        }    else
        {        return JsonConvert.SerializeObject(new { stateCode = -1, errors = "Username or password is invalid" });
        }
    }


  • 接下来我们来完成授权验证部分

    在Controllers中新建一个Web API Controller Class,命名为ValuesController.cs

    在其中添加如下代码

    public string Get()
    {   
  •  var claimsIdentity = User.Identity as ClaimsIdentity;  
  • var id = claimsIdentity.Claims.FirstOrDefault(c => c.Type == "ID").Value;    return $"Hello! {HttpContext.User.Identity.Name}, your ID is:{id}";
    }


  • 为方法添加装饰属性

    [HttpGet]
    [Authorize("Bearer")]

    完整的文件代码应该是这样

  • using System.Linq;  
    using Microsoft.AspNetCore.Mvc; 
    using Microsoft.AspNetCore.Authorization; 
  • using System.Security.Claims;
  • namespace CSTokenBaseAuth.Controllers
  • {
        [Route("api/[controller]")]  
  •   public class ValuesController : Controller
        {
            [HttpGet]
            [Authorize("Bearer")]       
  •         public string Get()
            {        
  •        var claimsIdentity = User.Identity as ClaimsIdentity;   
  •    var id = claimsIdentity.Claims.FirstOrDefault(c => c.Type == "ID").Value;        
  •        return $"Hello! {HttpContext.User.Identity.Name}, your ID is:{id}";
            }
        }
    }
  • 最后让我们来添加视图

    在Controllers中新建一个Web Controller Class,命名为LoginController.cs

    其中的代码应该是这样

  • using Microsoft.AspNetCore.Mvc; 
    namespace CSTokenBaseAuth.Controllers
    {
        [Route("[controller]/[action]")]   
        public class LoginController : Controller
        {  
  •          public IActionResult Index()
  •         {            return View();
            }
        }
    }


  • 在项目Views目录下新建一个名为Login的目录,并在其中新建一个Index.cshtml文件。

    代码应该是这个样子

  • <html xmlns="http://www.w3.org/1999/xhtml"><head>
        <title></title></head><body>
        <button id="getToken">getToken</button>
        <button id="requestAPI">requestAPI</button>
    
        <script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
        <script>
            $(function () {            var accessToken = undefined;
    
                $("#getToken").click(function () {
                    $.post(                    "/api/TokenAuth",
                        { Username: "user1", Password: "user1psd" },                    function (data) {
                            console.log(data);                        if (data.stateCode == 1)
                            {
                                accessToken = data.accessToken;
    
                                $.ajaxSetup({
                                    headers: { "Authorization": "Bearer " + accessToken }
                                });
                            }
                        },                    "json"
                    );
                })
    
                $("#requestAPI").click(function () {
                    $.get("/api/Values", {}, function (data) {
                        alert(data);
                    }, "text");
                })
            })    </script></body></html>


最后:完整的代码Sample以及运行手册,请访问:How to achieve a bearer token authentication and authorization in ASP.NET Core

原文地址:http://www.cnblogs.com/onecodeonescript/p/6061714.html


.NET社区新闻,深度好文,微信中搜索dotNET跨平台或扫描二维码关注

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值