Multiple login pages với Spring Security

Trong các dự án thực tế, các bạn sẽ gặp những trường hợp mà ứng dụng cần thiết phải sử dụng 2 cách login khác nhau tuỳ theo role của user, ví dụ như có những ứng dụng sẽ cần user bình thường login sử dụng token hoặc QR code, còn admin thì login sử dụng username, password. Để hiện thực multiple login pages sử dụng Spring Security như thế nào? Mình sẽ hướng dẫn các bạn trong bài viết này các bạn nhé!

Ứng dụng ví dụ

Đầu tiên, mình sẽ tạo mới một Spring Boot project với Spring Security Starter, Spring Web Starter, Thymeleaf Starter:

Multiple login page với Spring Security

và WebJars với Bootstrap dependency để làm ví dụ như sau:

Kết quả:

Multiple login page với Spring Security

Để thể hiện nhu cầu mà chúng ta đang muốn giải quyết, mình sẽ tạo một controller để expose ra 2 trang, một chỉ cho user có role là USER access và một chỉ cho user có role ADMIN access. Cụ thể như sau:

Thymeleaf template cho các trang này như sau:

admin.html:

user.html:

Lúc này, nếu các bạn chạy ứng dụng lên và request tới 2 trang này, trang login mặc định của Spring Security sẽ luôn được hiển thị.

Mình sẽ sử dụng trang login mặc định của Spring Security cho user “admin” với username và password, còn user bình thường “user” thì mình sẽ sử dụng một custom login page cũng với username và password, tương tự như mình đã làm trong bài viết Custom login page sử dụng Bootstrap và Thymeleaf trong Spring Security.

Code trang login-user.html cho user bình thường đăng nhập như sau:

Expose trang login này trong class ApplicationController như sau::

Bây giờ mình sẽ cấu hình cho Spring Security cho request tới 2 trang này.

Cấu hình Spring Security

Đầu tiên, mình sẽ cấu hình thông tin về user sẽ đăng nhập vào ứng dụng ví dụ.

Như mình nói ở trên, chúng ta sẽ có 2 user là “user” và “admin” với role tương ứng là “USER” và “ADMIN”. Cả hai user này sẽ sử dụng chung một source cho phần authentication, điều này có nghĩa là chúng được lưu trữ ở một nơi giống nhau, trong bài viết này chúng ta sẽ sử dụng source là in memory.

Mình sẽ tạo bean cho đối tượng UserDetailsService chứa thông tin của 2 user này như sau:

Tiếp theo, chúng ta sẽ cấu hình Spring Security.

Ở đây, là vì chúng ta cần handle request cho user có role “USER” thì hiển thị trang custom login còn user có role “ADMIN” sẽ hiển thị trang login mặc định của Spring Security nên mình sẽ định nghĩa multiple class extends abstract class WebSecurityConfigurerAdapter với order như sau:

Ở đây, mình đang khai báo để handle cho request của user bình thường sử dụng class UserSpringSecurityConfiguration còn admin user thì những request còn lại. Mình chỉ khai báo @Order annotation cho class UserSpringSecurityConfiguration để nó được gọi đầu tiên để handle bất kỳ request nào, nếu không thoả điều kiện antMatcher() để nó handle request đó thì class AdminSpringSecurityConfiguration sẽ handle.

Như các bạn thấy, đối với những request bắt đầu với “/user”, nếu user không có role “USER”, mình cấu hình cho ứng dụng ví dụ của chúng ta redirect tới trang “/user-login” để user có thể login, lúc này class AdminSpringSecurityConfiguration sẽ handle request “/user-login” này. Trong class AdminSpringSecurityConfiguration, mình đã cấu hình đối với request bắt đầu bằng “/user-login”, chúng ta sẽ permitAll(). Lúc này trang “/user-login” sẽ được hiển thị. Nếu đăng nhập thành công và user có role “USER” thì ứng dụng của chúng ta sẽ tự động redirect tới trang bắt đầu với “/user” mà chúng ta đã request tới.

Chạy ứng dụng và request tới http://localhost:8080/user/view, các bạn sẽ thấy trang custom login hiển thị như sau:

Multiple login page với Spring Security

Đăng nhập với user “user” và password là “user”, các bạn sẽ thấy kết quả như sau:

Multiple login page với Spring Security

Còn nếu các bạn request tới http://localhost:8080/admin/view, các bạn sẽ thấy trang login mặc định của Spring Security hiển thị. Đăng nhập với user “admin” và password “admin”, các bạn sẽ thấy kết quả như sau:

Multiple login page với Spring Security

Trong class AdminSpringSecurityConfiguration, mình đã cấu hình cho những request còn lại, ngoại trừ request “/user/**”, user phải có role là “ADMIN”.

Các bạn hãy nhớ là, để cấu hình cho những specific riêng biệt thì chúng ta sẽ sử dụng phương thức antMatcher() của đối tượng HttpSecurity với value là request URL mà chúng ta cần. Cho những request còn lại thì các bạn đừng khai báo annotation @Order với class cấu hình, để nó luôn là order cao nhất.

2 thoughts on “Multiple login pages với Spring Security

  1. Ở đây, là vì chúng ta cần handle request cho user có role “USER” thì hiển thị trang custom login còn user có role “ADMIN” sẽ hiển thị trang login mặc định của Spring Security nên mình sẽ định nghĩa multiple class extends abstract class WebSecurityConfigurerAdapter với order như sau:

    Mình cảm thấy hơi khó hiểu, user đang login vào hệ thống thì user đang là anonymous , ko hề có role hay gì cả, làm sao lại check dk hasrole = admin để điều hướng đến trang login của admin??
    Nếu đây là trang login thì bản chất bất cứ ai có url đều có thể truy cập được, cái cần thiết là nếu dùng user thường mà login vào trang của admin thì sẽ bị redirect hoặc chặn thôi

    1. Bạn nên hiểu là có 2 request khác nhau:

      * /user/view
      * /admin/view

      User thì có thể là anonymous user hoặc là user, sau khi đăng nhập, có role USER hoặc ADMIN.

      Anonymous user thì chắc chắn không request được tới 2 request ở trên rồi. Lúc này, app mình sẽ redirect tới trang login để user login tùy theo request mà họ đang muốn, sau đó thì mới kiểm tra logged in user có quyền access tới request mà họ muốn không? Dựa vào role của logged user.

      Không hiểu gì thì cứ nói mình nhé!

Add Comment