Cách xây dựng REST API sử dụng ASP.NET Core, Entity Framework Core và JWT

Cách xây dựng REST API sử dụng ASP.NET Core, Entity Framework Core và JWT

Trong bài viết này, tôi sẽ cung cấp hướng dẫn về cách xây dựng REST API bằng ASP.NET Core, kết nối với cơ sở dữ liệu hiện có bằng Entity Framework Core và bảo mật API bằng JWT (Json Web Token). Tôi sẽ phát triển một ứng dụng REST API cho hàng tồn kho với các thao tác cơ bản.

Lưu ý: Trong hướng dẫn này, tôi đã sử dụng ASP.NET Core 3.1, Entity Framework Core 3.1 với Visual Studio 2019 16.4.0, SQL Server 2017 và Postman.

REST API là gì?

Do ngày càng có nhiều loại ứng dụng client khác nhau (ứng dụng dành cho thiết bị di động, ứng dụng SPA dựa trên trình duyệt, ứng dụng dành cho máy tính để bàn, ứng dụng IOT, v.v.), chúng ta cần những cách tốt hơn để truyền dữ liệu từ máy chủ đến máy khách, không phụ thuộc vào công nghệ và ngăn xếp máy chủ.

REST API giải quyết vấn đề này. REST là viết tắt của chuyển trạng thái đại diện (REpresentational State Transfer). Các REST API dựa trên HTTP và cung cấp cho các ứng dụng khả năng giao tiếp bằng cách sử dụng định dạng JSON nhẹ. Chúng chạy trên máy chủ web.

REST bao gồm các thực thể sau:

Resource: Tài nguyên là các thực thể được định danh duy nhất (ví dụ: dữ liệu từ cơ sở dữ liệu, hình ảnh hoặc bất kỳ dữ liệu nào).

Endpoint: Điểm cuối là một tài nguyên có thể được truy cập thông qua một URL.

HTTP method: Giao thức HTTP là loại yêu cầu mà máy khách gửi đến máy chủ. Các hoạt động chúng ta thực hiện trên tài nguyên phải tuân theo điều này.

HTTP header: Tiêu đề HTTP là một cặp khóa-giá trị được sử dụng để chia sẻ thông tin bổ sung giữa máy khách và máy chủ, chẳng hạn như:

  • Loại dữ liệu được gửi đến máy chủ (JSON, XML).
  • Loại mã hóa được hỗ trợ bởi ứng dụng khách.
  • Mã thông báo liên quan đến xác thực.
  • Dữ liệu khách hàng dựa trên nhu cầu ứng dụng.

Định dạng dữ liệu: JSON là định dạng phổ biến để gửi và nhận dữ liệu thông qua các REST API.

JWT là gì?

Trong phần trước, chúng ta đã biết REST API là gì, và ở đây chúng ta sẽ xem mã thông báo JWT là gì, và cách bảo mật cho các REST API.

JWT là viết tắt của JSON Web Token. Nó là tiêu chuẩn mở và xác định một cách tốt hơn để truyền dữ liệu an toàn giữa hai thực thể (máy khách và máy chủ).

JWT được ký điện tử bằng khóa bí mật của nhà cung cấp mã thông báo hoặc máy chủ xác thực. JWT giúp máy chủ tài nguyên xác minh mã thông báo bằng cùng một khóa bí mật để bạn có thể tin tưởng vào dữ liệu.

JWT bao gồm ba phần sau:

Header: Tiêu đề là dữ liệu được mã hóa bằng base64url của loại mã thông báo và thuật toán được sử dụng để ký dữ liệu.

Payload: là dữ liệu được mã hóa bằng base64url của các xác nhận quyền sở hữu dự định chia sẻ.

Signature: Chữ ký được tạo bằng cách mã hóa (Header được mã hóa + Payload được mã hóa) sử dụng khóa bí mật.

Mã thông báo JWT cuối cùng sẽ giống như sau: Header.Payload.Signature

Bước 1: Khách hàng yêu cầu mã thông báo

Máy khách gửi yêu cầu đến máy chủ xác thực với thông tin cần thiết để chứng minh danh tính của nó.

Bước 2: Tạo mã thông báo

Máy chủ xác thực nhận yêu cầu mã thông báo và xác minh danh tính. Nếu nó được tìm thấy hợp lệ, mã thông báo sẽ được tạo (như đã giải thích trước đó) với các claim cần thiết và mã thông báo JWT sẽ được gửi lại cho máy khách.

Bước 3: Máy khách gửi mã thông báo đến máy chủ tài nguyên

Đối với mỗi yêu cầu tới Tài nguyên hoặc máy chủ API, máy khách cần kèm theo mã thông báo trong tiêu đề và yêu cầu tài nguyên bằng cách sử dụng URI của nó.

Bước 4: Máy chủ tài nguyên xác minh mã thông báo

Làm theo các bước sau để xác minh mã thông báo:

  • Đọc mã thông báo từ tiêu đề xác thực.
  • Tách các phần header, payload và signature ra khỏi mã thông báo.
  • Tạo signature của header và payload đã nhận bằng cách sử dụng cùng một khóa bí mật được sử dụng khi tạo mã thông báo.
  • Kiểm tra xem cả chữ ký mới tạo và chữ ký nhận được từ mã thông báo có hợp lệ hay không.
  • Nếu các chữ ký giống nhau, các mã thông báo hợp lệ (không bị thay đổi ở giữa) và chúng cung cấp quyền truy cập vào tài nguyên được yêu cầu.
  • Nếu các chữ ký khác nhau, một phản hồi 401unauthorized sẽ được gửi lại cho máy khách.

Không chia sẻ thông tin bí mật bằng JWT, vì header và payload của JWT có thể được giải mã và có thể xem các thông tin này.

Phần sau giải thích cách tạo REST API và bảo mật nó bằng mã thông báo.

Tạo ứng dụng ASP.NET Core REST API

Làm theo các bước sau để tạo ứng dụng ASP.NET Core trong Visual Studio 2019:

Bước 1: Đi tới File > New , sau đó chọn Project.

Bước 2: Chọn Create a new project.

Bước 3: Chọn mẫu ASP.NET Core Web Application.

Bước 4:   Nhập tên dự án, sau đó nhấp vào Create. Hộp thoại Mẫu dự án sẽ được hiển thị.

Bước 5: Chọn .NET Core, ASP.NET Core 3.1 và mẫu API (được đánh dấu trong phần sau).

Tạo ứng dụng ASP.NET Core REST API

Bước 6: Nhấp vào Create. Ứng dụng ASP.NET Core API mẫu sẽ được tạo. Xem cấu trúc dự án trong ảnh chụp màn hình sau.

Tạo ứng dụng ASP.NET Core REST API

Theo mặc định, một API mẫu là WeatherForecast được tạo. Chúng ta có thể xóa nó.

Cài đặt các gói NuGet cần thiết

Thêm các gói NuGet sau để thao tác với cơ sở dữ liệu SQL Server bằng cách chạy các lệnh sau trong Package Manager Console (Nhấp vào Tools -> NuGet Package Manager ->  Package Manager Console).

Gói này giúp tạo bộ điều khiển và chế độ xem.

Install-Package Microsoft.VisualStudio.Web.CodeGeneration.Design -Version 3.1.4

Gói này giúp tạo ngữ cảnh cơ sở dữ liệu và các lớp mô hình từ cơ sở dữ liệu.

Install-Package Microsoft.EntityFrameworkCore.Tools -Version 3.1.8

Nhà cung cấp cơ sở dữ liệu cho phép Entity Framework Core hoạt động với SQL Server.

Install-Package Microsoft.EntityFrameworkCore.SqlServer -Version 3.1.8

Nó cung cấp hỗ trợ để tạo và xác thực mã thông báo JWT.

Install-Package System.IdentityModel.Tokens.Jwt -Version 5.6.0

Đây là phần mềm trung gian cho phép ứng dụng ASP.NET Core nhận mã thông báo mang trong đường dẫn yêu cầu.

Install-Package Microsoft.AspNetCore.Authentication.JwtBearer -Version 3.1.8

Hoặc bạn có thể tìm tên gói trong cửa sổ NuGet Package Manager và cài đặt.

Lưu ý: phiên bản của các gói NuGet có thể mới hơn khi bạn làm theo hướng dẫn này.

Tạo cơ sở dữ liệu và kết nối nó với ứng dụng

Tôi hy vọng bạn đã cài đặt SQL Server 2017 trong máy của mình. (Bạn cũng có thể sử dụng SQL Server 2008, 2012 hoặc 2016.)

Nếu chưa cài SQL Server thì bạn có thể tham khảo hướng dẫn sau để cài đặt.

Giới thiệu SQL Server | Comdy
Giới thiệu SQL Server sẽ giúp bạn tìm hiểu về kiến ​​trúc, dịch vụ, công cụ và phiên bản, cài đặt … của SQL Server.

Bước 1: Tạo cơ sở dữ liệu mới (Inventory).

Bước 2: Đối với ứng dụng này, tôi sẽ tạo các bảng có tên là ProductUserInfo với các thuộc tính cơ bản. Dán truy vấn SQL sau vào cửa sổ Query để tạo các bảng cần thiết.

Create Table Products
(
    ProductId Int Identity(1,1) Primary Key,
    Name Varchar(100) Not Null,
    Category Varchar(100),
    Color Varchar(20),
    UnitPrice Decimal Not Null,
    AvailableQuantity Int Not Null
)
GO

Create Table UserInfo
(
    UserId Int Identity(1,1) Not null Primary Key,
    FirstName Varchar(30) Not null,
    LastName Varchar(30) Not null,
    UserName Varchar(30) Not null,
    Email Varchar(50) Not null,
    Password Varchar(20) Not null,
    CreatedDate DateTime Default(GetDate()) Not Null
)
GO

Insert Into UserInfo(FirstName, LastName, UserName, Email, Password) 
Values ('Inventory', 'Admin', 'InventoryAdmin', '[email protected]', '$admin@2017')

Bước 3: Chạy lệnh sau trong Package Manager Console để thiết kế ngược cơ sở dữ liệu nhằm tạo context cho cơ sở dữ liệu và các lớp thực thể POCO từ các bảng. Lệnh sẽ chỉ tạo lớp POCO cho các bảng có khóa chính.

Scaffold-DbContext “Server=******;Database=Inventory;Integrated Security=True” Microsoft.EntityFrameworkCore.SqlServer -OutputDir Models
  • Connection: Thiết lập chuỗi kết nối của cơ sở dữ liệu.
  • Provider: Thiết lập trình cung cấp được sử dụng để kết nối cơ sở dữ liệu.
  • OutputDir : Thiết lập thư mục nơi các lớp POCO được tạo.

Trong trường hợp của chúng ta, lớp Product, lớp UserInfo và lớp context InventoryContext sẽ được tạo như thể hiện trong ảnh chụp màn hình sau.

Tạo cơ sở dữ liệu và kết nối nó với ứng dụng

Trong tệp lớp InventoryContext được tạo tự động, thông tin đăng nhập cơ sở dữ liệu mà bạn có thể thấy được hard code trong phương thức OnConfiguring.

Việc lưu trữ thông tin đăng nhập SQL Server trong lớp C# không phải là một phương pháp hay. Vì vậy, hãy xóa phương thức OnConfiguring và phương thức khởi tạo không tham sốkhỏi lớp InventoryContext (được đánh dấu ở hình dưới).

Xóa phương thức không cần thiết trong lớp InventoryContext

Thêm một chuỗi kết nối vào appsetting.json.

Thêm thông tin cấu hình chuỗi kết nối SQL Server vào file appsetting.json

Sau đó, đăng ký dịch vụ DbContext (InventoryContext) khi khởi động ứng dụng. Trong đoạn mã sau, chuỗi kết nối được đọc từ tập tin appsetting và được truyền cho các dịch vụ DbContext.

Thêm các namespace sau vào file Startup.cs:

using InventoryService.Models;
using Microsoft.EntityFrameworkCore;

Sau đó, dịch vụ DbContext này được đưa vào các controller được yêu cầu thông qua dependency injection.

Xây dựng REST API

Bây giờ, chúng ta có cơ sở dữ liệu và các lớp thực thể. Làm theo các bước sau để tạo Products Api:

Bước 1: Nhấp chuột phải vào thư mục Controllers, chọn Add, và sau đó bấm Controller.

Bước 2: Chọn APIController with actions bằng cách sử dụng mẫu Entity Framework.

Bước 3: Chọn lớp model Products và lớp ngữ cảnh InventoryContext, sau đó đặt tên cho controller là ProductsController.

Xây dựng REST API

Khi chúng ta nhấp vào Add, API sẽ tự động được tạo bằng kỹ thuật tạo mã ASP.NET CORE scaffolding.

Các API sau được tạo:

  • Để liệt kê tất cả các sản phẩm: Phương thức HTTP Get
  • Nhận thông tin chi tiết về sản phẩm: Phương thức HTTP Get
  • Cập nhật chi tiết sản phẩm: Phương thức HTTP Put
  • Tạo sản phẩm: Phương thức HTTP Post
  • Xóa sản phẩm: Phương thức HTTP Delete

Theo best practice của REST, mỗi điểm cuối được gán với các phương thức HTTP tương ứng dựa trên hoạt động của nó.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using InventoryService.Models;
using Microsoft.AspNetCore.Authorization;
 
namespace InventoryService.Controllers
{
    [Authorize]
    [Route("api/[controller]")]
    [ApiController]
    public class ProductsController : ControllerBase
    {
        private readonly InventoryContext _context;
 
        public ProductsController(InventoryContext context)
        {
            _context = context;
        }
 
        [HttpGet]
        public async Task<ActionResult<IEnumerable<Products>>> GetProducts()
        {
            return await _context.Products.ToListAsync();
        }
 
 
        // GET: api/Products/5
        [HttpGet("{id}")]
        public async Task<ActionResult<Products>> GetProducts(int id)
        {
            var products = await _context.Products.FindAsync(id);
 
            if (products == null)
            {
                return NotFound();
            }
 
            return products;
        }
 
        // PUT: api/Products/5
        // To protect from overposting attacks, please enable the specific properties you want to bind to, for
        // more details see https://aka.ms/RazorPagesCRUD.
        [HttpPut("{id}")]
        public async Task<IActionResult> PutProducts(int id, Products products)
        {
            if (id != products.ProductId)
            {
                return BadRequest();
            }
 
            _context.Entry(products).State = EntityState.Modified;
 
            try
            {
                await _context.SaveChangesAsync();
            }
            catch (DbUpdateConcurrencyException)
            {
                if (!ProductsExists(id))
                {
                    return NotFound();
                }
                else
                {
                    throw;
                }
            }
 
            return NoContent();
        }
 
        // POST: api/Products
        // To protect from overposting attacks, please enable the specific properties you want to bind to, for
        // more details see https://aka.ms/RazorPagesCRUD.
        [HttpPost]
        public async Task<ActionResult<Products>> PostProducts(Products products)
        {
            _context.Products.Add(products);
            await _context.SaveChangesAsync();
 
            return CreatedAtAction("GetProducts", new { id = products.ProductId }, products);
        }
 
        // DELETE: api/Products/5
        [HttpDelete("{id}")]
        public async Task<ActionResult<Products>> DeleteProducts(int id)
        {
            var products = await _context.Products.FindAsync(id);
            if (products == null)
            {
                return NotFound();
            }
 
            _context.Products.Remove(products);
            await _context.SaveChangesAsync();
 
            return products;
        }
 
        private bool ProductsExists(int id)
        {
            return _context.Products.Any(e => e.ProductId == id);
        }
    }
}

Bây giờ, chúng ta sẽ thực hiện các sửa đổi sau đối với Get Products API để lọc các sản phẩm:

  • Trả lại các sản phẩm có trong kho.
  • Hỗ trợ giới hạn số lượng kết quả trả về.
[HttpGet]
public async Task<ActionResult<IEnumerable<Products>>> GetProducts(bool? inStock, int? skip, int? take)
{
    var products = _context.Products.AsQueryable();

    if (inStock != null) // Adds the condition to check availability 
    {
        products = _context.Products.Where(i => i.AvailableQuantity > 0);
    }

    if (skip != null)
    {
        products = products.Skip((int)skip);
    }

    if (take != null)
    {
        products = products.Take((int)take);
    }

    return await products.ToListAsync();
}

Thay đổi URL khởi chạy thành api/products trong file launcherSettings.js.

Xây dựng REST API

Chạy và thử nghiệm các API bằng Postman

Bấm Run để xem dịch vụ Inventory. Một tab trình duyệt mới sẽ mở ra và chúng ta sẽ có thể xem danh sách sản phẩm.

Chạy và thử nghiệm các API

Dịch vụ REST Inventory của chúng ta đang hoạt động.

Lưu ý: Số cổng localhost có thể khác trên máy của bạn.

Trong phần này, chúng ta sẽ xem cách sử dụng dịch vụ của mình bằng Postman (Postman là một công cụ thử nghiệm API giúp các nhà phát triển sử dụng và kiểm tra cách hoạt động của một API).

Xem danh sách sản phẩm

Bước 1: Mở Postman và nhập điểm cuối này: https://localhost:44305/api/products.

Bước 2: Chọn phương thức GET và nhấp vào Send. Bây giờ, tất cả các sản phẩm sẽ được liệt kê như trong ảnh chụp màn hình sau.

Xem danh sách sản phẩm

Bây giờ, hãy áp dụng bộ lọc để trả lại các sản phẩm còn hàng và giới hạn số lượng các mặt hàng bằng cách sử dụng ignore và take.

Nhập điểm cuối sau vào Postman: https://localhost:44305/api/products?Instock=true&ignore=2&take=3

Bây giờ, bạn chỉ có thể xem các sản phẩm có trong kho. Nó bỏ qua hai bản ghi đầu tiên và hiển thị ba bản ghi tiếp theo.

Xem danh sách sản phẩm

Xem thông tin chi tiết của sản phẩm

Bước 1: Mở Postman và nhập điểm cuối này: https://localhost:44305/api/products/1.

Bước 2: Chọn phương thức GET và nhấp vào Send. Bây giờ, bạn có thể xem chi tiết của sản phẩm. Ở đây, id sản phẩm là 1.

Xem thông tin chi tiết của sản phẩm

Lưu ý: Thay đổi ProductId dựa trên các bản ghi có sẵn trong cơ sở dữ liệu của bạn.

Tạo một sản phẩm

Bước 1: Nhập điểm cuối này vào Postman: https://localhost:44305/api/products.

Bước 2: Chọn phương thức POST và đặt tiêu đề: ‘Content-Type’: ‘application/json’.

Bước 3: Trong phần Body>Raw, chọn loại JSON (application/javascript) và nhập thông tin chi tiết sản phẩm như sau.

Tạo một sản phẩm

Nhấp vào Send, một sản phẩm được tạo. Bạn thực hiện lại bước xem danh sách sản phẩm ở phía trên sẽ thấy sản phẩm mới được tạo.

Cập nhật sản phẩm

Bước 1 : Nhập điểm cuối này vào Postman: https: // localhost: 44305 / api / products / 7 .

Bước 2 : Chọn phương thức PUT và đặt làm tiêu đề: ‘Content-Type’: ‘application / json’ .

Bước 3 : Trong phần Body> Raw, chọn loại JSON (ứng dụng / javascript) và dán chi tiết sản phẩm.

Cập nhật sản phẩm

Bằng cách nhấp vào Gửi , chi tiết sản phẩm được cập nhật.

Lưu ý: ProductId phải giống nhau ở điểm cuối và chi tiết sản phẩm (xem phần đánh dấu màu đỏ trong hình trước), nếu không API sẽ đưa ra yêu cầu xấu.

Xóa sản phẩm

Bước 1: Nhập điểm cuối này vào Postman: https://localhost:44305/api/products/7.

Bước 2: Chọn phương thức DELETE và nhấp vào Send. Bây giờ, sản phẩm sẽ bị xóa khỏi cơ sở dữ liệu.

Xóa sản phẩm

Tạo JWT

Chúng ta đã có thể chạy và thử nghiệm API của mình bằng Postman, nhưng vấn đề ở đây là bất kỳ ai biết điểm cuối đều có thể sử dụng nó.

Vì vậy, chúng ta cần một tùy chọn để kiểm soát ai có thể sử dụng dịch vụ của chúng ta. Điều này có thể đạt được nhờ sử dụng mã thông báo JWT.

Tạo mã thông báo JWT

Bước 1: Tạo một controller có tên là TokenController.

Bước 2: Dán cấu hình JWT bên dưới vào tệp appsetting.json.

Lưu ý: bạn nên thay thông tin ở phần Key bằng thông tin của bạn.

Bước 3: Thêm action method trong TokenController để thực hiện thao tác sau:

Nhận tên người dùng và mật khẩu làm đầu vào. Sau đó kiểm tra thông tin đăng nhập của người dùng với cơ sở dữ liệu để đảm bảo danh tính của người dùng:

  • Nếu hợp lệ, mã thông báo truy cập sẽ được trả lại.
  • Nếu không hợp lệ, BadRequest sẽ được trả lại.

Ví dụ mã sau đây trình bày cách tạo mã thông báo.

using InventoryService.Models;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.IdentityModel.Tokens;
using System;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
using System.Threading.Tasks;
 
namespace InventoryService.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class TokenController : ControllerBase
    {
        public IConfiguration _configuration;
        private readonly InventoryContext _context;
 
        public TokenController(IConfiguration config, InventoryContext context)
        {
            _configuration = config;
            _context = context;
        }
 
        [HttpPost]
        public async Task<IActionResult> Post(UserInfo _userData)
        {
 
            if (_userData != null && _userData.Email != null && _userData.Password != null)
            {
                var user = await GetUser(_userData.Email, _userData.Password);
 
                if (user != null)
                {
                    //create claims details based on the user information
                    var claims = new[] {
                    new Claim(JwtRegisteredClaimNames.Sub, _configuration["Jwt:Subject"]),
                    new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
                    new Claim(JwtRegisteredClaimNames.Iat, DateTime.UtcNow.ToString()),
                    new Claim("Id", user.UserId.ToString()),
                    new Claim("FirstName", user.FirstName),
                    new Claim("LastName", user.LastName),
                    new Claim("UserName", user.UserName),
                    new Claim("Email", user.Email)
                   };
 
                    var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration["Jwt:Key"]));
 
                    var signIn = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
 
                    var token = new JwtSecurityToken(_configuration["Jwt:Issuer"], _configuration["Jwt:Audience"], claims, expires: DateTime.UtcNow.AddDays(1), signingCredentials: signIn);
 
                    return Ok(new JwtSecurityTokenHandler().WriteToken(token));
                }
                else
                {
                    return BadRequest("Invalid credentials");
                }
            }
            else
            {
                return BadRequest();
            }
        }
 
        private async Task<UserInfo> GetUser(string email, string password)
        {
            return await _context.UserInfo.FirstOrDefaultAsync(u => u.Email == email && u.Password == password);
        }
    }
}

Thử nghiệm mã thông báo JWT bằng Postman

Bước 1: Nhập điểm cuối này https://localhost: 44305/api/token.

Bước 2: Chọn phương thức POST và đặt tiêu đề thành ‘Content-Type’: ‘application/json’.

Bước 3: Trong phần Body>Raw, chọn loại JSON (application/javascript) và truyền thông tin đăng nhập.

Kiểm tra mã thông báo JWT bằng Postman

Bằng cách nhấp vào Send, thông tin đăng nhập của người dùng sẽ được kiểm tra và mã thông báo sẽ được tạo và trả lại. Xem phần nội dung được đánh dấu.

Kiểm tra mã thông báo JWT bằng Postman

Bảo mật điểm cuối API

Bây giờ, chúng tôi có mã thông báo JWT và sẽ xem cách bảo mật API của chúng ta.

Bước 1: Thêm các namespace sau vào tệp Startup.cs:

using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens;
using System.Text;

Bước 2: Cấu hình bổ sung Authentication vào ứng dụng trong phương thức ConfigureService của lớp Startup.

Bảo mật điểm cuối API

Chúng tôi đã truyền khóa bảo mật được sử dụng khi tạo mã thông báo và chúng tôi cũng đã bật xác thực Nhà phát hành (Issuer) và Đối tượng (Audience).

Ngoài ra, chúng tôi đã đặt SaveToken thành true để lưu trữ mã thông báo trong HTTP Context. Vì vậy, chúng tôi có thể truy cập mã thông báo trong controller khi cần thiết.

Bước 3: Thêm middleware Authentication vào đường dẫn yêu cầu (request pipeline) trong phương thức Configure của lớp Startup như sau:

Bảo mật điểm cuối API

Bước 4: Thêm AuthorizeAttribute cho controller hoặc action method cần được bảo mật.

Ở đây tôi đã thêm ủy quyền cho toàn bộ controller, vì vậy tất cả các API trong controller này sẽ được bảo mật bằng mã thông báo JWT. Bạn cũng có thể thêm ủy quyền cho một phương thức API cụ thể.

Thử nghiệm bảo mật API bằng mã thông báo JWT

Bước 1: Trong Postman, nhập điểm cuối này: https://localhost:44305/api/products.

Bước 2: Chọn phương thức GET và sau đó nhấp vào Send. Bây giờ, bạn có thể thấy mã trạng thái là 401 Unauthorized.

Thử nghiệm bảo mật API bằng mã thông báo JWT

Quyền truy cập ẩn danh đã bị chặn và các API đã được bảo mật. Bây giờ, chúng ta sẽ xem cách truy cập các API bằng cách sử dụng mã thông báo.

Bước 3: Sao chép mã thông báo đã được tạo trong các bước trước đó.

Thử nghiệm bảo mật API bằng mã thông báo JWT

Bước 4: Thêm Bearer vào đầu mã thông báo, bạn sẽ có một mã thông báo như sau.

Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJJbnZlbnRvcnlTZXJ2aWNlQWNjZXNzVG9rZW4iLCJqdGkiOiIwMGY2MjcwYy05NmFlLTQwMDUtOWUwOS00YWVkMjU5NWNjMTIiLCJpYXQiOiIxMS8yOS8yMDE5IDY6MTc6MDIgQU0iLCJJZCI6IjEiLCJGaXJzdE5hbWUiOiJJbnZlbnRvcnkiLCJMYXN0TmFtZSI6IkFkbWluIiwiVXNlck5hbWUiOiJJbnZlbnRvcnlBZG1pbiIsIkVtYWlsIjoiSW52ZW50b3J5QWRtaW5AYWJjLmNvbSIsImV4cCI6MTU3NTA5NDYyMiwiaXNzIjoiSW52ZW50b3J5QXV0aGVudGljYXRpb25TZXJ2ZXIiLCJhdWQiOiJJbnZldG9yeVNlcnZpY2VQb3N0bWFuQ2xpZW50In0.r3gDqAL9FmH2LA_-nfyLDrihfhuY5ODk1bGOLECaKcI

Bước 5:Bây giờ, quay lại danh sách sản phẩm. Trong tiêu đề Authorization, hãy dán mã thông báo trước đó vào trường Value, sau đó bấm Send.Bây giờ bạn có thể xem các sản phẩm từ API.

Thử nghiệm bảo mật API bằng mã thông báo JWT
  • Khi chúng ta truyền tiêu đề ủy quyền tới API, middleware authentication sẽ phân tích cú pháp và xác thực mã thông báo. Nếu nó hợp lệ, nó sẽ đặt User.Identity.IsAuthenticated thành true.
  • Các thuộc tính Authorize được thêm vào trong controller sẽ giúp middleware authorization kiểm tra xem các yêu cầu được xác thực hay chưa. Nếu nó là đã được xác thực, API có thể được truy cập.
  • Nếu User.Identity.IsAuthenticated trả về false, lỗi 401 unauthorized sẽ được trả về.
  • Nếu cần, bạn có thể đọc về các claim từ Identity.
Thử nghiệm bảo mật API bằng mã thông báo JWT

Phần kết luận

Trong bài viết này, chúng ta đã học cách tạo REST API bằng ASP.NET Core và Entity Framework Core để thực hiện các thao tác CRUD (Create – Read – Update – Delete) cơ bản, tạo mã thông báo JWT và bảo mật API. Tôi hy vọng bạn thấy bài viết này hữu ích.

Trả lời

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *