5.3.2 Tạo trang đăng nhập tùy chỉnh
Trang đăng nhập mặc định tốt hơn nhiều so với hộp thoại HTTP Basic đơn giản ban đầu, nhưng nó vẫn khá đơn điệu và không phù hợp với giao diện tổng thể của ứng dụng Taco Cloud.
Để thay thế trang đăng nhập tích hợp sẵn, trước tiên bạn cần thông báo cho Spring Security biết đường dẫn của trang đăng nhập tùy chỉnh của bạn. Điều này có thể được thực hiện bằng cách gọi formLogin() trên đối tượng HttpSecurity, như sau:
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
return http
.authorizeRequests()
.antMatchers("/design", "/orders").access("hasRole('USER')")
.antMatchers("/", "/**").access("permitAll()")
.and()
.formLogin()
.loginPage("/login")
.and()
.build();
}Lưu ý rằng trước khi gọi formLogin(), bạn nối phần cấu hình này với phần cấu hình trước đó bằng cách gọi and(). Phương thức and() biểu thị rằng bạn đã hoàn thành cấu hình ủy quyền và sẵn sàng áp dụng một số cấu hình HTTP bổ sung. Bạn sẽ sử dụng and() nhiều lần khi bắt đầu các phần cấu hình mới.
Sau phần nối, bạn gọi formLogin() để bắt đầu cấu hình biểu mẫu đăng nhập tùy chỉnh. Lệnh gọi loginPage() tiếp theo chỉ định đường dẫn nơi bạn cung cấp trang đăng nhập tùy chỉnh. Khi Spring Security xác định rằng người dùng chưa xác thực và cần đăng nhập, nó sẽ chuyển hướng họ đến đường dẫn này.
Bây giờ bạn cần cung cấp một controller xử lý các yêu cầu tại đường dẫn đó. Vì trang đăng nhập của bạn sẽ khá đơn giản—chỉ là một view—nên bạn có thể dễ dàng khai báo nó dưới dạng view controller trong WebConfig. Phương thức addViewControllers() sau đây thiết lập view controller cho trang đăng nhập cùng với view controller ánh xạ “/” tới controller trang chủ:
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("home");
registry.addViewController("/login");
}Cuối cùng, bạn cần định nghĩa chính view của trang đăng nhập. Vì bạn đang sử dụng Thymeleaf làm công cụ template, mẫu Thymeleaf sau đây là đủ dùng:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org">
<head>
<title>Taco Cloud</title>
</head>
<body>
<h1>Login</h1>
<img th:src="@{/images/TacoCloud.png}"/>
<div th:if="${error}">
Unable to login. Check your username and password.
</div>
<p>New here? Click
<a th:href="@{/register}">here</a> to register.</p>
<form method="POST" th:action="@{/login}" id="loginForm">
<label for="username">Username: </label>
<input type="text" name="username" id="username" /><br/>
<label for="password">Password: </label>
<input type="password" name="password" id="password" /><br/>
<input type="submit" value="Login"/>
</form>
</body>
</html>Điểm mấu chốt cần chú ý trong trang đăng nhập này là đường dẫn mà biểu mẫu gửi tới và tên của các trường tên người dùng và mật khẩu. Theo mặc định, Spring Security lắng nghe các yêu cầu đăng nhập tại /login và mong đợi các trường tên người dùng và mật khẩu có tên lần lượt là username và password. Tuy nhiên, điều này có thể cấu hình lại. Ví dụ, cấu hình sau đây tùy chỉnh đường dẫn và tên trường:
.and()
.formLogin()
.loginPage("/login")
.loginProcessingUrl("/authenticate")
.usernameParameter("user")
.passwordParameter("pwd")Tại đây, bạn chỉ định rằng Spring Security nên lắng nghe các yêu cầu đến /authenticate để xử lý đăng nhập. Ngoài ra, các trường tên người dùng và mật khẩu giờ sẽ có tên là user và pwd.
Theo mặc định, nếu đăng nhập thành công, người dùng sẽ được đưa đến trang mà họ đang truy cập trước khi bị chuyển hướng đến trang đăng nhập. Nếu người dùng truy cập trực tiếp trang đăng nhập, sau khi đăng nhập thành công, họ sẽ được chuyển đến đường dẫn gốc (ví dụ: trang chủ). Tuy nhiên, bạn có thể thay đổi điều đó bằng cách chỉ định trang đích mặc định như sau:
.and()
.formLogin()
.loginPage("/login")
.defaultSuccessUrl("/design")Như được cấu hình ở đây, nếu người dùng đăng nhập thành công sau khi truy cập trực tiếp trang đăng nhập, họ sẽ được chuyển đến trang /design.
Ngoài ra, bạn có thể buộc người dùng luôn được chuyển tới trang /design sau khi đăng nhập, ngay cả khi trước đó họ đang truy cập trang khác, bằng cách truyền true làm tham số thứ hai cho defaultSuccessUrl như sau:
.and()
.formLogin()
.loginPage("/login")
.defaultSuccessUrl("/design", true)Đăng nhập bằng tên người dùng và mật khẩu là cách phổ biến nhất để xác thực trong một ứng dụng web. Nhưng hãy cùng xem một cách khác để xác thực người dùng bằng cách sử dụng trang đăng nhập của bên thứ ba.
