1. 程式人生 > >NetCore使用Jwtbearer給WebAPI新增訪問控制

NetCore使用Jwtbearer給WebAPI新增訪問控制

現在JWT代替session來做訪問控制已經成為大部分webapi的做法,今天我們也來嘗試一下

WebAPI使用NetCore2.1建立,無身份認證資訊

nuget安裝包

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資訊

新建TokenController的WebAPI控制器

根據使用者post的使用者賬號和密碼從資料庫查詢資料

這裡我們加入根據賬號密碼從db匹配到了資料

然後返回token資料

上下程式碼標紅部分需要保持一致,這個是token需要用來做校驗的,如果不一致可能出現token無效 簽名無效等問題

   // 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 = "[email protected]", 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