{"id":90567,"date":"2025-11-24T13:59:04","date_gmt":"2025-11-24T06:59:04","guid":{"rendered":"https:\/\/itviec.com\/blog\/?p=90567"},"modified":"2025-11-24T13:59:09","modified_gmt":"2025-11-24T06:59:09","slug":"spring-boot-security-la-gi","status":"publish","type":"post","link":"https:\/\/itviec.com\/blog\/spring-boot-security-la-gi\/","title":{"rendered":"Spring Boot Security l\u00e0 g\u00ec? Kh\u00e1c g\u00ec v\u1edbi Spring Security?"},"content":{"rendered":"<div id=\"ez-toc-container\" class=\"ez-toc-v2_0_84 counter-hierarchy ez-toc-counter ez-toc-grey ez-toc-container-direction\">\n<div class=\"ez-toc-title-container\">\n<p class=\"ez-toc-title\" style=\"cursor:inherit\">N\u1ed9i dung b\u00e0i vi\u1ebft<\/p>\n<span class=\"ez-toc-title-toggle\"><a href=\"#\" class=\"ez-toc-pull-right ez-toc-btn ez-toc-btn-xs ez-toc-btn-default ez-toc-toggle\" aria-label=\"Toggle Table of Content\"><span class=\"ez-toc-js-icon-con\"><span class=\"\"><span class=\"eztoc-hide\" style=\"display:none;\">Toggle<\/span><span class=\"ez-toc-icon-toggle-span\"><svg style=\"fill: #999;color:#999\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" class=\"list-377408\" width=\"20px\" height=\"20px\" viewBox=\"0 0 24 24\" fill=\"none\"><path d=\"M6 6H4v2h2V6zm14 0H8v2h12V6zM4 11h2v2H4v-2zm16 0H8v2h12v-2zM4 16h2v2H4v-2zm16 0H8v2h12v-2z\" fill=\"currentColor\"><\/path><\/svg><svg style=\"fill: #999;color:#999\" class=\"arrow-unsorted-368013\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"10px\" height=\"10px\" viewBox=\"0 0 24 24\" version=\"1.2\" baseProfile=\"tiny\"><path d=\"M18.2 9.3l-6.2-6.3-6.2 6.3c-.2.2-.3.4-.3.7s.1.5.3.7c.2.2.4.3.7.3h11c.3 0 .5-.1.7-.3.2-.2.3-.5.3-.7s-.1-.5-.3-.7zM5.8 14.7l6.2 6.3 6.2-6.3c.2-.2.3-.5.3-.7s-.1-.5-.3-.7c-.2-.2-.4-.3-.7-.3h-11c-.3 0-.5.1-.7.3-.2.2-.3.5-.3.7s.1.5.3.7z\"\/><\/svg><\/span><\/span><\/span><\/a><\/span><\/div>\n<nav><ul class='ez-toc-list ez-toc-list-level-1 ' ><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-1\" href=\"https:\/\/itviec.com\/blog\/spring-boot-security-la-gi\/#Spring_Boot_Security_co_gi_khac_voi_Spring_Security\" >Spring Boot Security c\u00f3 g\u00ec kh\u00e1c v\u1edbi Spring Security?<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-2\" href=\"https:\/\/itviec.com\/blog\/spring-boot-security-la-gi\/#Spring_Boot_co_cac_tinh_nang_nao_cua_Spring_Security\" >Spring Boot c\u00f3 c\u00e1c t\u00ednh n\u0103ng n\u00e0o c\u1ee7a Spring Security?&nbsp;<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-3\" href=\"https:\/\/itviec.com\/blog\/spring-boot-security-la-gi\/#Cac_khai_niem_quan_trong_cua_Spring_Boot_Security\" >C\u00e1c kh\u00e1i ni\u1ec7m quan tr\u1ecdng c\u1ee7a Spring Boot Security<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-4\" href=\"https:\/\/itviec.com\/blog\/spring-boot-security-la-gi\/#Uy_quyen_trong_Spring_Boot_security\" >\u1ee6y quy\u1ec1n trong Spring Boot security<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-5\" href=\"https:\/\/itviec.com\/blog\/spring-boot-security-la-gi\/#Huong_dan_cai_dat_cau_hinh_va_lam_viec_voi_Spring_Boot_security\" >H\u01b0\u1edbng d\u1eabn c\u00e0i \u0111\u1eb7t c\u1ea5u h\u00ecnh v\u00e0 l\u00e0m vi\u1ec7c v\u1edbi Spring Boot security<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-6\" href=\"https:\/\/itviec.com\/blog\/spring-boot-security-la-gi\/#Cac_chu_de_nang_cao_va_bao_mat_toan_dien\" >C\u00e1c ch\u1ee7 \u0111\u1ec1 n\u00e2ng cao v\u00e0 b\u1ea3o m\u1eadt to\u00e0n di\u1ec7n<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-7\" href=\"https:\/\/itviec.com\/blog\/spring-boot-security-la-gi\/#Cac_phuong_phap_tot_nhat_de_su_dung_Spring_Boot_security\" >C\u00e1c ph\u01b0\u01a1ng ph\u00e1p t\u1ed1t nh\u1ea5t \u0111\u1ec3 s\u1eed d\u1ee5ng Spring Boot security<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-8\" href=\"https:\/\/itviec.com\/blog\/spring-boot-security-la-gi\/#Cac_cau_hoi_thuong_gap_ve_Spring_Boot_Security\" >C\u00e1c c\u00e2u h\u1ecfi th\u01b0\u1eddng g\u1eb7p v\u1ec1 Spring Boot Security<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-9\" href=\"https:\/\/itviec.com\/blog\/spring-boot-security-la-gi\/#Tong_ket\" >T\u1ed5ng k\u1ebft<\/a><\/li><\/ul><\/nav><\/div>\n\n<p><strong><em>Trong ph\u00e1t tri\u1ec3n \u1ee9ng d\u1ee5ng web, b\u1ea3o m\u1eadt l\u00e0 y\u1ebfu t\u1ed1 s\u1ed1ng c\u00f2n. V\u1edbi c\u00e1c \u1ee9ng d\u1ee5ng x\u00e2y d\u1ef1ng tr\u00ean n\u1ec1n t\u1ea3ng Spring, Spring Boot Security ch\u00ednh l\u00e0 &#8220;t\u1ea5m khi\u00ean&#8221; m\u1ea1nh m\u1ebd v\u00e0 linh ho\u1ea1t \u0111\u1ec3 ch\u1ed1ng l\u1ea1i c\u00e1c m\u1ed1i \u0111e d\u1ecda an ninh m\u1ea1ng. B\u00e0i vi\u1ebft n\u00e0y s\u1ebd h\u01b0\u1edbng d\u1eabn b\u1ea1n c\u00e1ch t\u00edch h\u1ee3p v\u00e0 s\u1eed d\u1ee5ng Spring Boot Security m\u1ed9t c\u00e1ch hi\u1ec7u qu\u1ea3, t\u1eeb c\u00e1c b\u01b0\u1edbc x\u00e1c th\u1ef1c v\u00e0 ph\u00e2n quy\u1ec1n c\u01a1 b\u1ea3n \u0111\u1ebfn nh\u1eefng k\u1ef9 thu\u1eadt n\u00e2ng cao, gi\u00fap b\u1ea1n b\u1ea3o v\u1ec7 \u1ee9ng d\u1ee5ng c\u1ee7a m\u00ecnh m\u1ed9t c\u00e1ch to\u00e0n di\u1ec7n.<\/em><\/strong><\/p>\n\n\n\n<p>\u0110\u1ecdc b\u00e0i vi\u1ebft n\u00e0y \u0111\u1ec3 hi\u1ec3u r\u00f5:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Spring Boot Security c\u00f3 g\u00ec gi\u1ed1ng v\u00e0 kh\u00e1c v\u1edbi Spring Security?<\/li>\n\n\n\n<li>C\u00e1c kh\u00e1i ni\u1ec7m quan tr\u1ecdng c\u1ee7a Spring Boot Security<\/li>\n\n\n\n<li>H\u01b0\u1edbng d\u1eabn c\u00e0i \u0111\u1eb7t c\u1ea5u h\u00ecnh v\u00e0 l\u00e0m vi\u1ec7c v\u1edbi Spring Boot security<\/li>\n\n\n\n<li>C\u00e1c ch\u1ee7 \u0111\u1ec1 n\u00e2ng cao v\u00e0 b\u1ea3o m\u1eadt to\u00e0n di\u1ec7n<\/li>\n\n\n\n<li>C\u00e1c ph\u01b0\u01a1ng ph\u00e1p t\u1ed1t nh\u1ea5t \u0111\u1ec3 s\u1eed d\u1ee5ng Spring Boot security<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-spring-boot-security-co-gi-khac-v\u1edbi-spring-security\"><span class=\"ez-toc-section\" id=\"Spring_Boot_Security_co_gi_khac_voi_Spring_Security\"><\/span><strong>Spring Boot Security c\u00f3 g\u00ec kh\u00e1c v\u1edbi Spring Security?<\/strong><span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>\u0110\u1ec3 hi\u1ec3u r\u00f5 <strong>Spring Boot Security<\/strong>, tr\u01b0\u1edbc ti\u00ean ch\u00fang ta c\u1ea7n ph\u00e2n bi\u1ec7t n\u00f3 v\u1edbi &#8220;cha \u0111\u1ebb&#8221; c\u1ee7a n\u00f3 l\u00e0 <strong>Spring Security<\/strong>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-spring-security-la-gi\"><strong>Spring Security l\u00e0 g\u00ec?<\/strong><\/h3>\n\n\n\n<p>Spring Security l\u00e0 m\u1ed9t framework m\u1ea1nh m\u1ebd v\u00e0 t\u00f9y bi\u1ebfn cao, cung c\u1ea5p c\u00e1c gi\u1ea3i ph\u00e1p to\u00e0n di\u1ec7n v\u1ec1 x\u00e1c th\u1ef1c (Authentication) v\u00e0 ph\u00e2n quy\u1ec1n (Authorization) cho c\u00e1c \u1ee9ng d\u1ee5ng Java. N\u00f3 l\u00e0 m\u1ed9t d\u1ef1 \u00e1n ri\u00eang bi\u1ec7t trong h\u1ec7 sinh th\u00e1i Spring, c\u00f3 kh\u1ea3 n\u0103ng t\u00edch h\u1ee3p v\u1edbi nhi\u1ec1u c\u00f4ng ngh\u1ec7 kh\u00e1c nhau.<\/p>\n\n\n\n<p>Tuy nhi\u00ean, s\u1ee9c m\u1ea1nh c\u1ee7a n\u00f3 c\u0169ng \u0111i k\u00e8m v\u1edbi s\u1ef1 ph\u1ee9c t\u1ea1p trong vi\u1ec7c c\u1ea5u h\u00ecnh ban \u0111\u1ea7u, \u0111\u00f2i h\u1ecfi l\u1eadp tr\u00ecnh vi\u00ean ph\u1ea3i t\u1ef1 tay thi\u1ebft l\u1eadp r\u1ea5t nhi\u1ec1u th\u00e0nh ph\u1ea7n.<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p><em>\u0110\u1ecdc chi ti\u1ebft: <strong><a href=\"https:\/\/itviec.com\/blog\/spring-security-la-gi\/\" target=\"_blank\" rel=\"noreferrer noopener\">Spring security: Kh\u00e1m ph\u00e1 framework b\u1ea3o m\u1eadt h\u00e0ng \u0111\u1ea7u cho \u1ee9ng d\u1ee5ng Java<\/a><\/strong><\/em><\/p>\n<\/blockquote>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-spring-boot-security-la-gi\"><strong>Spring Boot Security l\u00e0 g\u00ec?<\/strong><\/h3>\n\n\n\n<p>Spring Boot Security kh\u00f4ng ph\u1ea3i l\u00e0 m\u1ed9t framework ho\u00e0n to\u00e0n m\u1edbi. Ch\u00ednh x\u00e1c h\u01a1n, n\u00f3 l\u00e0 c\u00e1ch m\u00e0 Spring Boot t\u00edch h\u1ee3p v\u00e0 t\u1ef1 \u0111\u1ed9ng c\u1ea5u h\u00ecnh Spring Security. Khi b\u1ea1n th\u00eam spring-boot-starter-security v\u00e0o d\u1ef1 \u00e1n, Spring Boot s\u1ebd t\u1ef1 \u0111\u1ed9ng \u00e1p d\u1ee5ng m\u1ed9t chu\u1ed7i c\u00e1c c\u1ea5u h\u00ecnh b\u1ea3o m\u1eadt m\u1eb7c \u0111\u1ecbnh h\u1ee3p l\u00fd (sensible defaults). \u0110i\u1ec1u n\u00e0y gi\u00fap b\u1ea1n c\u00f3 ngay m\u1ed9t \u1ee9ng d\u1ee5ng \u0111\u01b0\u1ee3c b\u1ea3o v\u1ec7 m\u00e0 kh\u00f4ng c\u1ea7n vi\u1ebft b\u1ea5t k\u1ef3 d\u00f2ng code c\u1ea5u h\u00ecnh n\u00e0o.<\/p>\n\n\n\n<p>N\u00f3i m\u1ed9t c\u00e1ch \u0111\u01a1n gi\u1ea3n: <strong>Spring Boot Security = Spring Security + T\u1ef1 \u0111\u1ed9ng c\u1ea5u h\u00ecnh.<\/strong><\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-spring-boot-security-co-gi-khac-v\u1edbi-spring-security-0\"><strong>Spring Boot Security c\u00f3 g\u00ec kh\u00e1c v\u1edbi Spring Security?<\/strong><\/h3>\n\n\n\n<p>B\u1ea3ng d\u01b0\u1edbi \u0111\u00e2y t\u1ed5ng h\u1ee3p c\u00e1c \u0111i\u1ec3m kh\u00e1c nhau c\u01a1 b\u1ea3n gi\u1eefa Spring Security vs Spring Boot Security:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><td><strong>Ti\u00eau ch\u00ed<\/strong><\/td><td><strong>Spring Security (Truy\u1ec1n th\u1ed1ng)<\/strong><\/td><td><strong>Spring Boot Security<\/strong><\/td><\/tr><tr><td><strong>C\u1ea5u h\u00ecnh<\/strong><\/td><td><strong>Ph\u1ee9c t\u1ea1p v\u00e0 th\u1ee5 \u0111\u1ed9ng h\u01a1n: <\/strong>Ph\u1ea3i t\u1ef1 t\u1ea1o c\u00e1c l\u1edbp c\u1ea5u h\u00ecnh (v\u00ed d\u1ee5: k\u1ebf th\u1eeba t\u1eeb <code>WebSecurityConfigurerAdapter<\/code> tr\u01b0\u1edbc \u0111\u00e2y), \u0111\u1ecbnh ngh\u0129a c\u00e1c <code>Bean<\/code> nh\u01b0 <code>PasswordEncoder<\/code>, <code>AuthenticationManager<\/code> m\u1ed9t c\u00e1ch th\u1ee7 c\u00f4ng.<\/td><td><strong>\u0110\u01a1n gi\u1ea3n v\u00e0 t\u1ef1 \u0111\u1ed9ng<\/strong>: Ch\u1ec9 c\u1ea7n th\u00eam starter, Spring Boot t\u1ef1 \u0111\u1ed9ng cung c\u1ea5p c\u1ea5u h\u00ecnh b\u1ea3o m\u1eadt c\u01a1 b\u1ea3n. M\u1ecdi endpoint m\u1eb7c \u0111\u1ecbnh \u0111\u1ec1u \u0111\u01b0\u1ee3c b\u1ea3o v\u1ec7. C\u1ea5u h\u00ecnh t\u00f9y ch\u1ec9nh ch\u1ec9 c\u1ea7n khi mu\u1ed1n <em>thay \u0111\u1ed5i<\/em> h\u00e0nh vi m\u1eb7c \u0111\u1ecbnh.<\/td><\/tr><tr><td><strong>Dependencies<\/strong><\/td><td>Ph\u1ea3i t\u1ef1 qu\u1ea3n l\u00fd c\u00e1c dependency li\u00ean quan v\u00e0 \u0111\u1ea3m b\u1ea3o t\u01b0\u01a1ng th\u00edch phi\u00ean b\u1ea3n.<\/td><td>Ch\u1ec9 c\u1ea7n m\u1ed9t dependency duy nh\u1ea5t: <code>spring-boot-starter-security<\/code>. Spring Boot s\u1ebd lo ph\u1ea7n c\u00f2n l\u1ea1i.<\/td><\/tr><tr><td><strong>H\u00e0nh vi m\u1eb7c \u0111\u1ecbnh<\/strong><\/td><td>Kh\u00f4ng c\u00f3 h\u00e0nh vi m\u1eb7c \u0111\u1ecbnh n\u00e0o. B\u1ea1n ph\u1ea3i t\u1ef1 \u0111\u1ecbnh ngh\u0129a m\u1ecdi th\u1ee9 t\u1eeb \u0111\u1ea7u: trang \u0111\u0103ng nh\u1eadp, c\u00e1ch x\u1eed l\u00fd, c\u00e1c URL c\u1ea7n b\u1ea3o v\u1ec7.<\/td><td>B\u1ea3o m\u1eadt ngay l\u1eadp t\u1ee9c: T\u1ef1 \u0111\u1ed9ng t\u1ea1o trang \u0111\u0103ng nh\u1eadp, b\u1ea3o v\u1ec7 t\u1ea5t c\u1ea3 c\u00e1c endpoint, b\u1eadt c\u00e1c t\u00ednh n\u0103ng ch\u1ed1ng t\u1ea5n c\u00f4ng ph\u1ed5 bi\u1ebfn (CSRF, XSS), t\u1ea1o m\u1ed9t user m\u1eb7c \u0111\u1ecbnh v\u1edbi m\u1eadt kh\u1ea9u ng\u1eabu nhi\u00ean in ra \u1edf console.<\/td><\/tr><tr><td><strong>Tri\u1ebft l\u00fd<\/strong><\/td><td>Cung c\u1ea5p c\u00e1c c\u00f4ng c\u1ee5 \u0111\u1ec3 b\u1ea1n x\u00e2y d\u1ef1ng h\u1ec7 th\u1ed1ng b\u1ea3o m\u1eadt t\u1eeb con s\u1ed1 kh\u00f4ng.<\/td><td>&#8220;\u01afu ti\u00ean quy \u01b0\u1edbc h\u01a1n c\u1ea5u h\u00ecnh&#8221; (Convention over Configuration): Cung c\u1ea5p m\u1ed9t h\u1ec7 th\u1ed1ng b\u1ea3o m\u1eadt ho\u1ea1t \u0111\u1ed9ng ngay l\u1eadp t\u1ee9c, b\u1ea1n ch\u1ec9 c\u1ea7n can thi\u1ec7p khi c\u00f3 nhu c\u1ea7u \u0111\u1eb7c bi\u1ec7t.<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-spring-boot-co-cac-tinh-nang-nao-c\u1ee7a-spring-security-nbsp\"><span class=\"ez-toc-section\" id=\"Spring_Boot_co_cac_tinh_nang_nao_cua_Spring_Security\"><\/span><strong>Spring Boot c\u00f3 c\u00e1c t\u00ednh n\u0103ng n\u00e0o c\u1ee7a Spring Security?&nbsp;<\/strong><span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>V\u1ec1 b\u1ea3n ch\u1ea5t, <strong>Spring Boot Security ch\u00ednh l\u00e0 Spring Security<\/strong>, nh\u01b0ng \u0111\u01b0\u1ee3c Spring Boot t\u1ef1 \u0111\u1ed9ng c\u1ea5u h\u00ecnh s\u1eb5n (auto-configuration). Thay v\u00ec ph\u1ea3i thi\u1ebft l\u1eadp m\u1ecdi th\u1ee9 t\u1eeb \u0111\u1ea7u, Spring Boot cung c\u1ea5p c\u00e1c c\u00e0i \u0111\u1eb7t b\u1ea3o m\u1eadt m\u1eb7c \u0111\u1ecbnh h\u1ee3p l\u00fd, gi\u00fap \u1ee9ng d\u1ee5ng c\u1ee7a b\u1ea1n an to\u00e0n ngay l\u1eadp t\u1ee9c.<\/p>\n\n\n\n<p>N\u00f3 s\u1edf h\u1eefu to\u00e0n b\u1ed9 c\u00e1c t\u00ednh n\u0103ng m\u1ea1nh m\u1ebd c\u1ee7a Spring Security, bao g\u1ed3m:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>X\u00e1c th\u1ef1c (Authentication):<\/strong> H\u1ed7 tr\u1ee3 \u0111a d\u1ea1ng c\u00e1c h\u00ecnh th\u1ee9c t\u1eeb form \u0111\u0103ng nh\u1eadp, k\u1ebft n\u1ed1i c\u01a1 s\u1edf d\u1eef li\u1ec7u, cho \u0111\u1ebfn t\u00edch h\u1ee3p v\u1edbi c\u00e1c nh\u00e0 cung c\u1ea5p OAuth2 nh\u01b0 Google, Facebook.<\/li>\n\n\n\n<li><strong>Ph\u00e2n quy\u1ec1n (Authorization):<\/strong> Cho ph\u00e9p gi\u1edbi h\u1ea1n quy\u1ec1n truy c\u1eadp linh ho\u1ea1t d\u1ef1a tr\u00ean vai tr\u00f2 ng\u01b0\u1eddi d\u00f9ng (roles), \u0111\u01b0\u1eddng d\u1eabn (URL), ho\u1eb7c th\u1eadm ch\u00ed \u1edf c\u1ea5p \u0111\u1ed9 ph\u01b0\u01a1ng th\u1ee9c (method-level).<\/li>\n\n\n\n<li><strong>Ch\u1ed1ng t\u1ea5n c\u00f4ng ph\u1ed5 bi\u1ebfn:<\/strong> T\u1ef1 \u0111\u1ed9ng t\u00edch h\u1ee3p s\u1eb5n c\u01a1 ch\u1ebf b\u1ea3o v\u1ec7 ch\u1ed1ng l\u1ea1i c\u00e1c l\u1ed7 h\u1ed5ng nh\u01b0 CSRF (Cross-Site Request Forgery), Session Fixation, v\u00e0 Clickjacking.<\/li>\n\n\n\n<li><strong>M\u00e3 h\u00f3a m\u1eadt kh\u1ea9u:<\/strong> B\u1eaft bu\u1ed9c s\u1eed d\u1ee5ng c\u00e1c thu\u1eadt to\u00e1n m\u00e3 h\u00f3a m\u1ea1nh v\u00e0 hi\u1ec7n \u0111\u1ea1i nh\u01b0 BCrypt \u0111\u1ec3 l\u01b0u tr\u1eef m\u1eadt kh\u1ea9u an to\u00e0n.<\/li>\n<\/ul>\n\n\n\n<p><strong>T\u00f3m l\u1ea1i:<\/strong> Khi s\u1eed d\u1ee5ng Spring Boot Security, b\u1ea1n nh\u1eadn \u0111\u01b0\u1ee3c to\u00e0n b\u1ed9 s\u1ee9c m\u1ea1nh c\u1ee7a Spring Security nh\u01b0ng v\u1edbi \u00edt c\u00f4ng s\u1ee9c c\u1ea5u h\u00ecnh h\u01a1n r\u1ea5t nhi\u1ec1u, gi\u00fap \u0111\u1ea9y nhanh t\u1ed1c \u0111\u1ed9 ph\u00e1t tri\u1ec3n.&nbsp;<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-cac-khai-ni\u1ec7m-quan-tr\u1ecdng-c\u1ee7a-spring-boot-security\"><span class=\"ez-toc-section\" id=\"Cac_khai_niem_quan_trong_cua_Spring_Boot_Security\"><\/span><strong>C\u00e1c kh\u00e1i ni\u1ec7m quan tr\u1ecdng c\u1ee7a Spring Boot Security<\/strong><span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-c\u01a1-ch\u1ebf-t\u1ef1-d\u1ed9ng-c\u1ea5u-hinh-auto-configuration\"><strong>C\u01a1 ch\u1ebf t\u1ef1 \u0111\u1ed9ng c\u1ea5u h\u00ecnh (auto-configuration)<\/strong><\/h3>\n\n\n\n<p>Khi b\u1ea1n t\u00edch h\u1ee3p Spring Boot Security v\u00e0o d\u1ef1 \u00e1n, b\u1ea1n ch\u1ec9 c\u1ea7n khai b\u00e1o m\u1ed9t dependency duy nh\u1ea5t l\u00e0 <strong><code>spring-boot-starter-security<\/code><\/strong>. Ngay l\u1eadp t\u1ee9c, Spring Boot s\u1ebd k\u00edch ho\u1ea1t c\u01a1 ch\u1ebf <strong>t\u1ef1 \u0111\u1ed9ng c\u1ea5u h\u00ecnh (auto-configuration)<\/strong>.<\/p>\n\n\n\n<p>C\u01a1 ch\u1ebf n\u00e0y s\u1ebd:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>B\u1ea3o v\u1ec7 t\u1ea5t c\u1ea3 c\u00e1c endpoint<\/strong>: M\u1ecdi y\u00eau c\u1ea7u HTTP \u0111\u1ebfn \u1ee9ng d\u1ee5ng c\u1ee7a b\u1ea1n s\u1ebd m\u1eb7c \u0111\u1ecbnh y\u00eau c\u1ea7u x\u00e1c th\u1ef1c.<\/li>\n\n\n\n<li><strong>T\u1ea1o Form \u0110\u0103ng nh\u1eadp<\/strong>: T\u1ef1 \u0111\u1ed9ng sinh ra m\u1ed9t trang \u0111\u0103ng nh\u1eadp (\/login) cho ng\u01b0\u1eddi d\u00f9ng.<\/li>\n\n\n\n<li><strong>K\u00edch ho\u1ea1t Basic Authentication<\/strong>: H\u1ed7 tr\u1ee3 x\u00e1c th\u1ef1c qua HTTP Basic Auth cho c\u00e1c client kh\u00f4ng d\u00f9ng tr\u00ecnh duy\u1ec7t.<\/li>\n\n\n\n<li><strong>T\u1ea1o m\u1ed9t ng\u01b0\u1eddi d\u00f9ng m\u1eb7c \u0111\u1ecbnh<\/strong>: M\u1ed9t user t\u00ean l\u00e0 user s\u1ebd \u0111\u01b0\u1ee3c t\u1ea1o v\u1edbi m\u1ed9t m\u1eadt kh\u1ea9u ng\u1eabu nhi\u00ean duy nh\u1ea5t \u0111\u01b0\u1ee3c in ra trong console l\u00fac kh\u1edfi \u0111\u1ed9ng \u1ee9ng d\u1ee5ng.<\/li>\n\n\n\n<li><strong>B\u1ea3o v\u1ec7 ch\u1ed1ng l\u1ea1i c\u00e1c t\u1ea5n c\u00f4ng ph\u1ed5 bi\u1ebfn<\/strong>: C\u00e1c t\u00ednh n\u0103ng nh\u01b0 CSRF (Cross-Site Request Forgery) \u0111\u01b0\u1ee3c b\u1eadt m\u1eb7c \u0111\u1ecbnh.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-tuy-ch\u1ec9nh-c\u1ea5u-hinh-b\u1ea3o-m\u1eadt\"><strong>T\u00f9y ch\u1ec9nh C\u1ea5u h\u00ecnh B\u1ea3o m\u1eadt<\/strong><\/h3>\n\n\n\n<p>\u0110\u1ec3 thay \u0111\u1ed5i c\u00e1c h\u00e0nh vi m\u1eb7c \u0111\u1ecbnh tr\u00ean, ch\u00fang ta c\u1ea7n \u0111\u1ecbnh ngh\u0129a c\u1ea5u h\u00ecnh c\u1ee7a ri\u00eang m\u00ecnh. C\u00f3 2 c\u00e1ch \u0111\u1ec3 t\u00f9y ch\u1ec9nh c\u1ea5u h\u00ecnh b\u1ea3o m\u1eadt nh\u01b0 sau:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>C\u00e1ch c\u0169 (<code>WebSecurityConfigurerAdapter<\/code>)<\/strong>: Tr\u01b0\u1edbc \u0111\u00e2y, ng\u01b0\u1eddi d\u00f9ng th\u01b0\u1eddng k\u1ebf th\u1eeba l\u1edbp n\u00e0y v\u00e0 ghi \u0111\u00e8 c\u00e1c ph\u01b0\u01a1ng th\u1ee9c c\u1ee7a n\u00f3. C\u00e1ch n\u00e0y \u0111\u00e3 b\u1ecb <strong>deprecated (kh\u00f4ng d\u00f9ng n\u1eefa)<\/strong> t\u1eeb Spring Security 5.7.0 v\u00e0 b\u1ea1n n\u00ean tr\u00e1nh s\u1eed d\u1ee5ng.<\/li>\n\n\n\n<li><strong>C\u00e1ch m\u1edbi (<code>SecurityFilterChain<\/code> Bean)<\/strong>: \u0110\u00e2y l\u00e0 c\u00e1ch ti\u1ebfp c\u1eadn hi\u1ec7n \u0111\u1ea1i v\u00e0 \u0111\u01b0\u1ee3c khuy\u1ebfn kh\u00edch. B\u1ea1n s\u1ebd t\u1ea1o m\u1ed9t <code>@Bean<\/code> tr\u1ea3 v\u1ec1 m\u1ed9t \u0111\u1ed1i t\u01b0\u1ee3ng <code>SecurityFilterChain<\/code>. B\u00ean trong bean n\u00e0y, b\u1ea1n s\u1eed d\u1ee5ng \u0111\u1ed1i t\u01b0\u1ee3ng <code>HttpSecurity<\/code> \u0111\u1ec3 x\u00e2y d\u1ef1ng chu\u1ed7i quy t\u1eafc b\u1ea3o m\u1eadt c\u1ee7a m\u00ecnh. C\u00e1ch n\u00e0y linh ho\u1ea1t v\u00e0 ph\u00f9 h\u1ee3p v\u1edbi ki\u1ebfn tr\u00fac d\u1ef1a tr\u00ean component c\u1ee7a Spring.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-xac-th\u1ef1c-trong-b\u1ed9-nh\u1edb-in-memory-authentication\"><strong>X\u00e1c th\u1ef1c trong b\u1ed9 nh\u1edb (In-memory Authentication)<\/strong><\/h3>\n\n\n\n<p>\u0110\u00e2y l\u00e0 c\u00e1ch \u0111\u01a1n gi\u1ea3n nh\u1ea5t \u0111\u1ec3 cung c\u1ea5p th\u00f4ng tin ng\u01b0\u1eddi d\u00f9ng cho m\u1ee5c \u0111\u00edch ph\u00e1t tri\u1ec3n ho\u1eb7c cho c\u00e1c \u1ee9ng d\u1ee5ng nh\u1ecf. Thay v\u00ec k\u1ebft n\u1ed1i v\u1edbi c\u01a1 s\u1edf d\u1eef li\u1ec7u, b\u1ea1n \u0111\u1ecbnh ngh\u0129a th\u1eb3ng danh s\u00e1ch ng\u01b0\u1eddi d\u00f9ng, m\u1eadt kh\u1ea9u v\u00e0 vai tr\u00f2 c\u1ee7a h\u1ecd ngay trong m\u00e3 ngu\u1ed3n.<\/p>\n\n\n\n<p>\u0110\u1ec3 th\u1ef1c hi\u1ec7n \u0111\u01b0\u1ee3c c\u01a1 ch\u1ebf n\u00e0y, Spring Security d\u1ef1a tr\u00ean hai interface c\u1ed1t l\u00f5i sau:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong><code>UserDetailsService<\/code><\/strong>: L\u00e0 m\u1ed9t interface c\u1ed1t l\u00f5i trong Spring Security, c\u00f3 nhi\u1ec7m v\u1ee5 t\u1ea3i th\u00f4ng tin ng\u01b0\u1eddi d\u00f9ng d\u1ef1a tr\u00ean username.<\/li>\n\n\n\n<li><strong><code>UserDetails<\/code><\/strong>: L\u00e0 m\u1ed9t interface kh\u00e1c, ch\u1ee9a c\u00e1c th\u00f4ng tin c\u1ea7n thi\u1ebft c\u1ee7a m\u1ed9t ng\u01b0\u1eddi d\u00f9ng (username, password, authorities &#8211; quy\u1ec1n h\u1ea1n).<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-ma-hoa-m\u1eadt-kh\u1ea9u-password-encoding\"><strong>M\u00e3 h\u00f3a M\u1eadt kh\u1ea9u (Password Encoding)&nbsp;<\/strong><\/h3>\n\n\n\n<p>Nguy\u00ean t\u1eafc v\u00e0ng \u0111\u1ec3 b\u1ea3o m\u1eadt m\u1eadt kh\u1ea9u \u0111\u00f3 l\u00e0: Kh\u00f4ng bao gi\u1edd l\u01b0u tr\u1eef m\u1eadt kh\u1ea9u d\u01b0\u1edbi d\u1ea1ng v\u0103n b\u1ea3n thu\u1ea7n t\u00fay (plain text). M\u1eadt kh\u1ea9u ph\u1ea3i lu\u00f4n \u0111\u01b0\u1ee3c &#8220;b\u0103m&#8221; (hashed) b\u1eb1ng m\u1ed9t thu\u1eadt to\u00e1n m\u1ea1nh, m\u1ed9t chi\u1ec1u.<\/p>\n\n\n\n<p>\u0110\u1ec3 hi\u1ec7n th\u1ef1c h\u00f3a nguy\u00ean t\u1eafc n\u00e0y, Spring Security cung c\u1ea5p interface <strong>PasswordEncoder <\/strong>\u0111\u1ec3 x\u1eed l\u00fd vi\u1ec7c m\u00e3 h\u00f3a v\u00e0 so s\u00e1nh m\u1eadt kh\u1ea9u.<\/p>\n\n\n\n<p>Trong \u0111\u00f3, <strong>BCryptPasswordEncoder<\/strong> l\u00e0 m\u1ed9t trong nh\u1eefng c\u00e0i \u0111\u1eb7t ph\u1ed5 bi\u1ebfn v\u00e0 an to\u00e0n nh\u1ea5t c\u1ee7a PasswordEncoder. BCrypt l\u00e0 m\u1ed9t thu\u1eadt to\u00e1n b\u0103m m\u1eadt kh\u1ea9u th\u00edch \u1ee9ng, t\u1ef1 \u0111\u1ed9ng t\u00edch h\u1ee3p &#8220;salt&#8221; \u0111\u1ec3 ch\u1ed1ng l\u1ea1i c\u00e1c cu\u1ed9c t\u1ea5n c\u00f4ng b\u1ea3ng c\u1ea7u v\u1ed3ng (rainbow table attacks).<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-xac-th\u1ef1c-authentication\"><strong>X\u00e1c th\u1ef1c (Authentication)<\/strong><\/h3>\n\n\n\n<p>Trong Spring Boot Security, c\u00f3 nhi\u1ec1u ph\u01b0\u01a1ng th\u1ee9c x\u00e1c th\u1ef1c kh\u00e1c nhau, m\u1ed7i lo\u1ea1i ph\u00f9 h\u1ee3p v\u1edbi c\u00e1c y\u00eau c\u1ea7u v\u00e0 ki\u1ebfn tr\u00fac \u1ee9ng d\u1ee5ng web hi\u1ec7n \u0111\u1ea1i. D\u01b0\u1edbi \u0111\u00e2y l\u00e0 m\u1ed9t s\u1ed1 ph\u01b0\u01a1ng th\u1ee9c ph\u1ed5 bi\u1ebfn:<\/p>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"h-form-based-authentication-xac-th\u1ef1c-qua-form\"><strong>Form-Based Authentication (X\u00e1c th\u1ef1c qua Form)<\/strong><\/h4>\n\n\n\n<p>\u0110\u00e2y l\u00e0 ph\u01b0\u01a1ng th\u1ee9c \u0111\u0103ng nh\u1eadp <strong>username\/m\u1eadt kh\u1ea9u<\/strong> kinh \u0111i\u1ec3n cho c\u00e1c \u1ee9ng d\u1ee5ng web truy\u1ec1n th\u1ed1ng. Ph\u01b0\u01a1ng th\u1ee9c n\u00e0y ph\u00f9 h\u1ee3p nh\u1ea5t cho c\u00e1c \u1ee9ng d\u1ee5ng web c\u00f3 qu\u1ea3n l\u00fd session ph\u00eda m\u00e1y ch\u1ee7.<\/p>\n\n\n\n<p>Spring Boot Security cho ph\u00e9p b\u1ea1n d\u1ec5 d\u00e0ng t\u00f9y ch\u1ec9nh trang \u0111\u0103ng nh\u1eadp v\u00e0 ki\u1ec3m so\u00e1t logic sau khi ng\u01b0\u1eddi d\u00f9ng \u0111\u0103ng nh\u1eadp th\u00e0nh c\u00f4ng ho\u1eb7c th\u1ea5t b\u1ea1i.&nbsp;<\/p>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"h-jdbc-based-authentication-xac-th\u1ef1c-qua-database\"><strong>JDBC-Based Authentication (X\u00e1c th\u1ef1c qua Database)<\/strong><\/h4>\n\n\n\n<p>\u0110\u00e2y l\u00e0 ph\u01b0\u01a1ng th\u1ee9c s\u1eed d\u1ee5ng th\u00f4ng tin ng\u01b0\u1eddi d\u00f9ng \u0111\u01b0\u1ee3c <strong>l\u01b0u tr\u1eef trong c\u01a1 s\u1edf d\u1eef li\u1ec7u<\/strong> \u0111\u1ec3 x\u00e1c th\u1ef1c danh t\u00ednh.<\/p>\n\n\n\n<p>Tr\u01b0\u1eddng h\u1ee3p c\u1ea7n s\u1eed d\u1ee5ng:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Khi b\u1ea1n c\u1ea7n qu\u1ea3n l\u00fd ng\u01b0\u1eddi d\u00f9ng m\u1ed9t c\u00e1ch <strong>\u0111\u1ed9ng<\/strong>, ngh\u0129a l\u00e0 c\u00f3 kh\u1ea3 n\u0103ng th\u00eam, s\u1eeda, x\u00f3a ng\u01b0\u1eddi d\u00f9ng th\u00f4ng qua giao di\u1ec7n qu\u1ea3n tr\u1ecb c\u1ee7a \u1ee9ng d\u1ee5ng.<\/li>\n\n\n\n<li>Khi \u1ee9ng d\u1ee5ng c\u1ee7a b\u1ea1n c\u1ea7n t\u00edch h\u1ee3p v\u1edbi m\u1ed9t h\u1ec7 th\u1ed1ng qu\u1ea3n l\u00fd ng\u01b0\u1eddi d\u00f9ng hi\u1ec7n c\u00f3 \u0111\u00e3 l\u01b0u tr\u1eef trong database.<\/li>\n\n\n\n<li>Ph\u00f9 h\u1ee3p cho h\u1ea7u h\u1ebft c\u00e1c \u1ee9ng d\u1ee5ng web truy\u1ec1n th\u1ed1ng ho\u1eb7c \u1ee9ng d\u1ee5ng c\u1ea7n m\u1ed9t h\u1ec7 th\u1ed1ng qu\u1ea3n l\u00fd ng\u01b0\u1eddi d\u00f9ng t\u1eadp trung.<\/li>\n<\/ul>\n\n\n\n<p>C\u00e1ch l\u00e0m:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>C\u1ea5u h\u00ecnh DataSource cho database.<\/li>\n\n\n\n<li>T\u1ea1o UserDetailsService t\u00f9y ch\u1ec9nh \u0111\u1ec3 truy v\u1ea5n th\u00f4ng tin ng\u01b0\u1eddi d\u00f9ng t\u1eeb DB.<\/li>\n\n\n\n<li>S\u1eed d\u1ee5ng PasswordEncoder \u0111\u1ec3 m\u00e3 h\u00f3a v\u00e0 so s\u00e1nh m\u1eadt kh\u1ea9u.<\/li>\n<\/ul>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"h-jwt-json-web-tokens-authentication-xac-th\u1ef1c-b\u1eb1ng-jwt\"><strong>JWT (JSON Web Tokens) Authentication (X\u00e1c th\u1ef1c b\u1eb1ng JWT)<\/strong><\/h4>\n\n\n\n<p>\u0110\u00e2y l\u00e0 ph\u01b0\u01a1ng th\u1ee9c x\u00e1c th\u1ef1c phi tr\u1ea1ng th\u00e1i b\u1eb1ng c\u00e1ch truy\u1ec1n t\u1ea3i token ch\u1ee9a th\u00f4ng tin an to\u00e0n gi\u1eefa client v\u00e0 server.<\/p>\n\n\n\n<p>C\u00e1ch n\u00e0y l\u00fd t\u01b0\u1edfng cho RESTful API, Microservices, Single Page Application (SPA), Mobile Apps (server kh\u00f4ng l\u01b0u session).<\/p>\n\n\n\n<p><strong>C\u00e1ch l\u00e0m:<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Client \u0111\u0103ng nh\u1eadp, server tr\u1ea3 v\u1ec1 JWT.<\/li>\n\n\n\n<li>Client g\u1eedi JWT trong header Authorization cho c\u00e1c request ti\u1ebfp theo.<\/li>\n\n\n\n<li>Server d\u00f9ng b\u1ed9 l\u1ecdc \u0111\u1ec3 gi\u1ea3i m\u00e3 v\u00e0 x\u00e1c th\u1ef1c JWT.<\/li>\n<\/ul>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"h-oauth-2-0-amp-openid-connect-oidc\"><strong>OAuth 2.0 &amp; OpenID Connect (OIDC)<\/strong><\/h4>\n\n\n\n<p>Ph\u01b0\u01a1ng th\u1ee9c n\u00e0y cho ph\u00e9p ng\u01b0\u1eddi d\u00f9ng \u0111\u0103ng nh\u1eadp v\u00e0o \u1ee9ng d\u1ee5ng c\u1ee7a b\u1ea1n th\u00f4ng qua m\u1ed9t <strong>nh\u00e0 cung c\u1ea5p th\u1ee9 ba<\/strong> nh\u01b0 Google, Facebook, hay GitHub (v\u00ed d\u1ee5: n\u00fat &#8220;Login with Google&#8221;). C\u00e1ch n\u00e0y c\u00f3 l\u1ee3i \u00edch l\u00e0 t\u0103ng s\u1ef1 ti\u1ec7n l\u1ee3i cho ng\u01b0\u1eddi d\u00f9ng v\u00e0 gi\u1ea3m g\u00e1nh n\u1eb7ng qu\u1ea3n l\u00fd m\u1eadt kh\u1ea9u.<\/p>\n\n\n\n<p><strong>C\u00e1ch l\u00e0m: <\/strong>Th\u00eam spring-boot-starter-oauth2-client v\u00e0 c\u1ea5u h\u00ecnh Client ID, Client Secret trong application.properties.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"h-so-sanh-xac-th\u1ef1c-trong-spring-security-vs-spring-boot-security\"><strong>So s\u00e1nh x\u00e1c th\u1ef1c trong Spring Security vs Spring Boot Security<\/strong><\/h4>\n\n\n\n<p>\u0110\u1ec3 c\u00f3 th\u1ec3 nh\u00ecn th\u1ea5y r\u00f5 nh\u01b0ng kh\u00e1c bi\u1ec7t trong c\u00e1ch tri\u1ec3n khai x\u00e1c th\u1ef1c gi\u1eefa Spring Security v\u00e0 Spring Boot Security, ta c\u00f3 b\u1ea3ng sau:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><td><strong>Ph\u01b0\u01a1ng th\u1ee9c X\u00e1c th\u1ef1c<\/strong><\/td><td><strong>Spring Security (Truy\u1ec1n th\u1ed1ng)<\/strong><\/td><td><strong>Spring Boot Security (Kh\u00e1c bi\u1ec7t ch\u00ednh )<\/strong><\/td><\/tr><tr><td><strong>Form-Based<\/strong><\/td><td><strong>C\u1ea5u h\u00ecnh th\u1ee7 c\u00f4ng to\u00e0n b\u1ed9<\/strong>: Ph\u1ea3i t\u1ef1 \u0111\u1ecbnh ngh\u0129a t\u01b0\u1eddng minh m\u1ecdi th\u1ee9 nh\u01b0 trang \u0111\u0103ng nh\u1eadp, URL x\u1eed l\u00fd, c\u00e1c handler&#8230;<\/td><td><strong>T\u1ef1 \u0111\u1ed9ng h\u00f3a<\/strong>: Cung c\u1ea5p s\u1eb5n form \u0111\u0103ng nh\u1eadp v\u00e0 endpoint. B\u1ea1n ch\u1ec9 c\u1ea7n vi\u1ebft code \u0111\u1ec3 <em>t\u00f9y ch\u1ec9nh<\/em> l\u1ea1i h\u00e0nh vi m\u1eb7c \u0111\u1ecbnh.<\/td><\/tr><tr><td>JDBC-Based<\/td><td><strong>C\u1ea5u h\u00ecnh <code>DataSource <\/code>th\u1ee7 c\u00f4ng<\/strong>: Ph\u1ea3i t\u1ef1 t\u1ea1o bean <code>DataSource<\/code> v\u00e0 k\u1ebft n\u1ed1i n\u00f3 v\u00e0o <code>UserDetailsService<\/code>.<\/td><td><strong>T\u1ef1 \u0111\u1ed9ng c\u1ea5u h\u00ecnh <code>DataSource<\/code><\/strong>: Ch\u1ec9 c\u1ea7n khai b\u00e1o trong file <code>application.properties<\/code>, Spring Boot t\u1ef1 \u0111\u1ed9ng t\u1ea1o bean v\u00e0 t\u00edch h\u1ee3p.<\/td><\/tr><tr><td>JWT<\/td><td><strong>T\u00edch h\u1ee3p th\u1ee7 c\u00f4ng<\/strong>: Logic c\u1ed1t l\u00f5i gi\u1ed1ng nhau, nh\u01b0ng vi\u1ec7c \u0111\u0103ng k\u00fd v\u00e0 t\u00edch h\u1ee3p filter v\u00e0o chu\u1ed7i b\u1ea3o m\u1eadt ph\u1ee9c t\u1ea1p h\u01a1n.<\/td><td><strong>T\u00edch h\u1ee3p d\u1ec5 d\u00e0ng h\u01a1n<\/strong>: Vi\u1ec7c \u0111\u0103ng k\u00fd filter t\u00f9y ch\u1ec9nh \u0111\u01a1n gi\u1ea3n h\u01a1n nh\u1edd c\u01a1 ch\u1ebf component scanning (@Component).<\/td><\/tr><tr><td>OAuth 2.0 \/ OIDC<\/td><td><strong>C\u1ef1c k\u1ef3 ph\u1ee9c t\u1ea1p<\/strong>: Y\u00eau c\u1ea7u c\u1ea5u h\u00ecnh Java d\u00e0i d\u00f2ng v\u1edbi nhi\u1ec1u bean \u0111\u01b0\u1ee3c \u0111\u1ecbnh ngh\u0129a th\u1ee7 c\u00f4ng (<code>ClientRegistrationRepository<\/code>,&#8230;)<\/td><td><strong>C\u1ef1c k\u1ef3 \u0111\u01a1n gi\u1ea3n<\/strong>: Ch\u1ec9 c\u1ea7n th\u00eam starter v\u00e0 v\u00e0i d\u00f2ng c\u1ea5u h\u00ecnh trong <code>application.properties<\/code>. M\u1ecdi th\u1ee9 \u0111\u01b0\u1ee3c t\u1ef1 \u0111\u1ed9ng c\u1ea5u h\u00ecnh.<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-\u1ee7y-quy\u1ec1n-trong-spring-boot-security\"><span class=\"ez-toc-section\" id=\"Uy_quyen_trong_Spring_Boot_security\"><\/span><strong>\u1ee6y quy\u1ec1n trong Spring Boot security<\/strong><span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>\u1ee6y quy\u1ec1n (Authorization) trong Spring Boot Security l\u00e0 qu\u00e1 tr\u00ecnh x\u00e1c \u0111\u1ecbnh ng\u01b0\u1eddi d\u00f9ng \u0111\u00e3 \u0111\u01b0\u1ee3c x\u00e1c th\u1ef1c c\u00f3 quy\u1ec1n truy c\u1eadp v\u00e0o m\u1ed9t t\u00e0i nguy\u00ean c\u1ee5 th\u1ec3 hay kh\u00f4ng. C\u00e1c c\u00e1ch \u1ee7y quy\u1ec1n ch\u00ednh:<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-\u1ee7y-quy\u1ec1n-d\u1ef1a-tren-vai-tro-role-based\"><strong>\u1ee6y quy\u1ec1n d\u1ef1a tr\u00ean vai tr\u00f2 (Role-Based)<\/strong><\/h3>\n\n\n\n<p>\u0110\u00e2y l\u00e0 c\u00e1ch ti\u1ebfp c\u1eadn ph\u1ed5 bi\u1ebfn nh\u1ea5t, trong \u0111\u00f3 quy\u1ec1n truy c\u1eadp \u0111\u01b0\u1ee3c c\u1ea5p d\u1ef1a tr\u00ean vai tr\u00f2 c\u1ee7a ng\u01b0\u1eddi d\u00f9ng (v\u00ed d\u1ee5: <code>ADMIN<\/code>, <code>USER<\/code>, <code>MANAGER<\/code>).<\/p>\n\n\n\n<p>Trong c\u1ea5u h\u00ecnh <code>HttpSecurity<\/code>, b\u1ea1n s\u1eed d\u1ee5ng c\u00e1c ph\u01b0\u01a1ng th\u1ee9c <strong><code>hasRole()<\/code><\/strong> (y\u00eau c\u1ea7u m\u1ed9t vai tr\u00f2 c\u1ee5 th\u1ec3) v\u00e0 <strong><code>hasAnyRole()<\/code><\/strong> (y\u00eau c\u1ea7u m\u1ed9t trong nhi\u1ec1u vai tr\u00f2).<\/p>\n\n\n\n<p>D\u01b0\u1edbi \u0111\u00e2y l\u00e0 1 v\u00ed d\u1ee5 v\u1ec1 c\u00e1c tri\u1ec3n khai \u1ee7y quy\u1ec1n Role-Based:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>@Bean\npublic SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {\n    http.authorizeHttpRequests(authorize -&gt; authorize\n        \/\/ Ch\u1ec9 ng\u01b0\u1eddi d\u00f9ng c\u00f3 vai tr\u00f2 'ADMIN' m\u1edbi \u0111\u01b0\u1ee3c truy c\u1eadp c\u00e1c URL b\u1eaft \u0111\u1ea7u b\u1eb1ng \/admin\/\n        .requestMatchers(\"\/admin\/**\").hasRole(\"ADMIN\")\n        \n        \/\/ C\u1ea3 'ADMIN' v\u00e0 'USER' \u0111\u1ec1u c\u00f3 th\u1ec3 truy c\u1eadp \/dashboard\n        .requestMatchers(\"\/dashboard\").hasAnyRole(\"ADMIN\", \"USER\")\n        \n        \/\/ M\u1ecdi ng\u01b0\u1eddi \u0111\u1ec1u c\u00f3 th\u1ec3 truy c\u1eadp trang ch\u1ee7\n        .requestMatchers(\"\/\").permitAll()\n        \n        \/\/ B\u1ea5t k\u1ef3 y\u00eau c\u1ea7u n\u00e0o kh\u00e1c \u0111\u1ec1u c\u1ea7n x\u00e1c th\u1ef1c\n        .anyRequest().authenticated()\n    );\n    \/\/ ... c\u00e1c c\u1ea5u h\u00ecnh kh\u00e1c\n    return http.build();\n}<\/code><\/pre>\n\n\n\n<p><strong>L\u01b0u \u00fd quan tr\u1ecdng:<\/strong> Spring Security t\u1ef1 \u0111\u1ed9ng th\u00eam ti\u1ec1n t\u1ed1 <code><strong>ROLE_<\/strong> <\/code>v\u00e0o gi\u00e1 tr\u1ecb b\u1ea1n cung c\u1ea5p. V\u00ed d\u1ee5, n\u1ebfu vai tr\u00f2 trong CSDL c\u1ee7a b\u1ea1n l\u00e0 <code>ADMIN<\/code>, b\u1ea1n s\u1ebd ki\u1ec3m tra v\u1edbi <code>hasRole('ADMIN')<\/code> nh\u01b0 sau:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>@Bean\npublic SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {\n    http.authorizeHttpRequests(authorize -&gt; authorize\n        \/\/ Ch\u1ec9 ng\u01b0\u1eddi d\u00f9ng c\u00f3 vai tr\u00f2 'ADMIN' m\u1edbi \u0111\u01b0\u1ee3c truy c\u1eadp c\u00e1c URL b\u1eaft \u0111\u1ea7u b\u1eb1ng \/admin\/\n        .requestMatchers(\"\/admin\/**\").hasRole(\"ADMIN\")\n        \n        \/\/ C\u1ea3 'ADMIN' v\u00e0 'USER' \u0111\u1ec1u c\u00f3 th\u1ec3 truy c\u1eadp \/dashboard\n        .requestMatchers(\"\/dashboard\").hasAnyRole(\"ADMIN\", \"USER\")\n        \n        \/\/ M\u1ecdi ng\u01b0\u1eddi \u0111\u1ec1u c\u00f3 th\u1ec3 truy c\u1eadp trang ch\u1ee7\n        .requestMatchers(\"\/\").permitAll()\n        \n        \/\/ B\u1ea5t k\u1ef3 y\u00eau c\u1ea7u n\u00e0o kh\u00e1c \u0111\u1ec1u c\u1ea7n x\u00e1c th\u1ef1c\n        .anyRequest().authenticated()\n    );\n    \/\/ ... c\u00e1c c\u1ea5u h\u00ecnh kh\u00e1c\n    return http.build();\n}<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-\u1ee7y-quy\u1ec1n-d\u1ef1a-tren-quy\u1ec1n-h\u1ea1n-authority-based-nbsp\"><strong>\u1ee6y quy\u1ec1n d\u1ef1a tr\u00ean quy\u1ec1n h\u1ea1n (Authority-Based)&nbsp;<\/strong><\/h3>\n\n\n\n<p>Ph\u01b0\u01a1ng ph\u00e1p n\u00e0y cung c\u1ea5p s\u1ef1 ki\u1ec3m so\u00e1t chi ti\u1ebft h\u01a1n so v\u1edbi \u1ee7y quy\u1ec1n d\u1ef1a tr\u00ean vai tr\u00f2.<\/p>\n\n\n\n<p><strong>Ph\u00e2n bi\u1ec7t Role v\u00e0 Authority:<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Role (Vai tr\u00f2):<\/strong> Th\u01b0\u1eddng l\u00e0 m\u1ed9t nh\u00f3m c\u00e1c quy\u1ec1n. V\u00ed d\u1ee5: vai tr\u00f2 ROLE_EDITOR.<\/li>\n\n\n\n<li><strong>Authority (Quy\u1ec1n h\u1ea1n):<\/strong> L\u00e0 m\u1ed9t quy\u1ec1n h\u1ea1n c\u1ee5 th\u1ec3, \u0111\u01a1n l\u1ebb. V\u00ed d\u1ee5: product:read, product:write. M\u1ed9t ROLE_EDITOR c\u00f3 th\u1ec3 bao g\u1ed3m c\u1ea3 hai quy\u1ec1n n\u00e0y.<\/li>\n<\/ul>\n\n\n\n<p>Khi s\u1eed d\u1ee5ng c\u00e1c ph\u01b0\u01a1ng th\u1ee9c <strong>hasAuthority()<\/strong> ho\u1eb7c <strong>hasAnyAuthority()<\/strong>, Spring Security s\u1ebd so kh\u1edbp ch\u00ednh x\u00e1c gi\u00e1 tr\u1ecb b\u1ea1n cung c\u1ea5p m\u00e0 <strong>kh\u00f4ng<\/strong> t\u1ef1 \u0111\u1ed9ng th\u00eam ti\u1ec1n t\u1ed1 ROLE_.<\/p>\n\n\n\n<p><strong>C\u00e1ch l\u00e0m<\/strong>: S\u1eed d\u1ee5ng c\u00e1c ph\u01b0\u01a1ng th\u1ee9c hasAuthority() ho\u1eb7c hasAnyAuthority() trong c\u1ea5u h\u00ecnh b\u1ea3o m\u1eadt. L\u01b0u \u00fd Spring Security kh\u00f4ng t\u1ef1 \u0111\u1ed9ng th\u00eam ti\u1ec1n t\u1ed1 ROLE_ v\u1edbi hasAuthority().<\/p>\n\n\n\n<p><strong>V\u00ed d\u1ee5:<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>@Bean\npublic SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {\n    http.authorizeHttpRequests(authorize -&gt; authorize\n        \/\/ Y\u00eau c\u1ea7u quy\u1ec1n 'product:delete' c\u1ee5 th\u1ec3\n        .requestMatchers(\"\/products\/delete\/**\").hasAuthority(\"product:delete\")\n        \n        \/\/ \u0110\u1ec3 ki\u1ec3m tra vai tr\u00f2 ADMIN b\u1eb1ng authority, b\u1ea1n ph\u1ea3i cung c\u1ea5p c\u1ea3 ti\u1ec1n t\u1ed1\n        .requestMatchers(\"\/admin\/**\").hasAuthority(\"ROLE_ADMIN\")\n        \n        .anyRequest().authenticated()\n    );\n    return http.build();\n}<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-h\u01b0\u1edbng-d\u1eabn-cai-d\u1eb7t-c\u1ea5u-hinh-va-lam-vi\u1ec7c-v\u1edbi-spring-boot-security\"><span class=\"ez-toc-section\" id=\"Huong_dan_cai_dat_cau_hinh_va_lam_viec_voi_Spring_Boot_security\"><\/span><strong>H\u01b0\u1edbng d\u1eabn c\u00e0i \u0111\u1eb7t c\u1ea5u h\u00ecnh v\u00e0 l\u00e0m vi\u1ec7c v\u1edbi Spring Boot security<\/strong><span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-them-dependency-maven\"><strong>Th\u00eam Dependency (Maven)<\/strong><\/h3>\n\n\n\n<p>\u0110\u00e2y l\u00e0 b\u01b0\u1edbc \u0111\u1ea7u ti\u00ean v\u00e0 b\u1eaft bu\u1ed9c, gi\u00fap b\u1ea1n t\u00edch h\u1ee3p th\u01b0 vi\u1ec7n Spring Security v\u00e0o d\u1ef1 \u00e1n, l\u00e0 n\u1ec1n t\u1ea3ng \u0111\u1ec3 k\u00edch ho\u1ea1t c\u00e1c t\u00ednh n\u0103ng b\u1ea3o m\u1eadt.&nbsp;<\/p>\n\n\n\n<p>Trong file <code>pom.xml<\/code>, h\u00e3y th\u00eam dependency sau:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;dependency&gt;\n    &lt;groupId&gt;org.springframework.boot&lt;\/groupId&gt;\n    &lt;artifactId&gt;spring-boot-starter-security&lt;\/artifactId&gt;\n&lt;\/dependency&gt;<\/code><\/pre>\n\n\n\n<p>Sau khi th\u00eam, m\u1ecdi endpoint c\u1ee7a b\u1ea1n s\u1ebd \u0111\u01b0\u1ee3c b\u1ea3o v\u1ec7 ngay l\u1eadp t\u1ee9c.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-t\u1ea1o-l\u1edbp-c\u1ea5u-hinh-b\u1ea3o-m\u1eadt\"><strong>T\u1ea1o l\u1edbp c\u1ea5u h\u00ecnh b\u1ea3o m\u1eadt<\/strong><\/h3>\n\n\n\n<p>Sau khi c\u00f3 th\u01b0 vi\u1ec7n, b\u01b0\u1edbc n\u00e0y t\u1ea1o ra m\u1ed9t l\u1edbp \u0111\u1ec3 b\u1ea1n c\u00f3 th\u1ec3 \u0111\u1ecbnh ngh\u0129a v\u00e0 t\u00f9y ch\u1ec9nh c\u00e1c quy t\u1eafc b\u1ea3o m\u1eadt ri\u00eang cho \u1ee9ng d\u1ee5ng c\u1ee7a m\u00ecnh.<\/p>\n\n\n\n<p>T\u1ea1o m\u1ed9t l\u1edbp <code>SecurityConfig<\/code> v\u00e0 \u0111\u00e1nh d\u1ea5u n\u00f3 v\u1edbi <code>@Configuration<\/code>. \u0110\u00e2y s\u1ebd l\u00e0 n\u01a1i ch\u00fang ta \u0111\u1ecbnh ngh\u0129a c\u00e1c quy t\u1eafc b\u1ea3o m\u1eadt:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>import org.springframework.context.annotation.Configuration;\nimport org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;\n\n@Configuration\n@EnableWebSecurity \/\/ B\u1eadt t\u00ednh n\u0103ng b\u1ea3o m\u1eadt web c\u1ee7a Spring Security\npublic class SecurityConfig {\n    \/\/ C\u00e1c bean c\u1ea5u h\u00ecnh s\u1ebd \u0111\u01b0\u1ee3c \u0111\u1eb7t \u1edf \u0111\u00e2y\n}<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-c\u1ea5u-hinh-securityfilterchain-va-httpsecurity-nbsp\"><strong>C\u1ea5u h\u00ecnh SecurityFilterChain v\u00e0 HttpSecurity&nbsp;<\/strong><\/h3>\n\n\n\n<p>B\u01b0\u1edbc n\u00e0y cho ph\u00e9p b\u1ea1n ki\u1ec3m so\u00e1t c\u00e1ch c\u00e1c request HTTP \u0111\u01b0\u1ee3c x\u1eed l\u00fd v\u1ec1 m\u1eb7t b\u1ea3o m\u1eadt, v\u00ed d\u1ee5 nh\u01b0 trang n\u00e0o \u0111\u01b0\u1ee3c ph\u00e9p truy c\u1eadp t\u1ef1 do v\u00e0 trang n\u00e0o c\u1ea7n x\u00e1c th\u1ef1c.<\/p>\n\n\n\n<p>H\u00e3y t\u1ea1o m\u1ed9t bean SecurityFilterChain \u0111\u1ec3 t\u00f9y ch\u1ec9nh quy t\u1eafc. V\u00ed d\u1ee5, ch\u00fang ta s\u1ebd cho ph\u00e9p m\u1ecdi ng\u01b0\u1eddi truy c\u1eadp v\u00e0o trang ch\u1ee7 (\/) v\u00e0 y\u00eau c\u1ea7u x\u00e1c th\u1ef1c cho t\u1ea5t c\u1ea3 c\u00e1c trang c\u00f2n l\u1ea1i nh\u01b0 sau:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>import org.springframework.context.annotation.Bean;\nimport org.springframework.security.config.annotation.web.builders.HttpSecurity;\nimport org.springframework.security.web.SecurityFilterChain;\n\n@Configuration\n\/\/ ...\npublic class SecurityConfig {\n\n    @Bean\n    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {\n        http\n            .authorizeHttpRequests(authorize -&gt; authorize\n                .requestMatchers(\"\/\", \"\/home\").permitAll() \/\/ Cho ph\u00e9p truy c\u1eadp kh\u00f4ng c\u1ea7n x\u00e1c th\u1ef1c\n                .anyRequest().authenticated() \/\/ M\u1ecdi request kh\u00e1c \u0111\u1ec1u c\u1ea7n x\u00e1c th\u1ef1c\n            )\n            .formLogin(formLogin -&gt; formLogin \/\/ C\u1ea5u h\u00ecnh form \u0111\u0103ng nh\u1eadp\n                .loginPage(\"\/login\") \/\/ \u0110\u01b0\u1eddng d\u1eabn t\u1edbi trang \u0111\u0103ng nh\u1eadp t\u00f9y ch\u1ec9nh (n\u1ebfu c\u00f3)\n                .permitAll()\n            )\n            .logout(logout -&gt; logout.permitAll()); \/\/ Cho ph\u00e9p t\u1ea5t c\u1ea3 ng\u01b0\u1eddi d\u00f9ng logout\n\n        return http.build();\n    }\n}<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-c\u1ea5u-hinh-userdetailsservice-va-passwordencoder\"><strong>C\u1ea5u h\u00ecnh <\/strong><strong>UserDetailsService<\/strong><strong> v\u00e0 <\/strong><strong>PasswordEncoder<\/strong><\/h3>\n\n\n\n<p>Cu\u1ed1i c\u00f9ng, b\u01b0\u1edbc n\u00e0y \u0111\u1ecbnh ngh\u0129a c\u00e1ch \u1ee9ng d\u1ee5ng x\u00e1c th\u1ef1c ng\u01b0\u1eddi d\u00f9ng v\u00e0 \u0111\u1ea3m b\u1ea3o m\u1eadt kh\u1ea9u \u0111\u01b0\u1ee3c l\u01b0u tr\u1eef an to\u00e0n b\u1eb1ng c\u00e1ch m\u00e3 h\u00f3a ch\u00fang.<\/p>\n\n\n\n<p>H\u00e3y \u0111\u1ecbnh ngh\u0129a m\u1ed9t bean PasswordEncoder v\u00e0 m\u1ed9t bean UserDetailsService \u0111\u1ec3 t\u1ea1o ra m\u1ed9t v\u00e0i ng\u01b0\u1eddi d\u00f9ng trong b\u1ed9 nh\u1edb nh\u01b0 sau:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>import org.springframework.security.core.userdetails.User;\nimport org.springframework.security.core.userdetails.UserDetails;\nimport org.springframework.security.core.userdetails.UserDetailsService;\nimport org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;\nimport org.springframework.security.crypto.password.PasswordEncoder;\nimport org.springframework.security.provisioning.InMemoryUserDetailsManager;\n\n@Configuration\n\/\/ ...\npublic class SecurityConfig {\n\n    \/\/ ... bean SecurityFilterChain \u1edf tr\u00ean\n\n    @Bean\n    public PasswordEncoder passwordEncoder() {\n        \/\/ S\u1eed d\u1ee5ng BCrypt \u0111\u1ec3 m\u00e3 h\u00f3a m\u1eadt kh\u1ea9u\n        return new BCryptPasswordEncoder();\n    }\n\n    @Bean\n    public UserDetailsService userDetailsService() {\n        \/\/ T\u1ea1o ng\u01b0\u1eddi d\u00f9ng admin\n        UserDetails admin = User.builder()\n                .username(\"admin\")\n                .password(passwordEncoder().encode(\"admin123\")) \/\/ M\u1eadt kh\u1ea9u ph\u1ea3i \u0111\u01b0\u1ee3c m\u00e3 h\u00f3a\n                .roles(\"ADMIN\")\n                .build();\n\n        \/\/ T\u1ea1o ng\u01b0\u1eddi d\u00f9ng user\n        UserDetails user = User.builder()\n                .username(\"user\")\n                .password(passwordEncoder().encode(\"user123\"))\n                .roles(\"USER\")\n                .build();\n        \n        \/\/ Qu\u1ea3n l\u00fd ng\u01b0\u1eddi d\u00f9ng trong b\u1ed9 nh\u1edb\n        return new InMemoryUserDetailsManager(admin, user);\n    }\n}<\/code><\/pre>\n\n\n\n<p>V\u1edbi c\u1ea5u h\u00ecnh n\u00e0y, b\u1ea1n \u0111\u00e3 thi\u1ebft l\u1eadp m\u1ed9t h\u1ec7 th\u1ed1ng b\u1ea3o m\u1eadt c\u01a1 b\u1ea3n v\u1edbi 2 ng\u01b0\u1eddi d\u00f9ng c\u00f3 vai tr\u00f2 kh\u00e1c nhau.<\/p>\n\n\n\n<p>T\u00f3m l\u1ea1i, v\u00ed d\u1ee5 tr\u00ean gi\u00fap b\u1ea1n h\u00ecnh dung ph\u1ea7n n\u00e0o c\u00e1ch Spring Boot Security gi\u00fap \u0111\u01a1n gi\u1ea3n h\u00f3a vi\u1ec7c c\u1ea5u h\u00ecnh b\u1ea3o m\u1eadt so v\u1edbi Spring Security truy\u1ec1n th\u1ed1ng, th\u00f4ng qua vi\u1ec7c cung c\u1ea5p c\u00e1c c\u01a1 ch\u1ebf t\u1ef1 \u0111\u1ed9ng v\u00e0 y\u00eau c\u1ea7u \u00edt code h\u01a1n \u0111\u1ec3 thi\u1ebft l\u1eadp m\u1ed9t h\u1ec7 th\u1ed1ng b\u1ea3o m\u1eadt ho\u1ea1t \u0111\u1ed9ng ngay l\u1eadp t\u1ee9c.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-cac-ch\u1ee7-d\u1ec1-nang-cao-va-b\u1ea3o-m\u1eadt-toan-di\u1ec7n\"><span class=\"ez-toc-section\" id=\"Cac_chu_de_nang_cao_va_bao_mat_toan_dien\"><\/span><strong>C\u00e1c ch\u1ee7 \u0111\u1ec1 n\u00e2ng cao v\u00e0 b\u1ea3o m\u1eadt to\u00e0n di\u1ec7n<\/strong><span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-b\u1ea3o-v\u1ec7-ch\u1ed1ng-l\u1ea1i-cac-l\u1ed7-h\u1ed5ng-ph\u1ed5-bi\u1ebfn\"><strong>B\u1ea3o v\u1ec7 ch\u1ed1ng l\u1ea1i c\u00e1c l\u1ed7 h\u1ed5ng ph\u1ed5 bi\u1ebfn<\/strong><\/h3>\n\n\n\n<p>Spring Security cung c\u1ea5p c\u00e1c c\u01a1 ch\u1ebf ph\u00f2ng th\u1ee7 m\u1ea1nh m\u1ebd \u0111\u01b0\u1ee3c b\u1eadt s\u1eb5n \u0111\u1ec3 ch\u1ed1ng l\u1ea1i c\u00e1c cu\u1ed9c t\u1ea5n c\u00f4ng web ph\u1ed5 bi\u1ebfn d\u01b0\u1edbi \u0111\u00e2y:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>CSRF (Cross-Site Request Forgery):<\/strong>&nbsp;<\/li>\n<\/ol>\n\n\n\n<p>\u0110\u00e2y l\u00e0 ki\u1ec3u t\u1ea5n c\u00f4ng l\u1eeba ng\u01b0\u1eddi d\u00f9ng th\u1ef1c hi\u1ec7n c\u00e1c h\u00e0nh \u0111\u1ed9ng h\u1ecd kh\u00f4ng mong mu\u1ed1n.<\/p>\n\n\n\n<p><strong>C\u01a1 ch\u1ebf b\u1ea3o v\u1ec7:<\/strong> Spring Security <strong>b\u1eadt b\u1ea3o v\u1ec7 CSRF m\u1eb7c \u0111\u1ecbnh<\/strong> cho c\u00e1c \u1ee9ng d\u1ee5ng s\u1eed d\u1ee5ng session. N\u00f3 y\u00eau c\u1ea7u m\u1ed9t token b\u00ed m\u1eadt ph\u1ea3i \u0111\u01b0\u1ee3c g\u1eedi k\u00e8m v\u1edbi c\u00e1c request thay \u0111\u1ed5i tr\u1ea1ng th\u00e1i (POST, PUT, DELETE). Thymeleaf v\u00e0 c\u00e1c template engine kh\u00e1c th\u01b0\u1eddng t\u1ef1 \u0111\u1ed9ng t\u00edch h\u1ee3p token n\u00e0y. \u0110\u1ed1i v\u1edbi API stateless (nh\u01b0 JWT), b\u1ea1n c\u00f3 th\u1ec3 t\u1eaft t\u00ednh n\u0103ng n\u00e0y.<\/p>\n\n\n\n<ol start=\"2\" class=\"wp-block-list\">\n<li><strong>CORS (Cross-Origin Resource Sharing):<\/strong>&nbsp;<\/li>\n<\/ol>\n\n\n\n<p>\u0110\u00e2y l\u00e0 m\u1ed9t c\u01a1 ch\u1ebf c\u1ee7a tr\u00ecnh duy\u1ec7t nh\u1eb1m ki\u1ec3m so\u00e1t c\u00e1c request \u0111\u01b0\u1ee3c g\u1eedi t\u1eeb m\u1ed9t domain kh\u00e1c v\u1edbi domain c\u1ee7a server.<\/p>\n\n\n\n<p>Khi frontend v\u00e0 backend c\u1ee7a b\u1ea1n ch\u1ea1y tr\u00ean hai domain kh\u00e1c nhau, b\u1ea1n c\u1ea7n c\u1ea5u h\u00ecnh CORS. Trong Spring Security, b\u1ea1n c\u00f3 th\u1ec3 \u0111\u1ecbnh ngh\u0129a m\u1ed9t <code>CorsConfigurationSource<\/code> bean \u0111\u1ec3 ch\u1ec9 \u0111\u1ecbnh c\u00e1c origin, method, v\u00e0 header \u0111\u01b0\u1ee3c ph\u00e9p.<\/p>\n\n\n\n<ol start=\"3\" class=\"wp-block-list\">\n<li><strong>XSS (Cross-Site Scripting):<\/strong>&nbsp;<\/li>\n<\/ol>\n\n\n\n<p>T\u1ea5n c\u00f4ng n\u00e0y x\u1ea3y ra khi k\u1ebb x\u1ea5u ch\u00e8n c\u00e1c \u0111o\u1ea1n script \u0111\u1ed9c h\u1ea1i v\u00e0o trang web c\u1ee7a b\u1ea1n \u0111\u1ec3 th\u1ef1c thi tr\u00ean tr\u00ecnh duy\u1ec7t c\u1ee7a ng\u01b0\u1eddi d\u00f9ng kh\u00e1c.<\/p>\n\n\n\n<p><strong>C\u01a1 ch\u1ebf b\u1ea3o v\u1ec7:<\/strong> M\u1eb7c d\u00f9 kh\u00f4ng ph\u1ea3i l\u00e0 nhi\u1ec7m v\u1ee5 ch\u00ednh, Spring Security g\u00f3p ph\u1ea7n ph\u00f2ng ch\u1ed1ng b\u1eb1ng c\u00e1ch thi\u1ebft l\u1eadp c\u00e1c header b\u1ea3o m\u1eadt (X<code>-XSS-Protection<\/code>). Tuy nhi\u00ean, bi\u1ec7n ph\u00e1p quan tr\u1ecdng nh\u1ea5t l\u00e0 lu\u00f4n l\u00e0m s\u1ea1ch (sanitize) v\u00e0 m\u00e3 h\u00f3a (escape) d\u1eef li\u1ec7u \u0111\u1ea7u v\u00e0o t\u1eeb ng\u01b0\u1eddi d\u00f9ng v\u00e0 s\u1eed d\u1ee5ng c\u00e1c template engine nh\u01b0 Thymeleaf c\u00f3 kh\u1ea3 n\u0103ng escape t\u1ef1 \u0111\u1ed9ng.<\/p>\n\n\n\n<ol start=\"4\" class=\"wp-block-list\">\n<li><strong>Session Fixation:<\/strong>&nbsp;<\/li>\n<\/ol>\n\n\n\n<p>K\u1ebb t\u1ea5n c\u00f4ng l\u1eeba ng\u01b0\u1eddi d\u00f9ng s\u1eed d\u1ee5ng m\u1ed9t session ID m\u00e0 ch\u00fang \u0111\u00e3 bi\u1ebft tr\u01b0\u1edbc.<\/p>\n\n\n\n<p><strong>C\u01a1 ch\u1ebf b\u1ea3o v\u1ec7:<\/strong> Spring Security t\u1ef1 \u0111\u1ed9ng ng\u0103n ch\u1eb7n \u0111i\u1ec1u n\u00e0y. Khi ng\u01b0\u1eddi d\u00f9ng \u0111\u0103ng nh\u1eadp th\u00e0nh c\u00f4ng, n\u00f3 s\u1ebd h\u1ee7y session c\u0169 v\u00e0 t\u1ea1o m\u1ed9t session ho\u00e0n to\u00e0n m\u1edbi, l\u00e0m cho session ID m\u00e0 k\u1ebb t\u1ea5n c\u00f4ng bi\u1ebft tr\u1edf n\u00ean v\u00f4 d\u1ee5ng.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-qu\u1ea3n-ly-phien-session-management\"><strong>Qu\u1ea3n l\u00fd phi\u00ean (Session Management)<\/strong><\/h3>\n\n\n\n<p>Vi\u1ec7c ki\u1ec3m so\u00e1t c\u00e1ch c\u00e1c phi\u00ean \u0111\u01b0\u1ee3c t\u1ea1o v\u00e0 duy tr\u00ec l\u00e0 r\u1ea5t quan tr\u1ecdng, \u0111\u1eb7c bi\u1ec7t khi ph\u00e2n bi\u1ec7t gi\u1eefa \u1ee9ng d\u1ee5ng web truy\u1ec1n th\u1ed1ng v\u00e0 API.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Ch\u00ednh s\u00e1ch t\u1ea1o phi\u00ean:<\/strong><\/li>\n<\/ul>\n\n\n\n<p>B\u1ea1n c\u00f3 th\u1ec3 c\u1ea5u h\u00ecnh Spring Security \u0111\u1ec3 quy\u1ebft \u0111\u1ecbnh khi n\u00e0o t\u1ea1o session.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>IF_REQUIRED<\/code>: M\u1eb7c \u0111\u1ecbnh, ch\u1ec9 t\u1ea1o session n\u1ebfu c\u1ea7n.<\/li>\n\n\n\n<li><code>STATELESS<\/code>: <strong>Kh\u00f4ng t\u1ea1o ho\u1eb7c s\u1eed d\u1ee5ng session<\/strong>. \u0110\u00e2y l\u00e0 l\u1ef1a ch\u1ecdn b\u1eaft bu\u1ed9c cho c\u00e1c RESTful API s\u1eed d\u1ee5ng token (nh\u01b0 JWT) \u0111\u1ec3 duy tr\u00ec tr\u1ea1ng th\u00e1i ph\u00eda client.<\/li>\n\n\n\n<li><strong>Ph\u00e1t hi\u1ec7n phi\u00ean h\u1ebft h\u1ea1n:<\/strong> B\u1ea1n c\u00f3 th\u1ec3 c\u1ea5u h\u00ecnh \u0111\u1ec3 x\u1eed l\u00fd khi session c\u1ee7a ng\u01b0\u1eddi d\u00f9ng h\u1ebft h\u1ea1n, v\u00ed d\u1ee5 nh\u01b0 chuy\u1ec3n h\u01b0\u1edbng h\u1ecd v\u1ec1 trang \u0111\u0103ng nh\u1eadp.<\/li>\n<\/ul>\n\n\n\n<p><strong>V\u00ed d\u1ee5 c\u1ea5u h\u00ecnh cho API stateless:<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>@Bean\npublic SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {\n    http\n        \/\/ ... c\u00e1c c\u1ea5u h\u00ecnh kh\u00e1c\n        .sessionManagement(session -&gt; \n            session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)\n        );\n    return http.build();\n}<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-ki\u1ec3m-th\u1eed-b\u1ea3o-m\u1eadt-security-testing\"><strong>Ki\u1ec3m th\u1eed b\u1ea3o m\u1eadt (Security Testing)<\/strong><\/h3>\n\n\n\n<p>Vi\u1ebft test cho c\u00e1c quy t\u1eafc b\u1ea3o m\u1eadt l\u00e0 m\u1ed9t ph\u1ea7n kh\u00f4ng th\u1ec3 thi\u1ebfu \u0111\u1ec3 \u0111\u1ea3m b\u1ea3o ch\u00fang ho\u1ea1t \u0111\u1ed9ng \u0111\u00fang nh\u01b0 mong \u0111\u1ee3i.<\/p>\n\n\n\n<p>\u0110\u1ec3 ki\u1ec3m th\u1eed c\u00e1c t\u00ednh n\u0103ng b\u1ea3o m\u1eadt trong \u1ee9ng d\u1ee5ng Spring Boot, b\u1ea1n c\u00f3 th\u1ec3 s\u1eed d\u1ee5ng c\u00e1c c\u00f4ng c\u1ee5 chuy\u00ean d\u1ee5ng do ch\u00ednh Spring Security cung c\u1ea5p. C\u00f4ng c\u1ee5 ch\u00ednh bao g\u1ed3m dependency <strong>spring-security-test<\/strong> v\u00e0 <strong>MockMvc<\/strong>.<\/p>\n\n\n\n<p>C\u00e1ch th\u1ef1c hi\u1ec7n r\u1ea5t \u0111\u01a1n gi\u1ea3n, bao g\u1ed3m c\u00e1c b\u01b0\u1edbc sau:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Th\u00eam dependency<\/strong>: \u0110\u1ea7u ti\u00ean, b\u1ea1n c\u1ea7n th\u00eam <code>spring-security-test<\/code> v\u00e0o file <code>pom.xml<\/code> v\u1edbi scope test.<\/li>\n\n\n\n<li><strong>S\u1eed d\u1ee5ng MockMvc<\/strong>: Ti\u1ebfp theo, h\u00e3y d\u00f9ng <code>MockMvc<\/code> \u0111\u1ec3 t\u1ea1o c\u00e1c request HTTP gi\u1ea3 l\u1eadp \u0111\u1ebfn c\u00e1c endpoint c\u1ee7a b\u1ea1n. C\u00f4ng c\u1ee5 n\u00e0y gi\u00fap b\u1ea1n ki\u1ec3m tra xem m\u1ed9t endpoint c\u00f4ng khai c\u00f3 tr\u1ea3 v\u1ec1 m\u00e3 200 OK hay kh\u00f4ng, v\u00e0 m\u1ed9t endpoint \u0111\u01b0\u1ee3c b\u1ea3o v\u1ec7 s\u1ebd tr\u1ea3 v\u1ec1 401 Unauthorized (khi ch\u01b0a x\u00e1c th\u1ef1c) ho\u1eb7c 403 Forbidden (khi kh\u00f4ng c\u00f3 quy\u1ec1n truy c\u1eadp).<\/li>\n\n\n\n<li><strong>Gi\u1ea3 l\u1eadp ng\u01b0\u1eddi d\u00f9ng<\/strong>: Cu\u1ed1i c\u00f9ng, \u0111\u1ec3 ki\u1ec3m tra logic ph\u00e2n quy\u1ec1n, b\u1ea1n c\u00f3 th\u1ec3 s\u1eed d\u1ee5ng c\u00e1c annotation nh\u01b0 <code>@WithMockUser<\/code>. Annotation n\u00e0y cho ph\u00e9p b\u1ea1n th\u1ef1c thi m\u1ed9t b\u00e0i test nh\u01b0 th\u1ec3 \u0111ang c\u00f3 m\u1ed9t ng\u01b0\u1eddi d\u00f9ng \u0111\u00e3 \u0111\u0103ng nh\u1eadp v\u1edbi t\u00ean, m\u1eadt kh\u1ea9u v\u00e0 vai tr\u00f2 (roles\/authorities) c\u1ee5 th\u1ec3, gi\u00fap vi\u1ec7c ki\u1ec3m tra c\u00e1c quy t\u1eafc b\u1ea3o m\u1eadt tr\u1edf n\u00ean d\u1ec5 d\u00e0ng v\u00e0 tr\u1ef1c quan.<\/li>\n<\/ul>\n\n\n\n<p><strong>V\u00ed d\u1ee5 m\u1ed9t b\u00e0i test:<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>@SpringBootTest\n@AutoConfigureMockMvc\nclass SecurityTests {\n\n    @Autowired\n    private MockMvc mockMvc;\n\n    @Test\n    void accessAdminPage_FailsWithoutAuth() throws Exception {\n        \/\/ Ki\u1ec3m tra r\u1eb1ng truy c\u1eadp \/admin s\u1ebd b\u1ecb chuy\u1ec3n h\u01b0\u1edbng \u0111\u1ebfn trang login (status 302)\n        \/\/ khi ch\u01b0a x\u00e1c th\u1ef1c.\n        mockMvc.perform(get(\"\/admin\"))\n               .andExpect(status().is3xxRedirection());\n    }\n\n    @Test\n    @WithMockUser(username = \"admin\", roles = {\"ADMIN\"})\n    void accessAdminPage_SucceedsWithAdminRole() throws Exception {\n        \/\/ V\u1edbi @WithMockUser, b\u00e0i test n\u00e0y ch\u1ea1y nh\u01b0 m\u1ed9t ng\u01b0\u1eddi d\u00f9ng 'admin' c\u00f3 vai tr\u00f2 'ADMIN'\n        \/\/ \u0111\u00e3 \u0111\u0103ng nh\u1eadp. Do \u0111\u00f3, request s\u1ebd th\u00e0nh c\u00f4ng (status 200).\n        mockMvc.perform(get(\"\/admin\"))\n               .andExpect(status().isOk());\n    }\n}<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-b\u1ea3o-m\u1eadt-\u1edf-c\u1ea5p-d\u1ed9-ph\u01b0\u01a1ng-th\u1ee9c-method-level-security-nbsp\"><strong>B\u1ea3o m\u1eadt \u1edf c\u1ea5p \u0111\u1ed9 ph\u01b0\u01a1ng th\u1ee9c (Method-Level Security)&nbsp;<\/strong><\/h3>\n\n\n\n<p>Thay v\u00ec ch\u1ec9 b\u1ea3o v\u1ec7 c\u00e1c URL, b\u1ea1n c\u00f3 th\u1ec3 b\u1ea3o v\u1ec7 tr\u1ef1c ti\u1ebfp c\u00e1c ph\u01b0\u01a1ng th\u1ee9c trong t\u1ea7ng Service ho\u1eb7c Controller. C\u0169ng nh\u01b0 khi b\u1ea1n mu\u1ed1n ki\u1ec3m so\u00e1t quy\u1ec1n truy c\u1eadp chi ti\u1ebft h\u01a1n \u1edf m\u1ee9c h\u00e0m. \u0110i\u1ec1u n\u00e0y gi\u00fap m\u00e3 ngu\u1ed3n an to\u00e0n v\u00e0 r\u00f5 r\u00e0ng h\u01a1n<\/p>\n\n\n\n<p>\u0110\u1ea7u ti\u00ean, b\u1ea1n c\u1ea7n k\u00edch ho\u1ea1t t\u00ednh n\u0103ng n\u00e0y b\u1eb1ng c\u00e1ch th\u00eam annotation <strong><code>@EnableMethodSecurity<\/code><\/strong> v\u00e0o m\u1ed9t l\u1edbp c\u1ea5u h\u00ecnh.<\/p>\n\n\n\n<p>Sau \u0111\u00f3, b\u1ea1n s\u1eed d\u1ee5ng c\u00e1c annotation sau tr\u00ean c\u00e1c ph\u01b0\u01a1ng th\u1ee9c c\u1ea7n b\u1ea3o v\u1ec7:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong><code>@Secured<\/code><\/strong>: C\u00e1ch \u0111\u01a1n gi\u1ea3n nh\u1ea5t. B\u1ea1n truy\u1ec1n v\u00e0o m\u1ed9t m\u1ea3ng c\u00e1c vai tr\u00f2 ho\u1eb7c quy\u1ec1n.\n<ul class=\"wp-block-list\">\n<li>V\u00ed d\u1ee5: <code>@Secured(\"ROLE_ADMIN\")<\/code><\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong><code>@RolesAllowed<\/code><\/strong>: Annotation chu\u1ea9n c\u1ee7a JSR-250, ch\u1ec9 d\u00e0nh cho vai tr\u00f2. Kh\u00f4ng c\u1ea7n ti\u1ec1n t\u1ed1 <code>ROLE_<\/code>.\n<ul class=\"wp-block-list\">\n<li>V\u00ed d\u1ee5: <code>@RolesAllowed(\"ADMIN\")<\/code><\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong><code>@PreAuthorize <\/code>\/ <code>@PostAuthorize<\/code><\/strong>: M\u1ea1nh m\u1ebd v\u00e0 linh ho\u1ea1t nh\u1ea5t, s\u1eed d\u1ee5ng Ng\u00f4n ng\u1eef Bi\u1ec3u th\u1ee9c Spring (SpEL).\n<ul class=\"wp-block-list\">\n<li><strong><code>@PreAuthorize<\/code><\/strong>: Ki\u1ec3m tra quy\u1ec1n <strong>tr\u01b0\u1edbc khi<\/strong> ph\u01b0\u01a1ng th\u1ee9c \u0111\u01b0\u1ee3c th\u1ef1c thi.<\/li>\n\n\n\n<li><strong><code>@PostAuthorize<\/code><\/strong>: Ki\u1ec3m tra quy\u1ec1n <strong>sau khi<\/strong> ph\u01b0\u01a1ng th\u1ee9c \u0111\u00e3 th\u1ef1c thi, c\u00f3 th\u1ec3 d\u00f9ng \u0111\u1ec3 ki\u1ec3m tra gi\u00e1 tr\u1ecb tr\u1ea3 v\u1ec1 (returnObject).<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n\n<p><strong>V\u00ed d\u1ee5 trong Service Layer:<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>import org.springframework.security.access.prepost.PreAuthorize;\nimport org.springframework.stereotype.Service;\n\n@Service\npublic class ProductService {\n\n    \/\/ Ch\u1ec9 ng\u01b0\u1eddi d\u00f9ng c\u00f3 vai tr\u00f2 ADMIN m\u1edbi c\u00f3 th\u1ec3 x\u00f3a s\u1ea3n ph\u1ea9m\n    @PreAuthorize(\"hasRole('ADMIN')\")\n    public void deleteProduct(Long id) {\n        \/\/ logic x\u00f3a s\u1ea3n ph\u1ea9m\n        System.out.println(\"\u0110\u00e3 x\u00f3a s\u1ea3n ph\u1ea9m v\u1edbi ID: \" + id);\n    }\n\n    \/\/ Ng\u01b0\u1eddi d\u00f9ng ph\u1ea3i c\u00f3 quy\u1ec1n 'product:read' \u0111\u1ec3 xem s\u1ea3n ph\u1ea9m\n    @PreAuthorize(\"hasAuthority('product:read')\")\n    public Product getProductById(Long id) {\n        \/\/ logic l\u1ea5y s\u1ea3n ph\u1ea9m\n        return new Product(id, \"Sample Product\");\n    }\n    \n    \/\/ Ch\u1ec9 ng\u01b0\u1eddi d\u00f9ng t\u1ea1o ra \u0111\u01a1n h\u00e0ng m\u1edbi c\u00f3 th\u1ec3 xem chi ti\u1ebft \u0111\u01a1n h\u00e0ng \u0111\u00f3\n    @PreAuthorize(\"#username == authentication.principal.username\")\n    public Order getOrderForUser(Long orderId, String username) {\n        \/\/ logic ph\u1ee9c t\u1ea1p h\u01a1n\n        return new Order(orderId);\n    }\n}<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-cac-ph\u01b0\u01a1ng-phap-t\u1ed1t-nh\u1ea5t-d\u1ec3-s\u1eed-d\u1ee5ng-spring-boot-security\"><span class=\"ez-toc-section\" id=\"Cac_phuong_phap_tot_nhat_de_su_dung_Spring_Boot_security\"><\/span><strong>C\u00e1c ph\u01b0\u01a1ng ph\u00e1p t\u1ed1t nh\u1ea5t \u0111\u1ec3 s\u1eed d\u1ee5ng Spring Boot security<\/strong><span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>Vi\u1ec7c tri\u1ec3n khai c\u00e1c t\u00ednh n\u0103ng b\u1ea3o m\u1eadt ch\u1ec9 l\u00e0 b\u01b0\u1edbc \u0111\u1ea7u. \u0110\u1ec3 x\u00e2y d\u1ef1ng m\u1ed9t \u1ee9ng d\u1ee5ng th\u1ef1c s\u1ef1 an to\u00e0n v\u00e0 d\u1ec5 b\u1ea3o tr\u00ec, b\u1ea1n c\u1ea7n tu\u00e2n th\u1ee7 c\u00e1c ph\u01b0\u01a1ng ph\u00e1p th\u1ef1c h\u00e0nh t\u1ed1t nh\u1ea5t sau \u0111\u00e2y.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-1-c\u1ea5u-truc-d\u1ef1-an-ro-rang\"><strong>1. C\u1ea5u tr\u00fac d\u1ef1 \u00e1n r\u00f5 r\u00e0ng<\/strong><\/h3>\n\n\n\n<p>H\u00e3y t\u1ed5 ch\u1ee9c c\u00e1c l\u1edbp li\u00ean quan \u0111\u1ebfn b\u1ea3o m\u1eadt v\u00e0o m\u1ed9t package ri\u00eang, v\u00ed d\u1ee5 <code>com.example.yourapp.security<\/code>. \u0110i\u1ec1u n\u00e0y bao g\u1ed3m c\u00e1c l\u1edbp c\u1ea5u h\u00ecnh (<code>SecurityConfig<\/code>), c\u00e1c b\u1ed9 l\u1ecdc t\u00f9y ch\u1ec9nh (<code>JwtRequestFilter<\/code>), c\u00e1c l\u1edbp d\u1ecbch v\u1ee5 ng\u01b0\u1eddi d\u00f9ng (<code>UserDetailsService<\/code>), v\u00e0 c\u00e1c model li\u00ean quan.<\/p>\n\n\n\n<p>M\u1ed9t c\u1ea5u tr\u00fac r\u00f5 r\u00e0ng gi\u00fap m\u00e3 ngu\u1ed3n d\u1ec5 \u0111\u1ecdc, d\u1ec5 qu\u1ea3n l\u00fd v\u00e0 d\u1ec5 d\u00e0ng t\u00ecm ki\u1ebfm khi c\u1ea7n g\u1ee1 l\u1ed7i ho\u1eb7c n\u00e2ng c\u1ea5p.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-2-luon-s\u1eed-d\u1ee5ng-https-trong-moi-tr\u01b0\u1eddng-production\"><strong>2. Lu\u00f4n s\u1eed d\u1ee5ng HTTPS trong m\u00f4i tr\u01b0\u1eddng Production<\/strong><\/h3>\n\n\n\n<p>HTTPS l\u00e0 y\u00eau c\u1ea7u <strong>b\u1eaft bu\u1ed9c<\/strong> cho b\u1ea5t k\u1ef3 \u1ee9ng d\u1ee5ng n\u00e0o trong m\u00f4i tr\u01b0\u1eddng production. N\u00f3 m\u00e3 h\u00f3a to\u00e0n b\u1ed9 d\u1eef li\u1ec7u truy\u1ec1n t\u1ea3i gi\u1eefa client v\u00e0 server, b\u1ea3o v\u1ec7 th\u00f4ng tin nh\u1ea1y c\u1ea3m nh\u01b0 m\u1eadt kh\u1ea9u v\u00e0 token kh\u1ecfi c\u00e1c cu\u1ed9c t\u1ea5n c\u00f4ng nghe l\u00e9n (man-in-the-middle).<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-3-luon-c\u1eadp-nh\u1eadt-cac-dependency\"><strong>3. Lu\u00f4n c\u1eadp nh\u1eadt c\u00e1c Dependency<\/strong><\/h3>\n\n\n\n<p>Th\u1ebf gi\u1edbi b\u1ea3o m\u1eadt lu\u00f4n bi\u1ebfn \u0111\u1ed9ng, c\u00e1c l\u1ed7 h\u1ed5ng m\u1edbi \u0111\u01b0\u1ee3c ph\u00e1t hi\u1ec7n li\u00ean t\u1ee5c. H\u00e3y th\u01b0\u1eddng xuy\u00ean ki\u1ec3m tra v\u00e0 c\u1eadp nh\u1eadt c\u00e1c dependency c\u1ee7a d\u1ef1 \u00e1n, \u0111\u1eb7c bi\u1ec7t l\u00e0 <code>spring-boot-starter-security<\/code>, l\u00ean phi\u00ean b\u1ea3n m\u1edbi nh\u1ea5t. Vi\u1ec7c n\u00e0y \u0111\u1ea3m b\u1ea3o b\u1ea1n nh\u1eadn \u0111\u01b0\u1ee3c c\u00e1c b\u1ea3n v\u00e1 l\u1ed7i b\u1ea3o m\u1eadt quan tr\u1ecdng t\u1eeb c\u1ed9ng \u0111\u1ed3ng.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-4-nguyen-t\u1eafc-d\u1eb7c-quy\u1ec1n-t\u1ed1i-thi\u1ec3u-principle-of-least-privilege\"><strong>4. Nguy\u00ean t\u1eafc \u0111\u1eb7c quy\u1ec1n t\u1ed1i thi\u1ec3u (Principle of Least Privilege)<\/strong><\/h3>\n\n\n\n<p>\u0110\u00e2y l\u00e0 m\u1ed9t trong nh\u1eefng nguy\u00ean t\u1eafc n\u1ec1n t\u1ea3ng c\u1ee7a an to\u00e0n th\u00f4ng tin. H\u00e3y \u0111\u1ea3m b\u1ea3o r\u1eb1ng m\u1ed7i ng\u01b0\u1eddi d\u00f9ng ho\u1eb7c h\u1ec7 th\u1ed1ng ch\u1ec9 \u0111\u01b0\u1ee3c c\u1ea5p nh\u1eefng quy\u1ec1n t\u1ed1i thi\u1ec3u c\u1ea7n thi\u1ebft \u0111\u1ec3 th\u1ef1c hi\u1ec7n ch\u1ee9c n\u0103ng c\u1ee7a m\u00ecnh. V\u00ed d\u1ee5, m\u1ed9t ng\u01b0\u1eddi d\u00f9ng th\u00f4ng th\u01b0\u1eddng kh\u00f4ng n\u00ean c\u00f3 quy\u1ec1n truy c\u1eadp v\u00e0o c\u00e1c trang qu\u1ea3n tr\u1ecb, v\u00e0 m\u1ed9t API ch\u1ec9 \u0111\u1ecdc d\u1eef li\u1ec7u kh\u00f4ng n\u00ean c\u00f3 quy\u1ec1n ghi v\u00e0o c\u01a1 s\u1edf d\u1eef li\u1ec7u.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-5-x\u1eed-ly-ngo\u1ea1i-l\u1ec7-exception-handling-tuy-ch\u1ec9nh\"><strong>5. X\u1eed l\u00fd ngo\u1ea1i l\u1ec7 (Exception Handling) t\u00f9y ch\u1ec9nh<\/strong><\/h3>\n\n\n\n<p>Thay v\u00ec hi\u1ec3n th\u1ecb c\u00e1c trang l\u1ed7i m\u1eb7c \u0111\u1ecbnh c\u1ee7a Spring, h\u00e3y t\u00f9y ch\u1ec9nh ch\u00fang \u0111\u1ec3 mang l\u1ea1i tr\u1ea3i nghi\u1ec7m t\u1ed1t h\u01a1n cho ng\u01b0\u1eddi d\u00f9ng v\u00e0 API.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong><code>AuthenticationEntryPoint<\/code><\/strong>: T\u00f9y ch\u1ec9nh \u0111\u1ec3 x\u1eed l\u00fd c\u00e1c l\u1ed7i khi ng\u01b0\u1eddi d\u00f9ng ch\u01b0a \u0111\u01b0\u1ee3c x\u00e1c th\u1ef1c (v\u00ed d\u1ee5: tr\u1ea3 v\u1ec1 l\u1ed7i JSON 401 cho API thay v\u00ec chuy\u1ec3n h\u01b0\u1edbng \u0111\u1ebfn trang \u0111\u0103ng nh\u1eadp).<\/li>\n\n\n\n<li><strong><code>AccessDeniedHandler<\/code><\/strong>: T\u00f9y ch\u1ec9nh \u0111\u1ec3 x\u1eed l\u00fd khi ng\u01b0\u1eddi d\u00f9ng \u0111\u00e3 x\u00e1c th\u1ef1c nh\u01b0ng kh\u00f4ng \u0111\u1ee7 quy\u1ec1n truy c\u1eadp (v\u00ed d\u1ee5: tr\u1ea3 v\u1ec1 l\u1ed7i JSON 403 v\u1edbi th\u00f4ng b\u00e1o th\u00e2n thi\u1ec7n).<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-6-logging-va-giam-sat-cac-s\u1ef1-ki\u1ec7n-b\u1ea3o-m\u1eadt\"><strong>6. Logging v\u00e0 Gi\u00e1m s\u00e1t c\u00e1c s\u1ef1 ki\u1ec7n b\u1ea3o m\u1eadt<\/strong><\/h3>\n\n\n\n<p>H\u00e3y ghi log (ghi nh\u1eadt k\u00fd) l\u1ea1i c\u00e1c s\u1ef1 ki\u1ec7n b\u1ea3o m\u1eadt quan tr\u1ecdng, bao g\u1ed3m:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u0110\u0103ng nh\u1eadp th\u00e0nh c\u00f4ng v\u00e0 th\u1ea5t b\u1ea1i.<\/li>\n\n\n\n<li>C\u00e1c truy c\u1eadp b\u1ecb t\u1eeb ch\u1ed1i (l\u1ed7i 403).<\/li>\n\n\n\n<li>C\u00e1c thay \u0111\u1ed5i v\u1ec1 quy\u1ec1n h\u1ea1n c\u1ee7a ng\u01b0\u1eddi d\u00f9ng.<\/li>\n<\/ul>\n\n\n\n<p>Vi\u1ec7c gi\u00e1m s\u00e1t c\u00e1c log n\u00e0y gi\u00fap b\u1ea1n ph\u00e1t hi\u1ec7n s\u1edbm c\u00e1c ho\u1ea1t \u0111\u1ed9ng \u0111\u00e1ng ng\u1edd ho\u1eb7c c\u00e1c cu\u1ed9c t\u1ea5n c\u00f4ng ti\u1ec1m t\u00e0ng.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-7-b\u1ea3o-v\u1ec7-thong-tin-nh\u1ea1y-c\u1ea3m\"><strong>7. B\u1ea3o v\u1ec7 th\u00f4ng tin nh\u1ea1y c\u1ea3m<\/strong><\/h3>\n\n\n\n<p><strong>Kh\u00f4ng bao gi\u1edd hardcode<\/strong> c\u00e1c th\u00f4ng tin nh\u1ea1y c\u1ea3m nh\u01b0 m\u1eadt kh\u1ea9u database, API keys, hay secret key c\u1ee7a JWT tr\u1ef1c ti\u1ebfp v\u00e0o m\u00e3 ngu\u1ed3n ho\u1eb7c file properties. Thay v\u00e0o \u0111\u00f3, h\u00e3y s\u1eed d\u1ee5ng c\u00e1c ph\u01b0\u01a1ng ph\u00e1p an to\u00e0n h\u01a1n nh\u01b0:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Bi\u1ebfn m\u00f4i tr\u01b0\u1eddng (Environment Variables).<\/li>\n\n\n\n<li>C\u00e1c h\u1ec7 th\u1ed1ng qu\u1ea3n l\u00fd b\u00ed m\u1eadt chuy\u00ean d\u1ee5ng nh\u01b0 <strong>HashiCorp Vault<\/strong>, <strong>AWS Secrets Manager<\/strong>, ho\u1eb7c <strong>Azure Key Vault<\/strong>.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-cac-cau-h\u1ecfi-th\u01b0\u1eddng-g\u1eb7p-v\u1ec1-spring-boot-security\"><span class=\"ez-toc-section\" id=\"Cac_cau_hoi_thuong_gap_ve_Spring_Boot_Security\"><\/span><strong>C\u00e1c c\u00e2u h\u1ecfi th\u01b0\u1eddng g\u1eb7p v\u1ec1 Spring Boot Security<\/strong><span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-lam-th\u1ebf-nao-d\u1ec3-s\u1eed-d\u1ee5ng-jwt-json-web-token-thay-cho-session-cookie-m\u1eb7c-d\u1ecbnh\"><strong>L\u00e0m th\u1ebf n\u00e0o \u0111\u1ec3 s\u1eed d\u1ee5ng JWT (JSON Web Token) thay cho Session-Cookie m\u1eb7c \u0111\u1ecbnh?<\/strong><\/h3>\n\n\n\n<p>V\u1ec1 c\u01a1 b\u1ea3n b\u1ea1n c\u1ea7n:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>T\u1eaft t\u00ednh n\u0103ng CSRF v\u00e0 qu\u1ea3n l\u00fd phi\u00ean (session) c\u1ee7a Spring Security.<\/li>\n\n\n\n<li>T\u1ea1o m\u1ed9t b\u1ed9 l\u1ecdc (filter) \u0111\u1ec3 x\u1eed l\u00fd vi\u1ec7c t\u1ea1o token sau khi ng\u01b0\u1eddi d\u00f9ng \u0111\u0103ng nh\u1eadp th\u00e0nh c\u00f4ng.<\/li>\n\n\n\n<li>T\u1ea1o m\u1ed9t b\u1ed9 l\u1ecdc kh\u00e1c \u0111\u1ec3 x\u00e1c th\u1ef1c token t\u1eeb m\u1ed7i request \u0111\u1ebfn v\u00e0 thi\u1ebft l\u1eadp SecurityContext n\u1ebfu token h\u1ee3p l\u1ec7.<\/li>\n<\/ol>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-t\u1ea1i-sao-toi-nen-dung-jwt-cho-rest-api-thay-vi-session-m\u1eb7c-d\u1ecbnh\"><strong>T\u1ea1i sao t\u00f4i n\u00ean d\u00f9ng JWT cho REST API thay v\u00ec Session m\u1eb7c \u0111\u1ecbnh?<\/strong><\/h3>\n\n\n\n<p>V\u00ec REST API \u0111\u01b0\u1ee3c thi\u1ebft k\u1ebf theo nguy\u00ean t\u1eafc <strong>phi tr\u1ea1ng th\u00e1i (stateless)<\/strong>.<\/p>\n\n\n\n<p>Session m\u1eb7c \u0111\u1ecbnh l\u01b0u tr\u1eef tr\u1ea1ng th\u00e1i \u0111\u0103ng nh\u1eadp tr\u00ean server, \u0111i\u1ec1u n\u00e0y g\u00e2y kh\u00f3 kh\u0103n cho vi\u1ec7c m\u1edf r\u1ed9ng (scale) \u1ee9ng d\u1ee5ng v\u00e0 kh\u00f4ng ph\u00f9 h\u1ee3p v\u1edbi ki\u1ebfn tr\u00fac microservices.<\/p>\n\n\n\n<p>C\u00f2n JWT (JSON Web Token) ch\u1ee9a t\u1ea5t c\u1ea3 th\u00f4ng tin x\u00e1c th\u1ef1c b\u00ean trong ch\u00ednh n\u00f3. Server kh\u00f4ng c\u1ea7n l\u01b0u tr\u1eef g\u00ec c\u1ea3, gi\u00fap h\u1ec7 th\u1ed1ng d\u1ec5 d\u00e0ng m\u1edf r\u1ed9ng v\u00e0 c\u00e1c service c\u00f3 th\u1ec3 x\u00e1c th\u1ef1c token m\u1ed9t c\u00e1ch \u0111\u1ed9c l\u1eadp.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-lam-th\u1ebf-nao-d\u1ec3-b\u1ecf-qua-b\u1ea3o-m\u1eadt-cho-cac-tai-nguyen-tinh-nh\u01b0-css-javascript\"><strong>L\u00e0m th\u1ebf n\u00e0o \u0111\u1ec3 b\u1ecf qua b\u1ea3o m\u1eadt cho c\u00e1c t\u00e0i nguy\u00ean t\u0129nh nh\u01b0 CSS, JavaScript?<\/strong><\/h3>\n\n\n\n<p>B\u1ea1n c\u00f3 th\u1ec3 c\u1ea5u h\u00ecnh trong <code>SecurityFilterChain <\/code>\u0111\u1ec3 cho ph\u00e9p t\u1ea5t c\u1ea3 c\u00e1c request \u0111\u1ebfn c\u00e1c th\u01b0 m\u1ee5c ch\u1ee9a t\u00e0i nguy\u00ean t\u0129nh nh\u01b0 sau:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>@Bean\npublic SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {\n    http.authorizeHttpRequests(authorize -&gt; authorize\n        \/\/ Cho ph\u00e9p truy c\u1eadp kh\u00f4ng c\u1ea7n x\u00e1c th\u1ef1c v\u00e0o c\u00e1c t\u00e0i nguy\u00ean t\u0129nh\n        .requestMatchers(\"\/css\/**\", \"\/js\/**\", \"\/images\/**\").permitAll()\n        .anyRequest().authenticated()\n    );\n    return http.build();\n}<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-t\u1ed5ng-k\u1ebft\"><span class=\"ez-toc-section\" id=\"Tong_ket\"><\/span><strong>T\u1ed5ng k\u1ebft<\/strong><span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p><strong>Spring Boot Security<\/strong> \u0111\u00e3 \u0111\u01a1n gi\u1ea3n h\u00f3a \u0111\u00e1ng k\u1ec3 vi\u1ec7c b\u1ea3o m\u1eadt \u1ee9ng d\u1ee5ng Java. Nh\u1edd c\u01a1 ch\u1ebf t\u1ef1 \u0111\u1ed9ng c\u1ea5u h\u00ecnh v\u00e0 m\u1ed9t b\u1ed9 c\u00f4ng c\u1ee5 to\u00e0n di\u1ec7n, n\u00f3 gi\u00fap b\u1ea1n d\u1ec5 d\u00e0ng tri\u1ec3n khai m\u1ecdi th\u1ee9 t\u1eeb x\u00e1c th\u1ef1c c\u01a1 b\u1ea3n \u0111\u1ebfn c\u00e1c c\u01a1 ch\u1ebf ph\u00f2ng th\u1ee7 n\u00e2ng cao. B\u1eb1ng c\u00e1ch \u00e1p d\u1ee5ng nh\u1eefng ki\u1ebfn th\u1ee9c trong b\u00e0i vi\u1ebft n\u00e0y, b\u1ea1n c\u00f3 th\u1ec3 t\u1ef1 tin x\u00e2y d\u1ef1ng n\u00ean nh\u1eefng \u1ee9ng d\u1ee5ng kh\u00f4ng ch\u1ec9 gi\u00e0u t\u00ednh n\u0103ng m\u00e0 c\u00f2n v\u1eefng ch\u1eafc v\u00e0 an to\u00e0n.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Trong ph\u00e1t tri\u1ec3n \u1ee9ng d\u1ee5ng web, b\u1ea3o m\u1eadt l\u00e0 y\u1ebfu t\u1ed1 s\u1ed1ng c\u00f2n. V\u1edbi c\u00e1c \u1ee9ng d\u1ee5ng x\u00e2y d\u1ef1ng tr\u00ean n\u1ec1n t\u1ea3ng Spring, Spring Boot Security ch\u00ednh l\u00e0 &#8220;t\u1ea5m khi\u00ean&#8221; m\u1ea1nh m\u1ebd v\u00e0 linh ho\u1ea1t \u0111\u1ec3 ch\u1ed1ng l\u1ea1i c\u00e1c m\u1ed1i \u0111e d\u1ecda an ninh m\u1ea1ng. B\u00e0i vi\u1ebft n\u00e0y s\u1ebd h\u01b0\u1edbng d\u1eabn b\u1ea1n c\u00e1ch t\u00edch h\u1ee3p [&hellip;]<\/p>\n","protected":false},"author":203,"featured_media":93105,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"_gspb_post_css":"","footnotes":""},"categories":[109,10350],"tags":[],"class_list":["post-90567","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-chuyen-mon-it","category-java"],"blocksy_meta":[],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v26.8 (Yoast SEO v27.7) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\n<title>Spring Boot Security l\u00e0 g\u00ec? Kh\u00e1c g\u00ec v\u1edbi Spring Security? - ITviec Blog<\/title>\n<meta name=\"description\" content=\"Kh\u00e1m ph\u00e1 c\u00e1ch Spring Boot Security gi\u00fap b\u1ea3o m\u1eadt t\u1ed1t m\u00e0 kh\u00f4ng c\u1ea7n config ph\u1ee9c t\u1ea1p. Hi\u1ec3u r\u00f5 Spring Boot Security t\u1eeb kh\u00e1i ni\u1ec7m \u0111\u1ebfn n\u00e2ng cao.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/itviec.com\/blog\/spring-boot-security-la-gi\/\" \/>\n<meta property=\"og:locale\" content=\"vi_VN\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Spring Boot Security l\u00e0 g\u00ec? Kh\u00e1c g\u00ec v\u1edbi Spring Security?\" \/>\n<meta property=\"og:description\" content=\"Trong ph\u00e1t tri\u1ec3n \u1ee9ng d\u1ee5ng web, b\u1ea3o m\u1eadt l\u00e0 y\u1ebfu t\u1ed1 s\u1ed1ng c\u00f2n. V\u1edbi c\u00e1c \u1ee9ng d\u1ee5ng x\u00e2y d\u1ef1ng tr\u00ean n\u1ec1n t\u1ea3ng Spring, Spring Boot Security ch\u00ednh l\u00e0 &quot;t\u1ea5m khi\u00ean&quot; m\u1ea1nh\" \/>\n<meta property=\"og:url\" content=\"https:\/\/itviec.com\/blog\/spring-boot-security-la-gi\/\" \/>\n<meta property=\"og:site_name\" content=\"ITviec Blog\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/ITviec\" \/>\n<meta property=\"article:published_time\" content=\"2025-11-24T06:59:04+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2025-11-24T06:59:09+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/itviec.com\/blog\/wp-content\/uploads\/2025\/11\/spring-boot-security-scaled.png\" \/>\n\t<meta property=\"og:image:width\" content=\"800\" \/>\n\t<meta property=\"og:image:height\" content=\"421\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Tien Tran\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@ITviec\" \/>\n<meta name=\"twitter:site\" content=\"@ITviec\" \/>\n<meta name=\"twitter:label1\" content=\"\u0110\u01b0\u1ee3c vi\u1ebft b\u1edfi\" \/>\n\t<meta name=\"twitter:data1\" content=\"Tien Tran\" \/>\n\t<meta name=\"twitter:label2\" content=\"\u01af\u1edbc t\u00ednh th\u1eddi gian \u0111\u1ecdc\" \/>\n\t<meta name=\"twitter:data2\" content=\"25 ph\u00fat\" \/>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Spring Boot Security l\u00e0 g\u00ec? Kh\u00e1c g\u00ec v\u1edbi Spring Security? - ITviec Blog","description":"Kh\u00e1m ph\u00e1 c\u00e1ch Spring Boot Security gi\u00fap b\u1ea3o m\u1eadt t\u1ed1t m\u00e0 kh\u00f4ng c\u1ea7n config ph\u1ee9c t\u1ea1p. Hi\u1ec3u r\u00f5 Spring Boot Security t\u1eeb kh\u00e1i ni\u1ec7m \u0111\u1ebfn n\u00e2ng cao.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/itviec.com\/blog\/spring-boot-security-la-gi\/","og_locale":"vi_VN","og_type":"article","og_title":"Spring Boot Security l\u00e0 g\u00ec? Kh\u00e1c g\u00ec v\u1edbi Spring Security?","og_description":"Trong ph\u00e1t tri\u1ec3n \u1ee9ng d\u1ee5ng web, b\u1ea3o m\u1eadt l\u00e0 y\u1ebfu t\u1ed1 s\u1ed1ng c\u00f2n. V\u1edbi c\u00e1c \u1ee9ng d\u1ee5ng x\u00e2y d\u1ef1ng tr\u00ean n\u1ec1n t\u1ea3ng Spring, Spring Boot Security ch\u00ednh l\u00e0 \"t\u1ea5m khi\u00ean\" m\u1ea1nh","og_url":"https:\/\/itviec.com\/blog\/spring-boot-security-la-gi\/","og_site_name":"ITviec Blog","article_publisher":"https:\/\/www.facebook.com\/ITviec","article_published_time":"2025-11-24T06:59:04+00:00","article_modified_time":"2025-11-24T06:59:09+00:00","og_image":[{"width":800,"height":421,"url":"https:\/\/itviec.com\/blog\/wp-content\/uploads\/2025\/11\/spring-boot-security-scaled.png","type":"image\/png"}],"author":"Tien Tran","twitter_card":"summary_large_image","twitter_creator":"@ITviec","twitter_site":"@ITviec","twitter_misc":{"\u0110\u01b0\u1ee3c vi\u1ebft b\u1edfi":"Tien Tran","\u01af\u1edbc t\u00ednh th\u1eddi gian \u0111\u1ecdc":"25 ph\u00fat"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/itviec.com\/blog\/spring-boot-security-la-gi\/#article","isPartOf":{"@id":"https:\/\/itviec.com\/blog\/spring-boot-security-la-gi\/"},"author":{"name":"Tien Tran","@id":"https:\/\/itviec.com\/blog\/#\/schema\/person\/1595d671c49cfa2a48cd3c0a047a1298"},"headline":"Spring Boot Security l\u00e0 g\u00ec? Kh\u00e1c g\u00ec v\u1edbi Spring Security?","datePublished":"2025-11-24T06:59:04+00:00","dateModified":"2025-11-24T06:59:09+00:00","mainEntityOfPage":{"@id":"https:\/\/itviec.com\/blog\/spring-boot-security-la-gi\/"},"wordCount":6671,"publisher":{"@id":"https:\/\/itviec.com\/blog\/#organization"},"image":{"@id":"https:\/\/itviec.com\/blog\/spring-boot-security-la-gi\/#primaryimage"},"thumbnailUrl":"https:\/\/itviec.com\/blog\/wp-content\/uploads\/2025\/11\/spring-boot-security-scaled.png","articleSection":["Chuy\u00ean m\u00f4n IT","Java"],"inLanguage":"vi"},{"@type":"WebPage","@id":"https:\/\/itviec.com\/blog\/spring-boot-security-la-gi\/","url":"https:\/\/itviec.com\/blog\/spring-boot-security-la-gi\/","name":"Spring Boot Security l\u00e0 g\u00ec? Kh\u00e1c g\u00ec v\u1edbi Spring Security? - ITviec Blog","isPartOf":{"@id":"https:\/\/itviec.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/itviec.com\/blog\/spring-boot-security-la-gi\/#primaryimage"},"image":{"@id":"https:\/\/itviec.com\/blog\/spring-boot-security-la-gi\/#primaryimage"},"thumbnailUrl":"https:\/\/itviec.com\/blog\/wp-content\/uploads\/2025\/11\/spring-boot-security-scaled.png","datePublished":"2025-11-24T06:59:04+00:00","dateModified":"2025-11-24T06:59:09+00:00","description":"Kh\u00e1m ph\u00e1 c\u00e1ch Spring Boot Security gi\u00fap b\u1ea3o m\u1eadt t\u1ed1t m\u00e0 kh\u00f4ng c\u1ea7n config ph\u1ee9c t\u1ea1p. Hi\u1ec3u r\u00f5 Spring Boot Security t\u1eeb kh\u00e1i ni\u1ec7m \u0111\u1ebfn n\u00e2ng cao.","breadcrumb":{"@id":"https:\/\/itviec.com\/blog\/spring-boot-security-la-gi\/#breadcrumb"},"inLanguage":"vi","potentialAction":[{"@type":"ReadAction","target":["https:\/\/itviec.com\/blog\/spring-boot-security-la-gi\/"]}]},{"@type":"ImageObject","inLanguage":"vi","@id":"https:\/\/itviec.com\/blog\/spring-boot-security-la-gi\/#primaryimage","url":"https:\/\/itviec.com\/blog\/wp-content\/uploads\/2025\/11\/spring-boot-security-scaled.png","contentUrl":"https:\/\/itviec.com\/blog\/wp-content\/uploads\/2025\/11\/spring-boot-security-scaled.png","width":800,"height":421,"caption":"spring boot security - itviec blog"},{"@type":"BreadcrumbList","@id":"https:\/\/itviec.com\/blog\/spring-boot-security-la-gi\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Chuy\u00ean m\u00f4n IT","item":"https:\/\/itviec.com\/blog\/chuyen-mon-it\/"},{"@type":"ListItem","position":2,"name":"Spring Boot Security l\u00e0 g\u00ec? Kh\u00e1c g\u00ec v\u1edbi Spring Security?"}]},{"@type":"WebSite","@id":"https:\/\/itviec.com\/blog\/#website","url":"https:\/\/itviec.com\/blog\/","name":"ITviec Blog","description":"IT Jobs &amp; People in Vietnam","publisher":{"@id":"https:\/\/itviec.com\/blog\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/itviec.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"vi"},{"@type":"Organization","@id":"https:\/\/itviec.com\/blog\/#organization","name":"ITviec","url":"https:\/\/itviec.com\/blog\/","logo":{"@type":"ImageObject","inLanguage":"vi","@id":"https:\/\/itviec.com\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/itviec.com\/blog\/wp-content\/uploads\/2018\/12\/itviec-black-square-facebook.png","contentUrl":"https:\/\/itviec.com\/blog\/wp-content\/uploads\/2018\/12\/itviec-black-square-facebook.png","width":1800,"height":1800,"caption":"ITviec"},"image":{"@id":"https:\/\/itviec.com\/blog\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/ITviec","https:\/\/x.com\/ITviec","https:\/\/www.linkedin.com\/company\/itviec","https:\/\/www.youtube.com\/channel\/UCYthAQ3bcGr57M_ag5gHDvQ"]},{"@type":"Person","@id":"https:\/\/itviec.com\/blog\/#\/schema\/person\/1595d671c49cfa2a48cd3c0a047a1298","name":"Tien Tran","image":{"@type":"ImageObject","inLanguage":"vi","@id":"https:\/\/itviec.com\/blog\/wp-content\/uploads\/2024\/05\/tien-tran-author-e1715658627643-100x100.jpg","url":"https:\/\/itviec.com\/blog\/wp-content\/uploads\/2024\/05\/tien-tran-author-e1715658627643-100x100.jpg","contentUrl":"https:\/\/itviec.com\/blog\/wp-content\/uploads\/2024\/05\/tien-tran-author-e1715658627643-100x100.jpg","caption":"Tien Tran"},"url":"https:\/\/itviec.com\/blog\/author\/tien-tran\/"}]}},"_links":{"self":[{"href":"https:\/\/itviec.com\/blog\/wp-json\/wp\/v2\/posts\/90567","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/itviec.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/itviec.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/itviec.com\/blog\/wp-json\/wp\/v2\/users\/203"}],"replies":[{"embeddable":true,"href":"https:\/\/itviec.com\/blog\/wp-json\/wp\/v2\/comments?post=90567"}],"version-history":[{"count":4,"href":"https:\/\/itviec.com\/blog\/wp-json\/wp\/v2\/posts\/90567\/revisions"}],"predecessor-version":[{"id":93106,"href":"https:\/\/itviec.com\/blog\/wp-json\/wp\/v2\/posts\/90567\/revisions\/93106"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/itviec.com\/blog\/wp-json\/wp\/v2\/media\/93105"}],"wp:attachment":[{"href":"https:\/\/itviec.com\/blog\/wp-json\/wp\/v2\/media?parent=90567"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/itviec.com\/blog\/wp-json\/wp\/v2\/categories?post=90567"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/itviec.com\/blog\/wp-json\/wp\/v2\/tags?post=90567"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}