目錄: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的
源碼:GitHub
https://github.com/xiaoMaPrincess/Asp.NetCore-WebApi
多層架構版本: