Chuyển đến nội dung chính

Authentication and Authorize in Web API 2 (Phần 2): Xác thực địa chỉ email và tùy chỉnh Password Policy

Trong bài viết này, sẽ mô tả các bước để xác thực địa chỉ email sau khi đăng ký và cách tùy chỉnh Password Policy.
Authentication and Authorize in Web API 2 (Phần 1)

Gởi email sau khi tạo account

Table AspNetUsers có 1 cột tên là EmailConfirmed, với kiểu dữ liệu boolean. Khi người dùng chưa xác nhận email (EmailConfirmed = 0), hệ thống sẽ không cho account đó đăng nhập.
Quy trình xác nhận địa chỉ email:
  1. Đăng ký 1 account mới vào hệ thống.
  2. Hệ thống sẽ tạo ra 1 mã code và gởi vào email mà người dùng đã đăng ký
  3. Người dùng mở email, nhấp vào đường link trong email để mở ra 1 cửa sổ mới.
  4. Hệ thống sẽ kiểm tra user id và mã code. Nếu code hợp lệ, EmailConfirmed sẽ được thiết lập bằng true.

Cài đặt MailGun

 Bạn tham khảo cách cài đặt và gởi email bằng MailGun tại: http://nhatkyhoctap.blogspot.com/2017/05/goi-email-voi-mailgun.html
Sau khi thiết lập MailGun, bạn cần tích hợp vào IdentitySystem.
Mở file ApplicationUserManager, và cập nhật hàm Create bằng đoạn code dưới đây
public static ApplicationUserManager Create(IdentityFactoryOptions<ApplicationUserManager> options, IOwinContext context)
{
 var appDbContext = context.Get<LegacyDatabaseContext>();
 var appUserManager =
  new ApplicationUserManager(new UserStore<ApplicationUser>(appDbContext))
  {
   EmailService = new EmailService()
  };

 var dataProtectionProvider = options.DataProtectionProvider;
 if (dataProtectionProvider != null)
 {
  //must implement
  appUserManager.UserTokenProvider =
   new DataProtectorTokenProvider<ApplicationUser>(dataProtectionProvider.Create("ASP.NET Identity"))
   {
    //Code for email confirmation and reset password life time
    TokenLifespan = TimeSpan.FromHours(6)
   };
 }

 return appUserManager;
}

Option UserTokenProvider chịu trách nhiệm tạo ra token email confirm và password reset token.
Cập nhật lại hàm Account/Create

[Route("create")]
public async Task<IHttpActionResult> CreateUser(CreateUserBindingModel createUserModel)
{
    if (!ModelState.IsValid)
    {
        return BadRequest(ModelState);
    }

    var user = new ApplicationUser()
    {
        UserName = createUserModel.Username,
        Email = createUserModel.Email,
        FirstName = createUserModel.FirstName,
        LastName = createUserModel.LastName,
        Level = 3,
        JoinDate = DateTime.Now.Date,
    };

    var addUserResult = await AppUserManager.CreateAsync(user, createUserModel.Password);

    if (!addUserResult.Succeeded)
    {
        return GetErrorResult(addUserResult);
    }


    var code = await AppUserManager.GenerateEmailConfirmationTokenAsync(user.Id);
    //if no route is ConfirmEmailRoute, it will throw an exception.
    var callbackUrl = new Uri(Url.Link("ConfirmEmailRoute", new { userId = user.Id, code = code }));

    await AppUserManager.SendEmailAsync(user.Id, "Confirm your account", "Please confirm your account by clicking <a href=\"" + callbackUrl + "\">here</a>");

    var locationHeader = new Uri(Url.Link("GetUserById", new { id = user.Id }));

    return Created(locationHeader, TheModelFactory.Create(user));
}
Email nhận được sẽ có nội dung:
Please confirm your account by clicking <a href="http://your-domain/api/accounts/ConfirmEmail?userId=your-id&code=your-code">here</a>

Http Status Code

Response trả về sau khi gọi hàm create user sẽ có giá trị Http Code = 201. Ý nghĩa của 1 số Status code được liệt kê bên dưới.
201: Phương thức này trả về đối tượng CreateNegotiatedContentResult, HttpStatusCode = 201, chỉ ra rằng một tài nguyên mới đã được tạo ra. Tham số url được sử dụng để chỉ định URL có thể được sử dụng để yêu cầu đối tượng mới.

Confirm Email

Chúng ta sẽ xây dựng 1 API để nhận 1 Http request với method = GET, để xác nhận thông tin đăng ký.

Bạn chỉ cần kiểm tra xem user id và code có khác rỗng hay không. Sau đó, chúng ta dùng phương thức “ConfirmEmailAsync” để kiểm tra user id và code.
[HttpGet]
[Route("ConfirmEmail", Name = "ConfirmEmailRoute")]
public async Task<IHttpActionResult> ConfirmEmail(string userId, string code)
{
 if (string.IsNullOrEmpty(userId) || string.IsNullOrEmpty(code))
 {
  ModelState.AddModelError("", "User Id and code is required");
 }
 var result = await AppUserManager.ConfirmEmailAsync(userId, code);
 if (result.Succeeded)
 {
  return Ok();
 }
 return GetErrorResult(result);
}

Nếu kết quả trả về bằng true, thì field EmailConfirm trong bảng AspNetUsers sẽ được gán bằng 1.
Như vậy, tài khoản user đã được kích hoạt thành công.

Thay đổi Policy 

Trong phần này, chúng ta sẽ đổi UserPolicy và Password Policy.

Thay đổi User Policy

Trường hợp bạn muốn quy định username chỉ chứa ký tự Alphabet và email chỉ tồn tại duy nhất trong hệ thống.

Mở file ApplicationUserManager
Bạn thêm dòng code
                appUserManager.UserValidator = new UserValidator(appUserManager)
                {
                    AllowOnlyAlphanumericUserNames = true,
                    RequireUniqueEmail = true
                };
Đoạn code nằm trong điều kiện tồn tại Data Proctection Provider

Thay đổi Password Policy

Tương tự như trên, nếu bạn muốn thay đổi Password Policy, bạn thêm đoạn code:
appUserManager.PasswordValidator = new PasswordValidator
{
 RequiredLength = 6,
 RequireNonLetterOrDigit = true,
 RequireDigit = false,
 RequireLowercase = true,
 RequireUppercase = true,
};

Mật khẩu yêu cầu có ít nhất 6 ký tự, bao gồm 1 ký tự không phải là chữ hoặc số (@, #, ...), số, chữ hoa và chữ thường.

Tùy chỉnh Policy cho User và Password

Trong một vài trường hợp, bạn muốn tùy chỉnh Policy cho User, Password hoặc Email. Ví dụ như bạn muốn cho phép những người dùng địa chỉ gmail đăng ký account thôi, hoặc password chứa các ký tự khác "123456".
Tạo 1 class mới, tên "MyCustomerPasswordValidator", nằm trong folder "Validator" và kế thừa từ PasswordValidator.
public class MyCustomPasswordValidator: PasswordValidator
{
 public override async Task<identityresult> ValidateAsync(string password)
 {
  var result = await base.ValidateAsync(password);
  if (password.Contains("abcdef") || password.Contains("123456"))
  {
   var errors = result.Errors.ToList();
   errors.Add("Password can not contain sequence of chars");
   result = new IdentityResult(errors);
  }
  return result;
 }
}
Để sử dụng class MyCustomPasswordValidator, bạn mở file ApplicationUserManager, thêm vào đoạn code sau đây, nằm trong câu lệnh "if dataProtectionProvider != null"
appUserManager.PasswordValidator = new MyCustomPasswordValidator
{
 RequireUppercase = true,
 RequireNonLetterOrDigit = true,
 RequireDigit = false,
 RequireLowercase = true,
 RequiredLength = 6
};
Chúc các bạn thành công!

Nhận xét

Bài đăng phổ biến từ blog này

[ASP.NET MVC] Authentication và Authorize

Một trong những vấn đề bảo mật cơ bản nhất là đảm bảo những người dùng hợp lệ truy cập vào hệ thống. ASP.NET đưa ra 2 khái niệm: Authentication và Authorize Authentication xác nhận bạn là ai. Ví dụ: Bạn có thể đăng nhập vào hệ thống bằng username và password hoặc bằng ssh. Authorization xác nhận những gì bạn có thể làm. Ví dụ: Bạn được phép truy cập vào website, đăng thông tin lên diễn đàn nhưng bạn không được phép truy cập vào trang mod và admin.

ASP.NET MVC: Cơ bản về Validation

Validation (chứng thực) là một tính năng quan trọng trong ASP.NET MVC và được phát triển trong một thời gian dài. Validation vắng mặt trong phiên bản đầu tiên của asp.net mvc và thật khó để tích hợp 1 framework validation của một bên thứ 3 vì không có khả năng mở rộng. ASP.NET MVC2 đã hỗ trợ framework validation do Microsoft phát triển, tên là Data Annotations. Và trong phiên bản 3, framework validation đã hỗ trợ tốt hơn việc xác thực phía máy khách, và đây là một xu hướng của việc phát triển ứng dụng web ngày nay.

Tổng hợp một số kiến thức lập trình về Amibroker

Giới thiệu về Amibroker Amibroker theo developer Tomasz Janeczko được xây dựng dựa trên ngôn ngữ C. Vì vậy bộ code Amibroker Formula Language sử dụng có syntax khá tương đồng với C, ví dụ như câu lệnh #include để import hay cách gói các object, hàm trong các block {} và kết thúc câu lệnh bằng dấu “;”. AFL trong Amibroker là ngôn ngữ xử lý mảng (an array processing language). Nó hoạt động dựa trên các mảng (các dòng/vector) số liệu, khá giống với cách hoạt động của spreadsheet trên excel.