- Sản phẩm & Dịch vụSản phẩm & Dịch vụ
- Giải phápGiải pháp
- Bảng giáBảng giá
- Công tyCông ty
- Tài liệuTài liệu
vi
vi
Chuyên mục với các bài viết hướng dẫn, nghiên cứu và phân tích chi tiết về kỹ thuật, các xu hướng công nghệ mới nhất dành cho lập trình viên.
Technical Writer
I have over 5 years of experience writing technical documentation for tech products, making them accessible and user-friendly. My focus is always on providing clear and precise information. @#@ Tôi đã có hơn 5 năm kinh nghiệm viết tài liệu kỹ thuật cho các sản phẩm công nghệ, giúp người dùng dễ dàng tiếp cận và sử dụng. Tôi luôn tập trung vào việc cung cấp thông tin chính xác và dễ hiểu.
Thảo luận (0)
Đăng nhập để thảo luận
Hôm nay, chúng ta sẽ tìm hiểu cách phân quyền truy cập ****theo vai trò người dùng (role-based access) trong Spring Security. Tuy nhiên, trước khi đọc bài viết này, bạn nên tham khảo bài viết trước: “Spring 4 Security MVC Login Logout Example” để nắm được những kiến thức cơ bản về Spring Security.
Trong bài viết này, chúng ta sẽ cùng tìm hiểu cách định nghĩa, sử dụng và quản lý các vai trò bảo mật (security roles) như "USER", "ADMIN" trong ứng dụng web sử dụng Spring Security.
Tương tự như ví dụ ở bài trước, bài viết này cũng sử dụng Spring 4 MVC Security, kết hợp với In-Memory Store và Spring Java Configuration để xây dựng ứng dụng.
Điều này có nghĩa là chúng ta sẽ:
web.xmlThay vào đó, chúng ta sẽ sử dụng In-Memory Store để quản lý tài khoản và quyền truy cập.
Công nghệ sử dụng trong ví dụ:
SpringMVCSecruityMavenRolesApppom.xml từ bài viết trước, với một vài chỉnh sửa nhỏ để phù hợp với ví dụ hiện tại.<artifactId>SpringMVCSecruityMavenRolesApp</artifactId><build> <finalName>SpringMVCSecruityMavenRolesApp</finalName> </build> </project>
LoginSecurityConfig.java để cấu hình vai trò người dùng "USER" và "ADMIN"package com.journaldev.spring.secuity.config;import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
@Configuration @EnableWebSecurity public class LoginSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired public void configureGlobal(AuthenticationManagerBuilder authenticationMgr) throws Exception { authenticationMgr.inMemoryAuthentication() .withUser("jduser").password("jdu@123").authorities("ROLE_USER") .and() .withUser("jdadmin").password("jda@123").authorities("ROLE_USER","ROLE_ADMIN"); } @Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .antMatchers("/homePage").access("hasRole('ROLE_USER') or hasRole('ROLE_ADMIN')") .antMatchers("/userPage").access("hasRole('ROLE_USER')") .antMatchers("/adminPage").access("hasRole('ROLE_ADMIN')") .and() .formLogin().loginPage("/loginPage") .defaultSuccessUrl("/homePage") .failureUrl("/loginPage?error") .usernameParameter("username").passwordParameter("password") .and() .logout().logoutSuccessUrl("/loginPage?logout"); }}
configureGlobal(), chúng ta đã thêm hai người dùng:
Một người dùng có vai trò "ROLE_USER"
Một người dùng khác có cả "ROLE_USER" và "ROLE_ADMIN"
Điều này có nghĩa là người dùng thứ hai sẽ đóng vai trò quản trị viên (Admin).
authorities() và roles()
Phương thức authorities() yêu cầu viết đầy đủ tên role, ví dụ: "ROLE_USER"
Phương thức roles() chỉ cần tên vai trò như "USER". Spring sẽ tự động thêm tiền tố ROLE_.
configure(), chúng ta đã cấu hình các đường dẫn URL với role yêu cầu tương ứng.antMatchers("/homePage")
.access("hasRole('ROLE_USER') or hasRole('ROLE_ADMIN')")
Đoạn mã này quy định rằng đường dẫn /homePage có thể được truy cập bởi cả người dùng có vai trò "USER" và "ADMIN".
.antMatchers("/userPage").access("hasRole('ROLE_USER')")
.antMatchers("/adminPage").access("hasRole('ROLE_ADMIN')")
Đoạn mã trên cấu hình như sau:
/userPage: chỉ những người dùng có vai trò "USER" mới được truy cập./adminPage: chỉ những người dùng có vai trò "ADMIN" mới được truy cập.Nếu người dùng không có vai trò phù hợp mà cố truy cập vào những đường dẫn này, hệ thống sẽ trả về lỗi: “403 Access is Denied”
LoginController.java để định nghĩa các đường dẫn mới (/userPage và /adminPage) như sau:package com.journaldev.spring.web.controller;import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.servlet.ModelAndView;
@Controller public class LoginController {
@RequestMapping(value = { "/"}, method = RequestMethod.GET) public ModelAndView welcomePage() { ModelAndView model = new ModelAndView(); model.setViewName("welcomePage"); return model; } @RequestMapping(value = { "/homePage"}, method = RequestMethod.GET) public ModelAndView homePage() { ModelAndView model = new ModelAndView(); model.setViewName("homePage"); return model; } @RequestMapping(value = {"/userPage"}, method = RequestMethod.GET) public ModelAndView userPage() { ModelAndView model = new ModelAndView(); model.setViewName("userPage"); return model; } @RequestMapping(value = {"/adminPage"}, method = RequestMethod.GET) public ModelAndView adminPage() { ModelAndView model = new ModelAndView(); model.setViewName("adminPage"); return model; } @RequestMapping(value = "/loginPage", method = RequestMethod.GET) public ModelAndView loginPage(@RequestParam(value = "error",required = false) String error, @RequestParam(value = "logout", required = false) String logout) { ModelAndView model = new ModelAndView(); if (error != null) { model.addObject("error", "Invalid Credentials provided."); } if (logout != null) { model.addObject("message", "Logged out from JournalDEV successfully."); } model.setViewName("loginPage"); return model; }}
Bên cạnh ví dụ từ bài viết trước, lần này chúng ta đã thêm hai đường dẫn URL mới:
/userPage: dành cho người dùng có vai trò "USER" để truy cập và thực hiện các chức năng thông thường./adminPage: dành riêng cho người dùng có vai trò "ADMIN" để truy cập và thực hiện các chức năng quản trị. Người dùng có vai trò "ADMIN" cũng có thể truy cập vào /userPage.homePage.jsp đã được cập nhật để cung cấp các hoạt động riêng biệt dành cho người dùng thuộc vai trò User và Admin**.**<%@taglib prefix="c" uri="<https://java.sun.com/jsp/jstl/core>"%>
<a href="${pageContext.request.contextPath}/userPage">JD User</a> | <a href="${pageContext.request.contextPath}/adminPage">JD Admin</a> | <a href="javascript:document.getElementById('logout').submit()">Logout</a>
<h3>Welcome to JournalDEV Tutorials</h3>
<ul>
<li>Java 8 tutorial</li>
<li>Spring tutorial</li>
<li>Gradle tutorial</li>
<li>BigData tutorial</li>
</ul>
<c:url value="/logout" var="logoutUrl" />
<form id="logout" action="${logoutUrl}" method="post" >
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" />
</form>
Trong phần đầu của trang, chúng ta đã thêm ba tùy chọn menu. Liên kết "Logout" đã được trình bày trong bài viết trước. Hai liên kết mới được thêm vào gồm:
JD User – Có thể được truy cập bởi cả người dùng có vai trò "USER" và "ADMIN".
JD Admin – Chỉ có người dùng có vai trò ****"ADMIN" mới có quyền truy cập.
Lưu ý:
"JD User" đối với người dùng có vai trò ****"USER", và ẩn liên kết "JD Admin" nếu người dùng không có quyền quản trị. Tuy nhiên, để kiểm tra xem người dùng "USER" có bị chặn đúng cách hay không khi truy cập vào liên kết "JD Admin", cũng như để xem rõ thông báo lỗi, trong ví dụ này chúng ta không ẩn liên kết đó.adminPage.jsp – Trang chủ dành riêng cho vai trò "ADMIN"<%@taglib prefix="c" uri="<https://java.sun.com/jsp/jstl/core>"%> <h3>Welcome to JournalDEV Tutorials</h3> <h3>Admin Page</h3><c:url value="/logout" var="logoutUrl" /> <form id="logout" action="${logoutUrl}" method="post" > <input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" /> </form> <c:if test="${pageContext.request.userPrincipal.name != null}"> <a href="javascript:document.getElementById('logout').submit()">Logout</a> </c:if>
userPage.jsp – Trang chủ dành cho vai trò "USER"<%@taglib prefix="c" uri="<https://java.sun.com/jsp/jstl/core>"%> <h3>Welcome to JournalDEV Tutorials</h3> <h3>User Page</h3><c:url value="/logout" var="logoutUrl" /> <form id="logout" action="${logoutUrl}" method="post" > <input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" /> </form> <c:if test="${pageContext.request.userPrincipal.name != null}"> <a href="javascript:document.getElementById('logout').submit()">Logout</a> </c:if>
Chúng ta đã hoàn tất quá trình phát triển ứng dụng. Bây giờ là lúc kiểm tra cấu trúc cuối cùng của dự án và chạy thử.



"USER":jdadminjda@123
"JD Admin", "JD User","Logout""JD User"Vì bạn đã đăng nhập bằng tài khoản có vai trò "USER", nên bạn có thể truy cập thành công liên kết này như hình minh họa bên dưới.

"JD Admin".
Vì bạn đã đăng nhập bằng tài khoản có vai trò "USER", nên không thể truy cập vào liên kết "JD Admin".
→ Kết quả là bạn sẽ thấy thông báo lỗi: 403 Access is denied.
jdadminjda@123Lần này, bạn có thể truy cập thành công vào liên kết "JD Admin" như hình minh họa bên dưới.

"Logout" để đăng xuất khỏi ứng dụng.Như vậy là bạn đã xem hoàn tất ví dụ về phân quyền truy cập theo vai trò trong Spring Security, giúp kiểm soát quyền truy cập vào các trang trong ứng dụng web một cách hiệu quả và an toàn.