.NetCore WebApi——基於JWT的簡單身份認證與受權(Swagger)

目錄:html

.NetCore WebApi——Swagger簡單配置git

.NetCore WebApi——基於JWT的簡單身份認證與受權(Swagger)github

.NetCore WebApi —— Swagger版本控制json

 

任何項目都有權限這一關鍵部分。好比咱們有許多接口。有的接口容許任何人訪問,另有一些接口須要認證身份以後才能夠訪問;以保證重要數據不會泄露。api

 

關於JWT安全

維基百科上是這樣定義的:服務器

JWT(讀做 [/dʒɒt/]),即JSON Web Tokens,是一種基於JSON的、用於在網絡上聲明某種主張的令牌(token)。JWT一般由三部分組成: 頭信息(header), 消息體(payload)和簽名(signature)。它是一種用於雙方之間傳遞安全信息的表述性聲明規範。JWT做爲一個開放的標準(RFC 7519),定義了一種簡潔的、自包含的方法,從而使通訊雙方實現以JSON對象的形式安全的傳遞信息。網絡

 

認證的工做流程:架構

1. 客戶端攜帶用戶名、密碼向受權服務申請 "令牌(token)"app

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

相關文章
相關標籤/搜索