สร้างโปรเจ็กส์แบบ webapi
สร้างโปรเจ็กส์แบบ webapi ชื่อโปรเจ็กส์ webJwt
[code]
> dotnet new webapi -o webJwt
> cd webJwt
[/code]
Startup.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.IdentityModel.Tokens; using System.Text; namespace webJwt { public class Startup { public Startup(IConfiguration configuration) { Configuration = configuration; } public IConfiguration Configuration { get; } // This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddJwtBearer(options => { options.TokenValidationParameters = new TokenValidationParameters { ValidateIssuer = true, ValidateAudience = true, ValidateLifetime = true, ValidateIssuerSigningKey = true, ValidIssuer = Configuration["Jwt:Issuer"], ValidAudience = Configuration["Jwt:Issuer"], IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["Jwt:Key"])) }; }); services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1); } // 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.UseHttpsRedirection(); app.UseAuthentication(); app.UseMvc(); } } } |
บรรทัดที่ 24-37 : เป็นการคอนฟิกให้รองรับ JWT-based authentication
บรรทัดที่ 55: เป็นการเรียกใช้ Authen (ต้องอยู่ก่อน app.UseMvc()
)
appsettings.json
1 2 3 4 5 6 7 8 9 10 11 12 |
{ "Logging": { "LogLevel": { "Default": "Warning" } }, "AllowedHosts": "*", "Jwt": { "Key": "veryVerySecretKey", "Issuer": "http://localhost:44307/" } } |
บรรทัดที่ 9 : ไม่แน่ใจว่า Key
นี้คือ private key หรือเปล่า ถ้าใช่ ก็ตั้งอะไรก็ได้ ยากๆเข้าไว้
บรรทัดที่ 10 : ใส่ค่า port ไม่ตรง ก็ทำงานได้ปกติดี
ตอนนี้ฝั่ง Server รองรับ JWT ละ
ต่อมาให้ฝั่ง Server รองรับการเชื่อมต่อแบบปลอดภับ (Securing ASP.NET Core 2.0 Endpoints with JWTs)
สร้างไฟล์ Controller/BookController.cs ไว้คืนรายชื่อหนัสือ
และไฟล์ Controller/TokenController.cs ไว้สร้าง Token
Controller/BooksController.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using System.Collections.Generic; namespace webJwt.Controllers { [Route("api/[controller]")] public class BooksController : Controller { [HttpGet, Authorize] public IEnumerable<Book> Get() { var currentUser = HttpContext.User; var resultBookList = new Book[] { new Book { Author = "Ray Bradbury",Title = "Fahrenheit 451" }, new Book { Author = "Gabriel García Márquez", Title = "One Hundred years of Solitude" }, new Book { Author = "George Orwell", Title = "1984" }, new Book { Author = "Anais Nin", Title = "Delta of Venus" } }; return resultBookList; } public class Book { public string Author { get; set; } public string Title { get; set; } public bool AgeRestriction { get; set; } } } } |
เรียก https://localhost:5001/api/books ตอนนี้จะยังใช้งานไม่ได้ 401 unauthorized เพราะต้องมี Token ก่อนถึงจะใช้งานได้
Controller/TokenController.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Configuration; using Microsoft.IdentityModel.Tokens; using System; using System.IdentityModel.Tokens.Jwt; using System.Text; namespace webJwt.Controllers { [Route("api/[controller]")] public class TokenController : Controller { private IConfiguration _config; public TokenController(IConfiguration config) { _config = config; } [AllowAnonymous] [HttpPost] public IActionResult CreateToken([FromBody]LoginModel login) { IActionResult response = Unauthorized(); var user = Authenticate(login); if (user != null) { var tokenString = BuildToken(user); response = Ok(new { token = tokenString }); } return response; } private string BuildToken(UserModel user) { var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_config["Jwt:Key"])); var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256); var token = new JwtSecurityToken(_config["Jwt:Issuer"], _config["Jwt:Issuer"], expires: DateTime.Now.AddMinutes(30), signingCredentials: creds); return new JwtSecurityTokenHandler().WriteToken(token); } private UserModel Authenticate(LoginModel login) { UserModel user = null; if (login.Username == "mario" && login.Password == "secret") { user = new UserModel { Name = "Mario Rossi", Email = "mario.rossi@domain.com" }; } return user; } public class LoginModel { public string Username { get; set; } public string Password { get; set; } } private class UserModel { public string Name { get; set; } public string Email { get; set; } public DateTime Birthdate { get; set; } } } } |
บรรทัดที่ 54 : กำหนด Username
และ Password
สำหรับการ Authen ไว้แบบ hardcode
ตอนนี้พร้อมใช้ละ
ลองเรียกด้วย Postman แบบ POST ไปที่ https://localhost:5001/api/token
พร้อมส่งค่าไปใน Body แบบ raw JSON
[code]
{"username": "mario", "password": "secret"}
[/code]
จะได้ค่า Token กลับมา เช่น
[code]
{"token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1Mzk1ODQ5MzIsImlzcyI6Imh0dHA6Ly9sb2NhbGhvc3Q6NDQzMDcvIiwiYXVkIjoiaHR0cDovL2xvY2FsaG9zdDo0NDMwNy8ifQ.2BPWXkdGTk_Lmmij04OwFtncw_n5-wMEsPSlVaMKhqg"}
[/code]
พอได้ Token มา
ทีนี้เรียกดูรายชื่อหนังสือแบบ GET ที่ https://localhost:5001/api/books
พร้อมส่ง Authorization แบบ Bearer Token โดยนำค่า Token ที่ได้มา ใส่ลงไปในช่อง Token ดังรูป
จะได้รายชื่อหนังสือกลับมา
[code]
[
{
"author": "Ray Bradbury",
"title": "Fahrenheit 451",
"ageRestriction": false
},
{
"author": "Gabriel García Márquez",
"title": "One Hundred years of Solitude",
"ageRestriction": false
},
{
"author": "George Orwell",
"title": "1984",
"ageRestriction": false
},
{
"author": "Anais Nin",
"title": "Delta of Venus",
"ageRestriction": false
}
]
[/code]
ถ้ามี Error เกิดขึ้นแบบนี้
[code]
ArgumentNullException: String reference not set to an instance of a String. Parameter name: s
• System.Text.Encoding.GetBytes(string s)
• webJwt.Startup.<ConfigureServices>b__4_0(JwtBearerOptions options) in Startup.cs
27. options.TokenValidationParameters = new TokenValidationParameters
[/code]
ให้ตรวจสอบค่าในไฟล์ appsettings.json ว่าใส่ครบดีมั๊ย (ไม่ต้องเสียเวลาแก้ที่ c#)
Link