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/
元哥的筆記