如今JWT代替session來作訪問控制已經成爲大部分webapi的作法,今天咱們也來嘗試一下git
WebAPI使用NetCore2.1建立,無身份認證信息github
nuget安裝包web
IdentityModel 選擇穩定版3.9.0 Microsoft.AspNetCore.Authorization 版本2.1.1 Microsoft.AspNetCore.Authentication.JwtBearer 版本2.1.1
Startup注入服務數據庫
public void ConfigureServices(IServiceCollection services) { services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1); #region Auth services.AddAuthentication(x => { x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; }) .AddJwtBearer(o => { o.TokenValidationParameters = new TokenValidationParameters { NameClaimType = JwtClaimTypes.Name, RoleClaimType = JwtClaimTypes.Role, ValidIssuer = "http://localhost:44319", ValidAudience = "api", IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes("this is a security key")) /***********************************TokenValidationParameters的參數默認值***********************************/ // RequireSignedTokens = true, // SaveSigninToken = false, // ValidateActor = false, // 將下面兩個參數設置爲false,能夠不驗證Issuer和Audience,可是不建議這樣作。 // ValidateAudience = true, // ValidateIssuer = true, // ValidateIssuerSigningKey = false, // 是否要求Token的Claims中必須包含Expires // RequireExpirationTime = true, // 容許的服務器時間偏移量 // ClockSkew = TimeSpan.FromSeconds(300), // 是否驗證Token有效期,使用當前時間與Token的Claims中的NotBefore和Expires對比 // ValidateLifetime = true }; }); #endregion } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IHostingEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } else { app.UseHsts(); } app.UseAuthentication(); app.UseHttpsRedirection(); app.UseMvc(); }
以後驗證用戶返回token信息api
新建TokenController的WebAPI控制器服務器
根據用戶post的用戶帳號和密碼從數據庫查詢數據session
這裏咱們加入根據帳號密碼從db匹配到了數據app
而後返回token數據async
上下代碼標紅部分須要保持一致,這個是token須要用來作校驗的,若是不一致可能出現token無效 簽名無效等問題ide
// private MainDBContext _context; [HttpPost] public async Task<IActionResult> GenToken(UserModel model) { //get username and pwd from this model ,then get data from db //var user = _context.Users.FirstOrDefault(l => l.Name == model.Name && l.Pwd == model.PassWord); //If there is data in the database var user = new UserModel() { ID = 1, Email = "example@live.com", Name = "tester", PassWord = "123456" }; //if user null ,return if (user == null) return Unauthorized(); var tokenHandler = new JwtSecurityTokenHandler(); var key = Encoding.ASCII.GetBytes("this is a security key"); var authTime = DateTime.UtcNow; var expiresAt = authTime.AddDays(7); var tokenDescriptor = new SecurityTokenDescriptor { Subject = new ClaimsIdentity(new Claim[] { new Claim(JwtClaimTypes.Audience,"api"), new Claim(JwtClaimTypes.Issuer,"http://localhost:44319"), new Claim(JwtClaimTypes.Id, user.ID.ToString()), new Claim(JwtClaimTypes.Name, user.Name) }), Expires = expiresAt, SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature) }; var token = tokenHandler.CreateToken(tokenDescriptor); var tokenString = tokenHandler.WriteToken(token); return Ok(new { access_token = tokenString, token_type = "Bearer", profile = new { sid = user.ID, name = user.Name, auth_time = new DateTimeOffset(authTime).ToUnixTimeSeconds(), expires_at = new DateTimeOffset(expiresAt).ToUnixTimeSeconds() } }); }
PostMan測試獲取token
這樣能夠成功獲取token,下面來作權限校驗
在須要受權的api上新增 [Authorize] 標記
好比萬年values控制器
咱們分別使用攜帶token和不攜帶token訪問values接口
1 攜帶token訪問,返回了想要的數據
2 未攜帶token,返回401
這樣就達到了咱們想要的效果,以上作個記錄.
簡單的demo
github:https://github.com/ermpark/authapidemo