So sánh secure boot và authenticated boot năm 2024
Bạn có thể sử dụng bài giảng này để hiểu Spring Security là gì và các tính năng cốt lõi như authentication, authorization hay bảo vệ khai thác chung hoạt động như thế nào. Ngoài ra, còn có các câu hỏi thường hay gặp mà bao hàm toàn bộ nội dung. Show
Lưu ý của người biên tập : Với khoảng 6500 từ, bạn có thể sẽ không muốn đọc trên thiết bị di động. Hãy đánh dấu trang và quay lại sau Giới thiệuKhông sớm thì muộn, mọi người đều cần phải thêm bảo mật cho dự án của mình và trong hệ sinh thái Spring bạn có thể thực hiện việc đó với sự trợ giúp của thư viện Spring Security . Vì thế khi bạn mới bắt đầu thêm Spring Security vào dự án Spring Boot của bạn và đột nhiên…
Sau khi sống sót qua khỏi sự suy sụp tinh thần đó, bạn mới bắt đầu quan tâm tìm hiểu cách những thứ này hoạt động ra sao. Spring Security là gì và nó hoạt động như thế nào?Câu trả lời ngắn gọn : Về cốt lõi, Spring Security thực sự chỉ là một loạt các bộ lọc servlet giúp bạn thêm authentication và authorization vào ứng dụng web của mình. Nó cũng tích hợp tốt với các framework như Spring Web MVC (hay Spring Boot ), cũng như với các tiêu chuẩn như OAuth2 hoặc SAML. Và nó tự động tạo các trang login / logout và bảo vệ chống lại các hành vi khai thác thông tin như CSRF. Đến đây vẫn chưa giúp ích gì cho bạn phải không? May mắn thay, cũng có một câu trả lời dài: Chính là phần còn lại của bài viết này. Bảo mật ứng dụng web: 101Trước khi trở thành bậc thầy Spring Security, bạn cần hiểu ba khái niệm quan trọng:
Lời khuyên: Đừng bỏ qua phần này, vì nó là nền tảng cho mọi thứ mà Spring Security thực hiện. Ngoài ra, tôi sẽ làm cho thú vị nhất có thể. 1. Authentication (xác thực)Trước hết, nếu bạn đang chạy một ứng dụng (web) điển hình, bạn cần user của mình authenticate. Điều đó có nghĩa là ứng dụng của bạn cần xác minh xem user có phải là người mà anh ta thừa nhận đúng là anh ta hay không, thường được thực hiện bằng kiểm tra username và password. User : “Tôi là tổng thống Hoa Kỳ. username của tôi là: potus!” Ứng dụng web của bạn : “Chắc chắn rồi, thế còn password thì sao, thưa ngài Tổng thống?” User : “Pass của tôi là: th3don4ld”. Ứng dụng web của bạn : “Đúng. Chào mừng, thưa ngài!” 2. Authorization (Phân quyền)Trong các ứng dụng đơn giản hơn, chỉ cần authenticate là đủ: Ngay sau khi người dùng authenticate, họ có thể truy cập từng phần của ứng dụng. Nhưng hầu hết các ứng dụng đều có khái niệm về quyền (hoặc vai trò). Hãy tưởng tượng: khách hàng có quyền truy cập vào giao diện công khai của webshop của bạn và quản trị viên có quyền truy cập vào khu vực quản trị riêng biệt. Cả hai loại user đều cần đăng nhập, nhưng thực tế authentication đơn thuần không nói lên gì về việc họ được phép làm gì trong hệ thống của bạn. Do đó, bạn cũng cần phải kiểm tra các quyền của user đã được authenticate, tức là bạn cần cấp quyền cho người dùng đó. User : “Hãy để tôi chơi với quả bóng hạt nhân đó….” Ứng dụng web của bạn : "Đợi một giây, tôi cần kiểm tra lại permission của ngài trước… Dạ thưa Chủ tịch, ngài có đủ điều kiện. Hãy cứ tận hưởng” User : “Lại cái nút đỏ đó là gì vậy… ??” 3. Bộ lọc ServletCuối cùng nhưng không kém phần quan trọng, chúng ta hãy xem xét Bộ lọc Servlet. Chúng liên quan gì đến authentication và authorization? Tại sao sử dụng Bộ lọc Servlet?Hãy nhớ lại bài viết khác của tôi , nơi chúng tôi phát hiện ra rằng về cơ bản bất kỳ ứng dụng web Spring nào cũng chỉ là một servlet: cũ của Spring, giúp chuyển hướng các yêu cầu HTTP đến (ví dụ từ trình duyệt) đến @Controllers hoặc @RestControllers của bạn. Vấn đề là: Không có mật mã bảo mật nào được mã hóa trong DispatcherServlet đó và bạn cũng rất có thể không muốn mò mẫm với header HTTP Basic Auth thô sơ trong @Controllers của mình. Để cho tối ưu, việc authentication và authorization nên được thực hiện trước khi một request truy cập vào @Controllers của bạn. May mắn thay, có một cách để thực hiện chính xác điều này trong thế giới web Java: bạn có thể đặt bộ lọc lên trước các servlet, tức là bạn có thể viết SecurityFilter và cấu hình nó trong Tomcat (servlet container/ application server) của bạn để lọc mọi request HTTP trước khi nó truy cập vào servlet của bạn. Một SecurityFilter đơn giảnMột SecurityFilter có khoảng 4 tác vụ và một cách triển khai đơn giản quá mức có thể trông như thế này:
FilterChainsXác minh trong thực tế: Trong khi code trên có thể hoạt động khi biên dịch, nó sớm hay muộn cũng dẫn đến một bộ lọc chất đầy hàng tấn code cho các cơ chế authentication và authorization khác nhau. Trong thế giới thực, bạn sẽ chia bộ lọc này thành nhiều bộ lọc, sau đó bạn _cha_in với nhau. Ví dụ: một request HTTP sẽ…
Khái niệm này được gọi là FilterChain và câu lệnh cuối cùng trong method ở bộ lọc phía trên của bạn thực sự đang authorize cho chính chain đó:
Với một bộ lọc (chain) như vậy thì về cơ bản, bạn có thể xử lý mọi vấn đề authentication hay authorization có trong ứng dụng của mình mà không cần thay đổi việc triển khai ứng dụng thực tế của bạn (như là @RestControllers / @Controllers của bạn). Với những kiến thức đó, hãy cùng tìm hiểu Spring Security sử dụng phép thuật bộ lọc này như thế nào nhé. FilterChain & Security Configuration DSLChúng ta sẽ bắt đầu đề cập đến Spring Security một chút khác thường, bằng cách đi theo hướng ngược lại từ chương trước, bắt đầu với FilterChain của Spring Security. Spring’s DefaultSecurityFilterChainGiả sử bạn đúng cách và sau đó khởi động ứng dụng web của mình. Bạn sẽ thấy thông báo sau:
Nếu bạn mở rộng một dòng đó thành một list, nó sẽ giống như Spring Security không chỉ cài đặt một bộ lọc, thay vào đó, nó cài đặt toàn bộ một filterchain bao gồm 15 (!) bộ lọc khác nhau. Vì vậy, khi một HTTPRequest đến, nó sẽ đi qua tất cả 15 bộ lọc này, trước khi request của bạn cuối cùng truy cập vào @RestControllers của bạn. Thứ tự cũng quan trọng, bắt đầu từ trên cùng list đó và đi xuống đáy. Phân tích FilterChain của SpringSẽ mất rất lâu để có một cái nhìn chi tiết về mọi bộ lọc của chain này, nhưng đây là lời giải thích cho một số bộ lọc đó. Vui lòng xem mã nguồn của Spring Security để hiểu các bộ lọc khác.
Vì vậy, với một số bộ lọc này, Spring Security cung cấp cho bạn trang login / logout, cũng như khả năng login bằng Basic Auth hoặc Form Logins, cũng như một số tính năng bổ sung như CsrfFilter, mà chúng ta sẽ tìm hiểu sau. Nghỉ giữa hiệp : Những bộ lọc đó, phần lớn, chính là Spring Security. Không hơn, không kém. Chúng làm tất cả công việc. Những gì còn lại cho bạn là cấu hình cách chúng hoạt động, tức URL nào cần bảo vệ, URL nào cần bỏ qua và bảng cơ sở dữ liệu nào sẽ được sử dụng để authenticate. Do đó, bước tiếp theo chúng ta cần xem xét cách cấu hình Spring Security. Cách cấu hình Spring Security: WebSecurityConfigurerAdapterVới các phiên bản Spring Security và/hoặc Spring Boot mới nhất, cách để cấu hình Spring Security là có một class:
Đây là giao diện của một WebSecurityConfigurerAdapter điển hình:
Cách sử dụng DSL cấu hình của Spring SecurityPhải mất một thời gian để làm quen với DSL đó, nhưng bạn sẽ tìm thấy nhiều ví dụ hơn trong phần Câu hỏi thường gặp: hững ví dụ phổ biến . Điều quan trọng bây giờ đó là configure method này là nơi bạn chỉ định:
Lưu ý : Bạn sẽ không cần phải override ngay lập tức configure method của adapter, vì nó mặc định đi kèm với một implementation. Cụ thể như dưới đây:
C ấu hình mặc định này là lý do tại sao ứng dụng của bạn bị khóa ngay sau khi bạn thêm Spring Security vào nó. Đơn giản phải không? Tổng quát: Cấu hình DSL của WebSecurityConfigurerAdapterChúng ta đã biết rằng Spring Security bao gồm một số bộ lọc mà bạn cấu hình với class WebSecurityConfigurerAdapter @Configuration. Nhưng còn thiếu một phần quan trọng. Hãy lấy BasicAuthFilter của Spring làm ví dụ. Nó có thể extract username / password từ một HTTP Basic Auth header, nhưng nó authenticate những thông tin này dựa trên điều gì? Đến đây tự nhiên dẫn chúng ta tới câu hỏi về cách authentication hoạt động với Spring Security. Authentication với Spring SecurityKhi nói đến authentication và Spring Security, bạn có ba kịch bản sau:
Lưu ý : Tùy thuộc vào bạn rơi vào kịch bản nào, bạn cần chỉ định các @Beans khác nhau để Spring Security hoạt động, nếu không bạn sẽ nhận được các exception khá khó hiểu (như NullPointerException nếu bạn quên chỉ định PasswordEncoder). Hãy ghi nhớ nó trong tâm trí. Chúng ta hãy xem xét hai kịch bản đầu. 1. UserDetailsService: Có quyền truy cập vào password của userHãy tưởng tượng bạn có một bảng database nơi bạn lưu trữ user của mình. Nó có một vài cột, nhưng quan trọng nhất là nó có cột username và password, nơi bạn lưu trữ hashed password của user.
Trong trường hợp này, Spring Security cần bạn xác định hai bean để thiết lập và chạy authentication
Chỉ định một UserDetailsService đơn giản như sau:
Vì vậy, bạn có thể tự implement các interface này, giống như chúng ta đã làm ở trên, hoặc là sử dụng các interface hiện có mà Spring Security cung cấp. Các Implementation sẵn cóMột lưu ý nhỏ: Bạn luôn có thể tự mình triển khai các interface UserDetailsService và UserDetails. Tuy nhiên, bạn cũng có thể thay thế bằng các implementations có sẵn của Spring Security mà bạn có thể sử dụng/configure/extend/override.
Quy trình làm việc đầy đủ của UserDetails: HTTP Basic AuthenticationBây giờ, hãy quay trở lại HTTP Basic Authentication của bạn, bạn đang bảo mật ứng dụng của mình bằng Spring Security và Basic Auth. Đây là những gì sẽ diễn ra khi bạn chỉ định một UserDetailsService và cố gắng login:
Đó là tất cả gì cần để authenticate. Nhưng đợi đã, làm cách nào Spring Security băm được password từ phía client (bước 3)? Và với thuật toán nào? PasswordEncodersSpring Security không thể đoán một cách kỳ diệu thuật toán băm password ưa thích của bạn. Đó là lý do tại sao bạn cần chỉ định một @Bean khác, một PasswordEncoder. Giả sử nếu bạn muốn sử dụng chức năng hashed password kiểu BCrypt (mặc định của Spring Security) cho tất cả các password của mình , bạn sẽ chỉ định @Bean này trong SecurityConfig.
Điều gì sẽ xảy ra nếu bạn có nhiều thuật toán băm password, vì bạn có một số user cũ có password được lưu trữ bằng MD5 (đừng làm điều này) và những user mới hơn với Bcrypt hoặc thậm chí là thuật toán thứ ba như SHA-256? Vậy thì bạn sẽ sử dụng bộ mã hóa sau:
Bộ mã hóa này hoạt động như thế nào? Nó sẽ xem xét hashed password của UserDetail (đến từ bảng database của bạn chẳng hạn), bây giờ phải bắt đầu với một
8. Prefix (tiền tố) đó, chính là phương pháp hash của bạn! Bảng database của bạn sau đó sẽ trông như thế này: [email protected]{bcrypt}$2y$12$6t86Rpr3llMANhCUt26oUen2WhvXr/A89Xo9zJion8W7gWgZ/[email protected]{sha256}5ffa39f5757a0dad5dfada519d02c6b71b61ab1df51b4ed1f3beed6abe0ff5f6 Spring Security sẽ:
Đó là tất cả những gì có được với PasswordEncoders. Tóm tắt: quyền truy cập vào password của userĐiểm nhấn cho phần này là: nếu bạn đang sử dụng Spring Security và có thể truy cập vào password của user, thì:
Đó là vắn tắt về authentication trong Spring Security. 2. AuthenticationProvider: Không có quyền truy cập vào password của userBây giờ, hãy tưởng tượng rằng bạn đang sử dụng Atlassian Crowd để quản lý danh tính. Điều đó có nghĩa là tất cả user và password của bạn cho tất cả các ứng dụng được lưu trữ trong Atlassian Crowd và không còn trong bảng database của bạn nữa. Điều này có hai hàm ý:
Nếu đúng như vậy, bạn không thể sử dụng UserDetailsService nữa, thay vào đó, bạn cần implement và cung cấp AuthenticationProvider @Bean.
0 Một AuthenticationProvider chủ yếu bao gồm một method và một implementation ngắn gọn có thể trông như thế này:
1
Quy trình làm việc AuthenticationProvider đầy đủ: HTTP Basic AuthenticationBây giờ, hãy quay lại HTTP Basic Authentication của bạn, có nghĩa là bạn đang bảo mật ứng dụng của mình bằng Spring Security và Basic Auth. Đây là những gì sẽ xảy ra khi bạn chỉ định AuthenticationProvider và cố gắng login:
Không có quá trình hash password hoặc gì đó tương tự đang diễn ra, vì về cơ bản bạn đang ủy quyền cho bên thứ ba thực hiện kiểm tra username / password thực tế. Tóm lại đó là tất cả về AuthenticationProvider! Tóm tắt: AuthenticationProviderBài học kinh nghiệm cho phần này là: nếu bạn đang sử dụng Spring Security và không có quyền truy cập vào password của user, thì hãy implement và cung cấp một @Bean AuthenticationProvider . *Lời người dịch: Bài viết khá dài nên sẽ chia làm 2 phần. Đầu phần tiếp theo sẽ bàn tiếp về authorization. |