zoukankan      html  css  js  c++  java
  • .NetCore WebApi——基于JWT的简单身份认证与授权(Swagger)

    目录:

    .NetCore WebApi——Swagger简单配置

    .NetCore WebApi——基于JWT的简单身份认证与授权(Swagger)

    .NetCore WebApi —— Swagger版本控制

    任何项目都有权限这一关键部分。比如我们有许多接口。有的接口允许任何人访问,另有一些接口需要认证身份之后才可以访问;以保证重要数据不会泄露。

    关于JWT

    维基百科上是这样定义的:

    JWT(读作 [/dʒɒt/]),即JSON Web Tokens,是一种基于JSON的、用于在网络上声明某种主张的令牌(token)。JWT通常由三部分组成: 头信息(header), 消息体(payload)和签名(signature)。它是一种用于双方之间传递安全信息的表述性声明规范。JWT作为一个开放的标准(RFC 7519),定义了一种简洁的、自包含的方法,从而使通信双方实现以JSON对象的形式安全的传递信息。

    认证的工作流程:

    1. 客户端携带用户名、密码向授权服务申请 "令牌(token)"

    2.授权服务器验证用户名、密码后根据它的身份生成一张专属的 "令牌" 并JWT的格式规范返回给客户端

    3.客户端将获取到的令牌放入到http的请求头中,然后向资源服务器发起请求。服务器根据客户端发送过来的令牌来进行下一步处理(根据身份来响应客户端是否具有当前接口的权限)

    如下图所示:

     正文:

    主要参考园友  在7楼  的这篇文章 https://www.cnblogs.com/RayWang/p/9536524.html 

     1. 启用Swagger的验证功能

    在startup类中新添加红色部分代码。启动项目观察效果。

    // 注册Swagger服务
                services.AddSwaggerGen(c =>
                {
                    // 添加文档信息
                    c.SwaggerDoc("v1", new Info
                    {
                        Title = "CoreWebApi",
                        Version = "v1",
                        Description = "ASP.NET CORE WebApi",
                        Contact = new Contact
                        {
                            Name = "Jee",
                            Email = "xiaomaprincess@gmail.com",
                            Url = "https://www.cnblogs.com/jixiaosa/"
                        }
                    });
    
                    #region 读取xml信息
    
                    // 使用反射获取xml文件。并构造出文件的路径
                    var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
                    var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
                    // 启用xml注释. 该方法第二个参数启用控制器的注释,默认为false.
                    c.IncludeXmlComments(xmlPath, true);
                    #endregion
    
                    #region 启用swagger验证功能
                    //添加一个必须的全局安全信息,和AddSecurityDefinition方法指定的方案名称一致即可,CoreAPI。
                    var security = new Dictionary<string, IEnumerable<string>> { { "CoreAPI", new string[] { } }, };
                    c.AddSecurityRequirement(security);
                    c.AddSecurityDefinition("CoreAPI", new ApiKeyScheme
                    {
                        Description = "JWT授权(数据将在请求头中进行传输) 在下方输入Bearer {token} 即可,注意两者之间有空格",
                        Name = "Authorization",//jwt默认的参数名称
                        In = "header",//jwt默认存放Authorization信息的位置(请求头中)
                        Type = "apiKey"
                    });
                    #endregion
    
                });

    没启动Swagger验证之前是这样的:

    启用验证之后再看:多了个小按钮

    点开之后是如下界面:文本框里要如输入从服务器获取的Token。格式为:Bearer + 空格+token。 Bearer可以看作是一个默认的规则。

    2.生成token

    .net core 内置了许多帮助类,巧妙的使用这些类组合,就可以生成我们想要的 token

    新建一个tokenl类,编写一个方法来获取JWT字符串

     /// <summary>
        /// 生成JWT字符串
        /// </summary>
        public class Token
        {
            // 密钥,注意不能太短
            public static string secretKey { get; set; } = "xiaomaPrincess@gmail.com";
            /// <summary>
            /// 生成JWT字符串
            /// </summary>
            /// <param name="tokenModel"></param>
            /// <returns></returns>
            public static string GetJWT(TokenModel tokenModel)
            {
                //DateTime utc = DateTime.UtcNow;
                var claims = new List<Claim>
                {
                    new Claim(JwtRegisteredClaimNames.Jti,tokenModel.ID.ToString()),
                    // 令牌颁发时间
                    new Claim(JwtRegisteredClaimNames.Iat, $"{new DateTimeOffset(DateTime.Now).ToUnixTimeSeconds()}"),
                    new Claim(JwtRegisteredClaimNames.Nbf,$"{new DateTimeOffset(DateTime.Now).ToUnixTimeSeconds()}"),
                     // 过期时间 100秒
                    new Claim(JwtRegisteredClaimNames.Exp,$"{new DateTimeOffset(DateTime.Now.AddSeconds(100)).ToUnixTimeSeconds()}"),
                    new Claim(JwtRegisteredClaimNames.Iss,"API"), // 签发者
                    new Claim(JwtRegisteredClaimNames.Aud,"User") // 接收者
                };
    
                
                // 密钥
                var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(secretKey));
                var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
    
                var tokenHandler = new JwtSecurityTokenHandler();
    
                JwtSecurityToken jwt = new JwtSecurityToken(
                    
                    claims: claims,// 声明的集合
                    //expires: .AddSeconds(36), // token的有效时间
                    signingCredentials: creds
                    );
                var handler = new JwtSecurityTokenHandler();
                // 生成 jwt字符串
                var strJWT = handler.WriteToken(jwt);
                return strJWT;
            }
    }

    基本信息类

     public class TokenModel
        {
            /// <summary>
            /// ID
            /// </summary>
            public int ID { get; set; }
            /// <summary>
            /// 名称
            /// </summary>
            public string Name { get; set; }
            /// <summary>
            /// 手机
            /// </summary>
            public string Phone { get; set; }
            /// <summary>
            /// 邮箱
            /// </summary>
            public string Email { get; set; }
            /// <summary>
            /// 身份
            /// </summary>
            public string Sub { get; set; }
        }

    添加一个方法来获取token

    /// <summary>
            /// 获取令牌
            /// </summary>
            /// <param name="ID">ID</param>
            /// <param name="name">账号</param>
            /// <returns></returns>
            [HttpPost]
            public string GetJwt(int ID,string name)
            {
                TokenModel tokenModel = new TokenModel
                {
                    ID = ID,
                    Name=name
                };
    
                return Token.GetJWT(tokenModel);
            }

    在Startup类中配置身份认证服务

    (1)在ConfigureServices方法中注册服务

     #region 添加验证服务
    
                // 添加验证服务
                services.AddAuthentication(x =>
                {
                    x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                    x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
                }).AddJwtBearer(o =>
                {
                    o.TokenValidationParameters = new TokenValidationParameters
                    {
                        // 是否开启签名认证
                        ValidateIssuerSigningKey = true,
                        IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(Token.secretKey)),
                        // 发行人验证,这里要和token类中Claim类型的发行人保持一致
                        ValidateIssuer = true,
                        ValidIssuer = "API",//发行人
                        // 接收人验证
                        ValidateAudience = true,
                        ValidAudience = "User",//订阅人
                        ValidateLifetime = true,
                        ClockSkew = TimeSpan.Zero,
                    };
                });
                #endregion

    (2)在Configure方法中启用验证中间件

       // 启用Swagger中间件
                app.UseSwagger();
                // 配置SwaggerUI
                app.UseSwaggerUI(c =>
                {
                    c.SwaggerEndpoint("/swagger/v1/swagger.json", "CoreAPI");
                    c.RoutePrefix = string.Empty;
                });
                // 启用认证中间件
                app.UseAuthentication();
                app.UseMvc();

    3. 添加一个测试测控制器来检测是否成功

    注意要添加 [Authorize]标签

      /// <summary>
        /// 需要身份认证的控制器
        /// </summary>
        [Route("api/[controller]/[action]")]
        [Produces("application/json")]
        [ApiController]
        [Authorize]// 添加授权特性
        public class TestController : ControllerBase
        {
            /// <summary>
            /// 认证通过之后可访问
            /// </summary>
            /// <returns></returns>
            [HttpPost]
            public ActionResult<TokenModel> Get(TokenModel tokenModel)
            {
                return new TokenModel{ ID=1 };
            }
    
        }

    启动项目

    测试一: 在没有获取token时访问此方法

     返回401 身份验证未通过

    测试二:先访问GetJWT接口获取token,在访问Test接口

    最后将获取的token输入到Swagger的文本框中:Bearer +空格+Token

     再次访问Test接口:成功返回数据

    至此,一个简单身份认证加授权就完成了。

    推荐一篇大神的文章 :讲述Claim的

    理解ASP.NET Core验证模型(Claim, ClaimsIdentity, ClaimsPrincipal)不得不读的英文博文

    源码:GitHub

    https://github.com/xiaoMaPrincess/Asp.NetCore-WebApi

    多层架构版本:

    https://github.com/xiaoMaPrincess/.NetCoreWebApi

  • 相关阅读:
    UE如何区分PDSCH中传输的DCCH和DTCH呢?
    LTE RLC 子层
    LTE的两篇微文
    TD-LTE中S1接口不支持的功能有哪些
    LTE系统消息SIB
    【转载】LTE – TTI Bundling技术
    关于lte上行闭环功控,下面哪个信道不能进行闭环功控
    lte每个小区有多少个可用的随机接入前导码
    LTE的物理小区标识(PCI)
    (转)MVC一个页面多个submit
  • 原文地址:https://www.cnblogs.com/jixiaosa/p/10783855.html
Copyright © 2011-2022 走看看