Học viên: Lương Quốc
Lớp: Java Fulltack 15
Email: quoc200799@gmail.com
Link tham khảo: https://www.baeldung.com/get-user-in-spring-security


1. Tổng quan

Trong bài viết này sẽ hiển thị làm sao lấy user details trong Spring Security
User hiện được xác thực có sẵn thông qua một số cơ chế khác nhau trong Spring. Trước tiên, hãy đề cập đến giải pháp phổ biến nhất — truy cập có lập trình.

2. Lấy User trong Bean

Cách đơn giản để lấy currently authenticated principal là thông qua một cuộc gọi tĩnh đến SecurityContextHolder

Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
String currentPrincipalName = authentication.getName();

Một sự cải tiến khi ta sử dụng đoạn mã đầu tiên là nếu có một người dùng được xác thực trước khi thử truy cập nó:

Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (!(authentication instanceof AnonymousAuthenticationToken)) {
    String currentUserName = authentication.getName();
    return currentUserName;
}

Tất nhiên, có những nhược điểm khi có một cuộc gọi tĩnh như thế này và khả năng kiểm tra mã bị giảm là một trong những điều rõ ràng hơn. Thay vào đó, chúng ta sẽ khám phá các giải pháp thay thế cho sự phổ biến này.

3. Lấy User trong Controller

Chúng ta có các tùy chọn bổ sung trong một anotation bean @Controller.
Chúng ta có thể trự tiếp thay đổi principal như một phương thức argument, và nó sẽ được giải quyết chính xác bởi framework:

@Controller
public class SecurityController {

    @RequestMapping(value = "/username", method = RequestMethod.GET)
    @ResponseBody
    public String currentUserName(Principal principal) {
        return principal.getName();
    }
}

Ngoài ra, chúng ta có thể sử dụng authentication token:

@Controller
public class SecurityController {

    @RequestMapping(value = "/username", method = RequestMethod.GET)
    @ResponseBody
    public String currentUserName(Authentication authentication) {
        return authentication.getName();
    }
}

API của lớp Authentication rất cởi mở để framework hỗ trợ vẫn linh hoạt nhất có thể. Vì điều này, Spring Security principal có thể chỉ lấy lại như một Object và cần phải xác định chính xác ví dụ UserDetails

UserDetails userDetails = (UserDetails) authentication.getPrincipal();
System.out.println("User has authorities: " + userDetails.getAuthorities());

Và cuối cùng, đây là trực tiếp từ HTTP request

@Controller
public class GetUserWithHTTPServletRequestController {

    @RequestMapping(value = "/username", method = RequestMethod.GET)
    @ResponseBody
    public String currentUserNameSimple(HttpServletRequest request) {
        Principal principal = request.getUserPrincipal();
        return principal.getName();
    }
}

4. Lấy User thông qua custom Interface

Để tận dụng triệt để việc tiêm phụ thuộc vào Spring và có thể truy xuất xác thực ở mọi nơi, không chỉ trong @Controller bean, chúng ta cần ẩn quyền truy cập tĩnh đằng sau một cách đơn giản:

public interface IAuthenticationFacade {
    Authentication getAuthentication();
}
@Component
public class AuthenticationFacade implements IAuthenticationFacade {

    @Override
    public Authentication getAuthentication() {
        return SecurityContextHolder.getContext().getAuthentication();
    }
}

Mặt tiền hiển thị đối tượng Xác thực trong khi ẩn trạng thái tĩnh và giữ cho code được tách rời và có thể kiểm tra đầy đủ:

@Controller
public class GetUserWithCustomInterfaceController {
    @Autowired
    private IAuthenticationFacade authenticationFacade;

    @RequestMapping(value = "/username", method = RequestMethod.GET)
    @ResponseBody
    public String currentUserNameSimple() {
        Authentication authentication = authenticationFacade.getAuthentication();
        return authentication.getName();
    }
}

5. Lấy User Trong JSP

Currently hiện được xác thực cũng có thể được truy cập trong các trang JSP, bằng cách tận dụng hỗ trợ Spring Security Taglib.
Đầu tiên, chúng ta cần xác định thẻ trong trang:

<%@ taglib prefix="security" uri="http://www.springframework.org/security/tags" %>

Tiếp theo, chúng ta có thể tham khảo từ principal

<security:authorize access="isAuthenticated()">
    authenticated as <security:authentication property="principal.username" /> 
</security:authorize>

6. lấy User trong Thymeleaf

Thymeleaf là một modern, công cụ tạo khuôn mẫu web phía máy chủ, tích hợp tốt với framework Spring MVC.
Hãy xem cách truy cập currently hiện được xác thực trong một trang bằng công cụ Thymeleaf.
Trước tiên, chúng ta cần thêm thymeleaf-spring5 và thymeleaf-extras-springsecurity5 vào dependencies để tích hợp Thymeleaf với Spring Security:

<dependency>
    <groupId>org.thymeleaf.extras</groupId>
    <artifactId>thymeleaf-extras-springsecurity5</artifactId>
</dependency>
<dependency>
    <groupId>org.thymeleaf</groupId>
    <artifactId>thymeleaf-spring5</artifactId>
</dependency>

Bây giờ chúng ta có thể tham chiếu đến phần chính trong trang HTML bằng cách sử dụng thuộc tính sec:authorize:

<html xmlns:th="https://www.thymeleaf.org" 
  xmlns:sec="https://www.thymeleaf.org/thymeleaf-extras-springsecurity5">
<body>
    <div sec:authorize="isAuthenticated()">
      Authenticated as <span sec:authentication="name"></span></div>
</body>
</html>

7. Tổng kết

Bài viết này cho thấy cách lấy thông tin User trong ứng dụng Spring, bắt đầu với cơ chế truy cập tĩnh phổ biến, tiếp theo là một số cách tốt hơn để thêm principal.
Việc triển khai các ví dụ này có thể được tìm thấy trong dự án GitHub. Đây là một dự án dựa trên Eclipse, do đó, nó sẽ dễ dàng nhập và chạy như vốn có. Khi chạy project cục bộ, chúng ta có thể truy cập trang chủ HTML tại đây:

http://localhost:8080/spring-security-rest-custom/foos/1