为了避免用户重复登录,系统在使用过程中用户可能需要保持登录。Spring提供了remember me的配置,在项目中我使用了基于cookie的保持登录功能。根据spring的安全文档,要实现remember me配置只要做以下几件事情:
1、登录页
其中的key是用于混淆加密串的,key也可以不设置。user-service-ref是用来指定具体使用的登录验证类。由于我们系统的用户认证是通过自己的业务逻辑实现的,此时就需要提供一个UserDetailsService 的一个实现类,这个类就是重载了loadUserByUsername的方法,根据我们内容的业务逻辑实现如下:
自己实现的UserDetailsService 也需要在spring-security.xml文件中加以声明:
2、
这样配置之后,每次用户进入系统后,一旦session过期,就会从cookie中获取用户信息,用户就永远保持登录。但如果仅仅这样配置,在后面使用过程中就会遇到新的问题,一旦用户点了logout,我们一般都会使用spring 的j_spring_security_logout则系统退出登录的时候就会删除本地的cookie,也就是说下次登录并不能记住用户,如果就实现到目前状态保持登录对用户来说没有任何意义!
这时候我们可以通过提供一个自己实现的SecurityContextLogoutHandler类,这个类继承了org.springframework.security.web.authentication.logout.LogoutHandler,实现了
这时候我们退出系统只是将当前用户的session设成无效,而不会去删除coookie,用户退出系统后再登录,spring就会在cookie中读取用户信息
3、
需要保持登录,用户每次进入登录页面,都应该默认显示登录用户的名字,用户应该只需要填写密码就能登录系统,这时候就需要action先从cookie中读取用户名后再返回给登录页显示即可;
4、
如果用户不想保持登录,在不勾选保持登录的时候需要将本地的cookie删除,目前找不到合适的获取勾选框值的方法,所以最后我决定在用户执行勾选框勾中或不勾中的时通过执行ajax实现cookie的删除
至此整个保持登录的功能就已经实现了,但还是有一些安全的隐患在里面,由于用户使用了保持登录功能,如果用户跳过登录页面,直接访问系统的一个有效链接,由于spring的安全机制决定其会从cookie中获取用户信息,所以系统可以有效访问,也就是只要用户没有清除cookie,那么用户在任何时间都可以无需登录访问系统。
1、登录页
<form action="${ctx}/j_spring_security_check" method="post">
<input type="text" class="standard-textfield" name="j_username" />
<input type="password" class="standard-textfield" name="j_password" />
<input type="checkbox" id="_spring_security_remember_me" /> 保持登录
</form>
[/html]
2、在spring-security.xml文件中需要加入:
[code="xml"]
<http>
<remember-me user-service-ref="userDetailManager" key="e37f4b31-0c45-11dd-bd0b-0800200c9a66"/>
</http>
其中的key是用于混淆加密串的,key也可以不设置。user-service-ref是用来指定具体使用的登录验证类。由于我们系统的用户认证是通过自己的业务逻辑实现的,此时就需要提供一个UserDetailsService 的一个实现类,这个类就是重载了loadUserByUsername的方法,根据我们内容的业务逻辑实现如下:
@Override
public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException, DataAccessException {
UserInfoManager userInfoManager = ContextLoader.getCurrentWebApplicationContext().getBean(UserInfoManager.class);
UserInfo user = userInfoManager.findUserInfo(userName);
// 鍒ゆ柇鐢ㄦ埛鐨勮处鍙锋槸鍚﹁繃鏈?
List<GrantedAuthority> authsList = new ArrayList<GrantedAuthority>();
authsList.add(new GrantedAuthorityImpl("ROLE_ADMIN"));
if (user != null) {
if (user.getEndDate() != null) {
String endDate = OrganizationConstant.dateToString(user.getEndDate());
if (endDate.equals(OrganizationConstant.STRIBF_END_DATE)) {
org.springframework.security.core.userdetails.User authUser = new org.springframework.security.core.userdetails.User(userName, user
.getPassWord(),
true, true, true,
true,
authsList.toArray(new GrantedAuthority[0]));
return authUser;
} else {
throw new UsernameNotFoundException("娌℃湁杩欎釜鐢ㄦ埛");
}
} else {
throw new UsernameNotFoundException("娌℃湁杩欎釜鐢ㄦ埛");
}
} else {
throw new UsernameNotFoundException("娌℃湁杩欎釜鐢ㄦ埛");
}
}
自己实现的UserDetailsService 也需要在spring-security.xml文件中加以声明:
<authentication-manager alias="authenticationManager">
<authentication-provider user-service-ref="userDetailManager">
<password-encoder hash="md5" base64="true"/>
</authentication-provider>
</authentication-manager>
<beans:bean id="userDetailManager"
class="cn.ac.sec.limulus.framework.main.service.UserDetailManager" />
2、
这样配置之后,每次用户进入系统后,一旦session过期,就会从cookie中获取用户信息,用户就永远保持登录。但如果仅仅这样配置,在后面使用过程中就会遇到新的问题,一旦用户点了logout,我们一般都会使用spring 的j_spring_security_logout则系统退出登录的时候就会删除本地的cookie,也就是说下次登录并不能记住用户,如果就实现到目前状态保持登录对用户来说没有任何意义!
这时候我们可以通过提供一个自己实现的SecurityContextLogoutHandler类,这个类继承了org.springframework.security.web.authentication.logout.LogoutHandler,实现了
public void logout(HttpServletRequest request, HttpServletResponse response, Authentication authentication) {
Assert.notNull(request, "HttpServletRequest required");
if (this.invalidateHttpSession) {
HttpSession session = request.getSession(false);
if (session != null) {
session.invalidate();
}
}
org.springframework.security.web.authentication.rememberme.TokenBasedRememberMeServices service;
SecurityContextHolder.clearContext();
}
这时候我们退出系统只是将当前用户的session设成无效,而不会去删除coookie,用户退出系统后再登录,spring就会在cookie中读取用户信息
3、
需要保持登录,用户每次进入登录页面,都应该默认显示登录用户的名字,用户应该只需要填写密码就能登录系统,这时候就需要action先从cookie中读取用户名后再返回给登录页显示即可;
4、
如果用户不想保持登录,在不勾选保持登录的时候需要将本地的cookie删除,目前找不到合适的获取勾选框值的方法,所以最后我决定在用户执行勾选框勾中或不勾中的时通过执行ajax实现cookie的删除
至此整个保持登录的功能就已经实现了,但还是有一些安全的隐患在里面,由于用户使用了保持登录功能,如果用户跳过登录页面,直接访问系统的一个有效链接,由于spring的安全机制决定其会从cookie中获取用户信息,所以系统可以有效访问,也就是只要用户没有清除cookie,那么用户在任何时间都可以无需登录访问系统。