[Thực hành] Sử dụng Spring Security

14. Bảo mật

Mục tiêu

Luyện tập việc sử dụng Spring Security trong một ứng dụng Spring MVC.

Mô tả

Trong phần này, chúng ta sẽ tích hợp Spring Security vào trong một ứng dụng Spring MVC. Ứng dụng sẽ có một form để đăng nhập, link để đăng xuất.

Các tài nguyên của hệ thống được được cấu hình cấp quyền truy cập phù hợp cho các đối tượng đã đăng nhập và chưa đăng nhập.

Hướng dẫn

Bước 1: Tạo dự án Spring MVC.

Để tạo mới dự án, các bạn chọn File -> New -> Project.

Sau đó chọn Gradle -> Tích chọn Java, Web -> Chọn Next

Bạn nhập thông tin vào GroupId, và ArtifactId. Sau đó nhấn Next:

Màn hình sau đó bạn tiếp tục nhấn Next:

Nhập vào Project name, Project location. Sau đó nhấn Finish.

Bước 2: Tạo cấu trúc của dự án.

Bạn tạo cấu trúc của dự án như sau. Nhớ xóa file index.jsp trong trong thư mục webapp.

Bước 3: Cấu hình dependency trong build.gradle:

configurations {
provided
provided.extendsFrom(compile)
}

dependencies {
// https://mvnrepository.com/artifact/org.springframework/spring-webmvc
compile group: 'org.springframework', name: 'spring-webmvc', version: '4.3.10.RELEASE'
// https://mvnrepository.com/artifact/org.springframework.security/spring-security-web
compile group: 'org.springframework.security', name: 'spring-security-web', version: '4.2.3.RELEASE'
// https://mvnrepository.com/artifact/org.springframework.security/spring-security-config
compile group: 'org.springframework.security', name: 'spring-security-config', version: '4.2.3.RELEASE'
// https://mvnrepository.com/artifact/org.springframework.security/spring-security-taglibs
compile group: 'org.springframework.security', name: 'spring-security-taglibs', version: '4.2.3.RELEASE'
providedCompile group: 'javax.servlet', name: 'javax.servlet-api', version: '3.0.1'
compile group: 'org.thymeleaf', name: 'thymeleaf-spring4', version: '3.0.4.RELEASE'
// https://mvnrepository.com/artifact/org.thymeleaf.extras/thymeleaf-extras-springsecurity4
compile group: 'org.thymeleaf.extras', name: 'thymeleaf-extras-springsecurity4', version: '3.0.2.RELEASE'
}

Bước 4: Tạo class cấu hình spring security

Bước đầu tiên là tạo một class @Configuration bằng cách extending class WebSecurityConfigurerAdapter 

package com.codegym;

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;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;

@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("user").password("12345").roles("USER")
.and()
.withUser("admin").password("12345").roles("ADMIN");
}

@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/").permitAll()
.and()
.authorizeRequests().antMatchers("/user**").hasRole("USER")
.and()
.authorizeRequests().antMatchers("/admin**").hasRole("ADMIN")
.and()
.formLogin()
.and()
.logout().logoutRequestMatcher(new AntPathRequestMatcher("/logout"));
}
}
  • Lớp cấu hình Java này tạo ra một bộ lọc Servlet được gọi là springSecurityFilterChain, chịu trách nhiệm bảo mật tất cả (bảo vệ URL ứng dụng, xác nhận username và password, chuyển hướng tới form đăng nhập…) trong ứng dụng.
  • Phương thức Override configure(AuthenticationManagerBuilder auth) cấu hình xác thực bộ nhớ với thông tin đăng nhập và vai trò của người dùng.
  • Phương thức Override configure(HttpSecurity http) cấu hình bảo mật dựa trên web cho tất cả các yêu cầu HTTP. Theo mặc định, nó sẽ được áp dụng cho tất cả các yêu cầu, nhưng có thể bị hạn chế bằng cách sử dụng requestMatcher () hoặc các phương thức tương tự khác.
  • Url ‘/’ không được bảo mật và có thể được truy cập bởi bất kỳ ai.
  • Bất kỳ URL nào bắt đầu bằng ‘/user’ đều được bảo mật và chỉ những người dùng nào có vai trò ‘USER’ mới có thể truy cập được.
  • Bất kỳ URL nào bắt đầu bằng ‘/admin’ đều được bảo mật và chỉ những người dùng nào có vai trò ‘ADMIN’ mới có thể truy cập được.

Bước 5: Đăng ký springSecurityFilterChain

Trong cấu hình Java, bạn có thể đăng ký springSecurityFilterChain
bằng cách sử dụng base class AbstractSecurityWebApplicationInitializer

package com.codegym;

import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer;

public class SecurityWebApplicationInitializer
extends AbstractSecurityWebApplicationInitializer {

}

Cấu hình này chỉ đăng ký bộ lọc springSecurityFilterChain
cho mỗi URL cho ứng dụng của bạn.

Bước 6: Tạo lớp cấu hình Spring Web

package com.codegym;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.extras.springsecurity4.dialect.SpringSecurityDialect;
import org.thymeleaf.spring4.SpringTemplateEngine;
import org.thymeleaf.spring4.templateresolver.SpringResourceTemplateResolver;
import org.thymeleaf.spring4.view.ThymeleafViewResolver;
import org.thymeleaf.templatemode.TemplateMode;


@Configuration
@ComponentScan("com.codegym.controller")
@EnableWebMvc
public class WebConfig implements ApplicationContextAware {

@Bean
public SpringResourceTemplateResolver templateResolver(){
SpringResourceTemplateResolver templateResolver = new SpringResourceTemplateResolver();
templateResolver.setApplicationContext(applicationContext);
templateResolver.setPrefix("/WEB-INF/views/");
templateResolver.setSuffix(".html");
templateResolver.setTemplateMode(TemplateMode.HTML);
return templateResolver;
}

@Bean
public TemplateEngine templateEngine(){
TemplateEngine templateEngine = new SpringTemplateEngine();
templateEngine.setTemplateResolver(templateResolver());
templateEngine.addDialect(new SpringSecurityDialect());
return templateEngine;
}

@Bean
public ViewResolver viewResolver(){
ThymeleafViewResolver viewResolver = new ThymeleafViewResolver();
viewResolver.setTemplateEngine(templateEngine());
return viewResolver;
}
private ApplicationContext applicationContext;

@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
}

Bước 7: Tạo lớp khởi tạo ứng dụng

package com.codegym;

import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;

public class MvcWebApplicationInitializer
extends AbstractAnnotationConfigDispatcherServletInitializer {

@Override
protected Class<?>[] getRootConfigClasses() {
return new Class[] { WebSecurityConfig.class };
}

@Override
protected Class<?>[] getServletConfigClasses() {
return new Class[] { WebConfig.class };
}

@Override
protected String[] getServletMappings() {
return new String[] { "/" };
}
}

Bước 8: Tạo controller

package com.codegym.controller;

import java.security.Principal;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

@Controller
public class UserController {

@GetMapping("/")
public String index() {
return "index";
}

@GetMapping("/user")
public String user(Principal principal) {
// Get authenticated user name from Principal
System.out.println(principal.getName());
return "user";
}

@GetMapping("/admin")
public String admin() {
// Get authenticated user name from SecurityContext
SecurityContext context = SecurityContextHolder.getContext();
System.out.println(context.getAuthentication().getName());
return "admin";
}
}

Bước 9: Tạo các views

9.1. Trang index.html

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"
xmlns:sec="http://www.thymeleaf.org/extras/spring-security">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Spring Security Example</title>
</head>
<body>
<h2>Spring Security Example</h2>
<hr/>
<h3>
Welcome !
<!-- Print the logged in user name -->
<div sec:authorize="isAuthenticated()">
<span sec:authentication="principal.username"></span>
</div>
</h3>
<div sec:authorize="isAnonymous()">
Login as <a th:href="@{/user}">User</a> or <a th:href="@{/admin}">Admin</a>
</div>
<div sec:authorize="isAuthenticated()">
<div sec:authorize="hasRole('USER')">
<a th:href="@{/user}">My Profile</a>
</div>
<div sec:authorize="hasRole('ADMIN')">
<a th:href="@{/admin}">My Profile</a>
</div>
<a th:href="@{/logout}">Logout</a>
</div>
</body>
</html>

9.2. Trang user.html

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"
xmlns:sec="http://www.thymeleaf.org/extras/spring-security">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Spring Security Example</title>
</head>
<body>
<h2>Spring Security Example</h2>
<hr/>
<h3>User dashboard</h3>
<div sec:authorize="isAuthenticated()">
<b>Welcome!<span sec:authentication="principal.username"></span></b>
</div>
<br/>
<div sec:authorize="isAuthenticated()">
<a th:href="@{/}">Home</a> | <a th:href="@{/logout}">Logout</a>
</div>
</body>
</html>

9.3. Trang admin.html

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"
xmlns:sec="http://www.thymeleaf.org/extras/spring-security">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Spring Security Example</title>
</head>
<body>
<h2>Spring Security Example</h2>
<hr/>
<h3>Admin dashboard</h3>
<div sec:authorize="isAuthenticated()">
<b>Welcome!
<div sec:authentication="principal.username"/>
</b>
</div>
<br/>
<div sec:authorize="isAuthenticated()">
<a th:href="@{/}">Home</a> | <a th:href="@{/logout}">Logout</a>
</div>
</body>
</html>

Trong đó:

  • sec:authorize sẽ đánh giá quyền truy cập
  • sec:authentication sẽ truy cập đối tượng Authentication hiện tại

Bước 10: Cấu hình Artifact và Tomcat

Bước 11: Chạy ứng dụng

  • Bạn truy cập vào link User (user: user, pass: 12345)
  • Bạn truy cập vào link Admin (user: admin, pass: 12345)

Bạn có thể nhập đúng hoặc sai user và pass rồi quan sát kết quả.

Dưới đây là ví dụ truy cập và link User và đăng nhập đúng user và pass:

Mã nguồn tham khảo: https://github.com/codegym-vn/java-spring-security

Leave a Reply

Your email address will not be published. Required fields are marked *