Spring security remember me

Hôm nay mình xin chia sẻ kỹ thuật login remenber username password trong spring security. Cơ chế hoạt động của spring remember me tiện lợi hơn cho người dùng khi muốn quay trở lại sử dụng ứng dụng mà không cần login. Cụ thể khi người dùng lần đầu tiên login thành công thì ứng dụng sẽ tạo ra một cookie trên trình duyệt lưu thông tin xác thực của người dùng. Và cookie này sẽ tồn tại trên trình duyệt web cho đến khi người dùng bấm vào logout. Nếu như người dùng không bấm vào logout mà chỉ đơn giản là tắt trình duyệt đi, như vậy ở lần truy cập sau này người dùng sẽ không phải xác thực lại nữa. Ứng dụng sẽ đọc cookie của người dùng từ trình duyệt và lấy ra thông tin cho việc xác thực. Sau đây mình sẽ đi xây dựng một ví dụ về spring remember me.

  • Mình sẽ view cấu trúc project lên để các bạn tiện theo rõi. Một cấu trúc theo chuẩn maven
  • Đây là trang login.jsp mình xây dựng như sau
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@page session="true"%>
<html>
<head>
<title>Login Page</title>
<style>
.error {
	padding: 15px;
	margin-bottom: 20px;
	border: 1px solid transparent;
	border-radius: 4px;
	color: #a94442;
	background-color: #f2dede;
	border-color: #ebccd1;
}

.msg {
	padding: 15px;
	margin-bottom: 20px;
	border: 1px solid transparent;
	border-radius: 4px;
	color: #31708f;
	background-color: #d9edf7;
	border-color: #bce8f1;
}

#login-box {
	width: 300px;
	padding: 20px;
	margin: 100px auto;
	background: #fff;
	-webkit-border-radius: 2px;
	-moz-border-radius: 2px;
	border: 1px solid #000;
}
</style>
</head>
<body onload='document.loginForm.username.focus();'>

	<h1>Spring Security Login</h1>
	<div id="login-box">
		<h3>Login with Username and Password</h3>
		<form name='loginForm' action="<c:url value='/auth/login_check' />" method='POST'>
			<table>
				<tr>
					<td>User:</td>
					<td><input type='text' name='username'></td>
				</tr>
				<tr>
					<td>Password:</td>
					<td><input type='password' name='password' /></td>
				</tr>
				<!-- if this is login for update, ignore remember me check -->
				<c:if test="${empty loginUpdate}">
					<tr>
						<td></td>
						<td>Remember Me: <input type="checkbox" name="remember-me" /></td>
					</tr>
				</c:if>
				<tr>
					<td colspan='2'><input name="submit" type="submit" value="submit" /></td>
				</tr>
			</table>
			<input type="hidden" name="${_csrf.parameterName}"value="${_csrf.token}" />
		</form>
	</div>
</body>
</html>

Lưu ý là tên checkbox name="remember-me" phải giống với remember-me-parameter trong file spring-security.xml như bên dưới.

  • Đây là file cấu hình spring-security.xml
<beans:beans xmlns="http://www.springframework.org/schema/security"
	xmlns:beans="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
	http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
	http://www.springframework.org/schema/security
	http://www.springframework.org/schema/security/spring-security-3.2.xsd">

	<!-- enable use-expressions -->
	<http auto-config="true" use-expressions="true">

		<intercept-url pattern="/admin**" access="hasRole('ROLE_ADMIN')" />
		<access-denied-handler error-page="/403" />
		<form-login login-page="/login" 
		    default-target-url="/welcome"
			authentication-failure-url="/login?error" 
			username-parameter="username"
			password-parameter="password" 
			login-processing-url="/auth/login_check"/>

		<logout logout-success-url="/login?logout" delete-cookies="JSESSIONID" />
		<!-- enable csrf protection -->
		<csrf />

		<remember-me 
		    token-validity-seconds="1209600"
			remember-me-parameter="remember-me"  
			 />
	</http>

	<authentication-manager>
		<authentication-provider>
			<user-service>
				<user name="tomcruies" authorities="ROLE_USER" password="123" />
				<user name="shara" authorities="ROLE_ADMIN" password="123" />
			</user-service>
		</authentication-provider>
	</authentication-manager>
</beans:beans>

Trong file cấu hình mình chỉ đơn giản sử dụng thẻ <remember-me> với thuộc tính remember-me-parameter="remember-me" chỉ ra tên của cookie chứa thông tin xác thực của người dùng sẽ được lưu lại ở trình duyệt. *Tiếp đến là file MainControll.java

package com.web.controller;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.springframework.security.authentication.RememberMeAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
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 MainController {
	
	@RequestMapping(value = { "/","/welcome**" }, method = RequestMethod.GET)
	public ModelAndView defaultPage() {

		ModelAndView model = new ModelAndView();
		model.addObject("title", "Welcome Page Home");
		model.setViewName("hello");
		return model;

	}

	@RequestMapping(value = "/admin**", method = RequestMethod.GET)
	public ModelAndView adminPage() {

		ModelAndView model = new ModelAndView();
		model.addObject("title", "Pages Admin");
		model.setViewName("admin");

		return model;

	}

	@RequestMapping(value = "/login", method = RequestMethod.GET)
	public ModelAndView login(HttpServletRequest request) {
		ModelAndView model = new ModelAndView();
		model.addObject("error", "Invalid username and password!");
		model.setViewName("login");
		return model;
	}

}
  • Một file cũng rất quan trọng trong ứng dụng web là file web.xml mình cấu hình như sau
<web-app id="WebApp_ID" version="2.4"
	xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee 
	http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">

	<display-name>Spring Security Application</display-name>

	<!-- Spring MVC -->
	<servlet>
		<servlet-name>mvc-dispatcher</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<load-on-startup>1</load-on-startup>
	</servlet>
	<servlet-mapping>
		<servlet-name>mvc-dispatcher</servlet-name>
		<url-pattern>/</url-pattern>
	</servlet-mapping>

	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>

	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>
			/WEB-INF/spring-security.xml
		</param-value>
	</context-param>

	<!-- Spring Security -->
	<filter>
		<filter-name>springSecurityFilterChain</filter-name>
		<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
	</filter>

	<filter-mapping>
		<filter-name>springSecurityFilterChain</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>

</web-app>

Xin cảm ơn các bạn! Mình sẽ gửi đính kèm project qua link sau: http://www.mediafire.com/file/cwtfp9imze8b4p2/SpringRememberMe.rar