Hướng dẫn dùng authentication header trong PHP

Lượt truy cập: 1,131

Trong bài hướng dẫn này, chúng ta sẽ tìm hiểu và lập trình cơ chế xác thực Basic Authentication dựa trên kiến trúc RESTful Web Services, trong đó, yêu cầu xác thực (Request) sẽ được gửi thông qua API-URI.

Công cụ

Để hiện thực được bài hướng dẫn này, chúng ta cần chuẩn bị (tối thiểu) những công cụ sau:

  • Eclipse IDE for Enterprise Java Developers
  • Apache Tomcat 8.5
  • JAX-RS RI 2.30
  • Postman
  • Java JDK 1.8
  • XAMPP 5.6.40

TL;DR

Các bước cấu hình môi trường lập trình, cấu hình Java Servlet, triển khai API theo kiến trúc RESTful Web Services, kiểm thử API, chúng ta có tham khảo trong video tại đây và tải về mã nguồn mẫu tại đây.

Basic HTTP authentication scheme

Tiêu chuẩn RFC-7235 định nghĩa cơ chế xác thực dựa trên giao thức HTTP, cơ chế này cho phép phía máy chủ yêu cầu phía máy khách cung cấp các thông tin xác thực (authentication information). Một cách vắn tắt, cơ chế hoạt động như sau:

  • Máy chủ phản hồi về máy khách mã lỗi 401 (Unauthorized), cùng với thông tin về cách xác thực dựa trên WWW-Authenticate header;
  • Tiếp theo, nếu máy khách muốn xác thực với máy chủ, máy khách cần phải thêm thông tin Authorization vào trường header của HTTP. Thông thường, thông tin dùng để xác thực là tên-truy-cập (Username) và mâ-khẩu (Password).

Hướng dẫn dùng authentication header trong PHP

Trong phạm vi của bài viết, chúng ta sẽ xem cơ chế xác thực này (sau đây gọi tắt là Basic Auth) là một trong những giải pháp dùng để xác thực một người dùng (User/Client) khi gửi truy cập đến API, chúng ta sẽ không thảo luận nhiều về ưu-khuyết điểm của nó. Trong thực tế, bên cạnh cơ chế này, chúng ta còn có những cơ chế khác như (có thể dùng kết hợp với Basic Auth): API Key, Bearer Token, Digest Auth, OAuth 1.0, OAuth 2.0, Hawk Authentication, AWS Signature, NTLM Authentication, Akamai EdgeGrid.

Xét về độ bảo mật, cơ chế Basic Auth dùng mã Base64 để mã hóa và giải mã thông tin xác thực, do vậy, thường không được đánh giá cao về độ bảo mật. Trong thực tế, nếu dùng Basic Auth, chúng ta thường kết hợp với giao thức SSL (HTTPS) để có thêm một lớp mã hóa thông tin.

Xét về mặt kỹ thuật của Basic Auth, để gửi thông tin xác thực, phía máy khách cần phải “đính kèm” thông tin cần xác thực vào trường header của HTTP. Cấu trúc của Authorization header như sau:

  • Thông tin Username và Password được nối lại thành một chuỗi có định dạng username:password;
  • Tiếp theo, chuỗi này được mã hóa (encode) theo chuẩn Base64;
  • Sau cùng, nối thêm từ khóa Basic (cùng với 1 khoảng trắng) vào phía trước chuỗi “username:password” vừa được mã hóa.

Ví dụ, nếu username là newai và password là vietnam, thì giá trị Authorization header sẽ như sau:

Authorization: Basic bmV3YWk6dmlldG5hbQ==

Có một lưu ý với Base64 trong một số ngôn ngữ lập trình, thông thường sẽ bổ sung thêm (padding) ký tự = (dấu bằng) sau chuỗi mã hóa. Tùy thuộc vào ngôn ngữ lập trình, chúng ta cần lưu ý điểm này khi mã hóa một chuỗi. Chẳng hạn, trong Java, thư viện java.util.Base64.Encoder thông thường sẽ padding thêm ký tự = vào cuối chuỗi mã hóa, ngược lại, chúng ta có thể sử dụng phương thức withoutPadding().

Java Service sử dụng GET với Basic Auth

Trong đoạn chương trình bên dưới, chúng ta sẽ tiến hành hiện thực lớp Authentication, trong đó, bao gồm phương thức auth(...):boolean với tham số là chuỗi mã hóa Authorization header theo chuẩn Base64, kết quả trả về là true nếu thông tin xác thực đúng, và ngược lại.

package com.soa.auth;

import java.util.Base64;
import javax.ws.rs.*;
import javax.ws.rs.core.*;

@Path("/auth")
public class Authentication {
	
	@GET
	@Path("/v1")
	@Produces(MediaType.APPLICATION_JSON)
	public boolean auth(@HeaderParam("authorization") String authString)
	{
		// extract data before decoding
		String[] authParts = authString.split("\\s+");
		String authInfo = authParts[1];
		
		// decode the data back to original string
		byte[] bytes = null;
		bytes = Base64.getDecoder().decode(authInfo);
		String decodedAuth = new String(bytes);
		
		// extract username/password
		if(decodedAuth.contains(":"))
		{
			String username = decodedAuth.split(":")[0];
			String password = decodedAuth.split(":")[1];
			
			// change this line to your logic
			if(username.equals("admin") && password.equals("123456"))
				return true;
		}
    return false;
	}
}

Nếu chúng ta hiện thực các Services trong nhiều Package khác nhau, thì thẻ ... trong tập tin web.xml cần phải ghi nhận tất cả những Package đó, mỗi tên Package cần phải đầy đủ và cách nhau bằng dấu ; (semi-colon).

Ví dụ Project có 2 Package (com.soa.democom.soa.auth), thì tập tin web.xml cần phải thể hiện rõ thông tin cả 2 Package này:


  Jersey REST Service
  org.glassfish.jersey.servlet.ServletContainer
  
  
      jersey.config.server.provider.packages
      com.soa.demo;com.soa.auth
  
  
  1

Kiểm thử API bằng Postman

Trước khi kiểm thử API, chúng ta cần phải khởi động Servlet và triển khai (Deploy) dịch vụ lên Server (localhost:8080). [Xem video hướng dẫn]

Hướng dẫn dùng authentication header trong PHP

Các bước thực hiện như sau:

  • Trong phần mềm Postman, chọn thẻ Authorization;
  • Chọn Basic Auth trong trường Type;
  • Nhập thông tin Username và Password;
  • Kiểm tra có phải giao thức GET và bấm Send.

Đến đây, chúng ta đã lập trình và kiểm thử API đã chạy đúng với logic đặt ra. Tại bước này, chúng ta sẽ lập trình một giao diện Web (HTML & PHP) để thể hiện giao diện đăng nhập (HTML) và gửi (PHP) gói tin chứa Authentication header đến máy chủ chứa API (localhost:8081) và nhận (PHP) kết quả xác nhận thông tin người dùng.

Chúng ta sẽ cần hiện thực tập tin login.php chứa phần mã HTML thể hiện giao diện đăng nhập, và mã PHP để gửi thông tin xác nhận đến API và nhận kết quả xác thực từ API.




	
	Log In



	
	

Log In

Username:


Password:


Result: " . $data . "

"; } ?>

Để thực thi được đoạn chương trình trên, chúng ta cần phải có một Web Engine trên máy tính. Bài viết này sử dụng XAMPP 5.6.40 trên hệ điều hành MacOS 10.15.3. Hình bên dưới là kết quả khi thực thi tập tin login.php trên trình duyệt Web.

Hướng dẫn dùng authentication header trong PHP

Tổng kết

Trong bài hướng dẫn này, chúng ta đã hoàn thành được những việc sau:

  • Hiện thực được một Java Project dựa trên RESTful Web Services
  • Triển khai được một API xác thực dựa trên cơ chế HTTP Basic Authentication
  • Hiện thực giao diện Web (HTML & PHP) để gửi yêu cầu xác thực đến API và nhận kết quả xác thực từ API. Chúng ta có thể tiếp tục mở rộng phần giao diện Web theo hướng sau: nếu thông tin xác thực từ API gửi về là true, thì sẽ chuyển hướng (redirect) người dùng vào các giao diện Web/Services khác và quản lý bằng cơ chế Cookies hoặc Session-ID. Trong bài viết tiếp theo, chúng ta sẽ cùng tìm hiểu Cookies để lưu trữ Session của người dùng.

Tài nguyên tải về

  • Video hướng dẫn Sample Project [YouTube]
  • Mã nguồn chương trình trong bài hướng dẫn này [Download]