[ASP.NET Core]ASP.NET Core API 使用JWT驗證

ASP.NET Core 

今天要記錄一下API設計的時候,比較常用的授權和驗證的模式,JWT是其中一種比較常用的方式

為什麼要使用JWT

       在早期的Web登入部分都是採用Cookie居多,當登入的時候都是存放在Cookie裡面,當使用者進行
請求狀況,服務端的部分就會跟Cookie進行解密的動作,然後檢核OK之後,就會進行後續作業程序,這
是因為使用者是基於使用在瀏覽器的狀況使用,今天如果遇到APP的情況???
      那麼JWT就是其中一個做法,改用JWT的做法時候,就會請求token,就會涉及到Token認證,簡單來
說Token認證說穿就是通行證,例如你要去迪士尼樂園,你就要購買門票,所以售票人員會看你的票,來決
定你要去那些園區。

常用地方:跨伺服器請求資源、APP身分證驗證、IOT裝置驗證

JWT的組成是由Header.Payload.Signature

Header:Base64編碼的Header

{
  "alg": "HS256",
  "typ": "JWT"
}

Payload:以Base64的Payload包含了Claims

{
    "sub": "765032130654732",
    "name": "jeffcky"
}

Signature:在透過對應加密演算法變成簽名,以點為隔開

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1bmlxdWVfbmFtZSI6IjEiLCJuYmYiOjE1ODM3MzczMDQsImV4cCI6MTU4NDM0MjEwNCwiaWF0IjoxNTgzNzM3MzA0fQ.ch5zXaUhtfi8tiHvchpGgAjxx1tIgtFXIZ_hJkPcpxY

實作JWT,建立相關資料夾
 


設定Secret

 

在設置Startup.cs
 


Entities/User.cs
 

    public class User
    {
        public string Username { get; set; }
        public string Password { get; set; }
        public string Token { get; set; }
    }

定義Service Interface
 

namespace JWTDemo.Interface
{
    public interface IUserService
    {
        User Authenticate(string username, string password);
    }
}

實作Service Layer
 

    public class UserService:IUserService
    {

        
        private List<User> _users = new List<User> {
            new User{Username = "test",Password = "test"}
        };

        private readonly AppSettings _appSettings;

        public UserService(IOptions<AppSettings> appSettings)
        {
            _appSettings = appSettings.Value;
        }

        public User Authenticate(string username, string password)
        {
            var user = _users.SingleOrDefault(x => x.Username == username && x.Password == password);
            if (user == null)
                return null;

            var tokenHandler = new JwtSecurityTokenHandler();
       
            var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_appSettings.Secret));
            var jwt = new JwtSecurityToken(
                  claims: new List<Claim> { new Claim(ClaimTypes.Name, username) },
                  notBefore: DateTime.UtcNow,
                  expires: DateTime.UtcNow.AddHours(1), // 1小時候過期
                  signingCredentials: new SigningCredentials(key, SecurityAlgorithms.HmacSha256)
            );

            user.Token = tokenHandler.WriteToken(jwt);
            user.Password = null;
            return user;
        }

    }

Controller部分

   [Route("[controller]")]
    [ApiController]
    public class UserController : ControllerBase
    {
        private IUserService _userService;

        public UserController(IUserService userService)
        {
            _userService = userService;
        }

        [AllowAnonymous]
        [HttpPost("authenticate")]
        public IActionResult Authenticate([FromBody] AuthenticateModel model) 
        {
            var user = _userService.Authenticate(model.Username, model.Password);

            if (user == null) 
            {
                return BadRequest(new { nessage = "使用者名稱或密碼不正確" });
            }
            return Ok(user);
        }

    }

在調整Startup.cs
 

            var appSettingsSection = Configuration.GetSection("AppSettings");
            services.Configure<AppSettings>(appSettingsSection);
            //加入Token Jwt
            var appSettings = appSettingsSection.Get<AppSettings>();
            var key = Encoding.ASCII.GetBytes(appSettings.Secret);
            services.AddAuthentication(x =>
            {
                x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
            })
            .AddJwtBearer(x =>
            {
                x.RequireHttpsMetadata = false;
                x.SaveToken = true;
                x.TokenValidationParameters = new TokenValidationParameters
                {
                    ValidateIssuerSigningKey = true,
                    IssuerSigningKey = new SymmetricSecurityKey(key),
                    ValidateIssuer = false,
                    ValidateAudience = false,
                    ValidateLifetime = true,
                    ClockSkew = TimeSpan.Zero
                };
            });
            //DI
            services.AddScoped<IUserService, UserService>();

 

        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseHttpsRedirection();

            app.UseRouting();
            //加入
            app.UseAuthentication();

            app.UseAuthorization();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
            });
        }

完成後如下
 



取到Token去取其他API
 

https://dotnettutorials.net/lesson/token-based-authentication-web-api/

元哥的筆記