spring REMEMBER ME配置过程

15 篇文章 0 订阅
为了避免用户重复登录,系统在使用过程中用户可能需要保持登录。Spring提供了remember me的配置,在项目中我使用了基于cookie的保持登录功能。根据spring的安全文档,要实现remember me配置只要做以下几件事情:

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,那么用户在任何时间都可以无需登录访问系统。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring Security提供了Remember-me功能来让用户在下次访问时无需重新登录。要启用Remember-me功能,可以按照以下步骤进行配置: 1. 在Spring Security配置文件中启用Remember-me功能,例如: ``` http .rememberMe() .key("remember-me-key") .rememberMeParameter("remember-me") .tokenValiditySeconds(86400) .userDetailsService(userDetailsService); ``` 其中,key是用来加密Remember-me cookie的密钥,rememberMeParameter是用来接收Remember-me cookie的请求参数,tokenValiditySeconds是Remember-me cookie的有效期,userDetailsService是用来根据用户名获取用户信息的服务。 2. 在登录页面中添加Remember-me的复选框,例如: ``` <input type="checkbox" name="remember-me" value="true" /> Remember me ``` 3. 在登录成功后生成Remember-me cookie,例如: ``` @RequestMapping(value = "/login", method = RequestMethod.POST) public String login(@RequestParam("username") String username, @RequestParam("password") String password, @RequestParam(value = "remember-me", required = false) boolean rememberMe, HttpServletResponse response) { // 验证用户名和密码 // ... // 生成Remember-me cookie if (rememberMe) { TokenBasedRememberMeServices rememberMeServices = new TokenBasedRememberMeServices("remember-me-key", userDetailsService); rememberMeServices.setTokenValiditySeconds(86400); rememberMeServices.setAlwaysRemember(true); rememberMeServices.loginSuccess(request, response, authentication); } // ... } ``` 其中,如果用户勾选了Remember-me复选框,则调用TokenBasedRememberMeServices的loginSuccess方法生成Remember-me cookie。 4. 在下次访问时验证Remember-me cookie,例如: ``` http .csrf().disable() .authorizeRequests() .antMatchers("/admin/**").hasRole("ADMIN") .antMatchers("/user/**").hasAnyRole("USER", "ADMIN") .anyRequest().authenticated() .and() .formLogin() .loginPage("/login") .permitAll() .and() .rememberMe() .key("remember-me-key") .rememberMeParameter("remember-me") .tokenValiditySeconds(86400) .userDetailsService(userDetailsService); ``` 其中,Remember-me cookie会在每次请求时被自动验证,如果验证通过,则用户会被认为已经登录。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值