日常记录,代码是根据SpringSecurity写的。
###写个Entity类实现UserDetails
1<!-- lang: java --> 2package com.lqz.b2c.base.web.controller.member.support; 3 4import com.lqz.b2c.base.entity.Passport; 5import com.lqz.base.auth.UsernameNotFoundException; 6import com.lqz.base.auth.userdetails.UserDetails; 7 8public class LoginUserSupport implements UserDetails { 9 10 private static final long serialVersionUID = 20130411151453L; 11 12 public LoginUserSupport() { 13 // TODO Auto-generated constructor stub 14 } 15 16 public LoginUserSupport(Passport passport) throws UsernameNotFoundException { 17 if (passport == null || passport.getId() == null 18 || passport.getId() <= 0 || passport.getLoginName() == null 19 || passport.getPassword() == null) { 20 throw new UsernameNotFoundException(); 21 } 22 setId(passport.getId()); 23 setUsername(passport.getLoginName()); 24 setPassword(passport.getPassword()); 25 } 26 27 private Long id; 28 private String username; 29 private String password; 30 31 public Long getId() { 32 return id; 33 } 34 35 public void setId(Long id) { 36 this.id = id; 37 } 38 39 public String getUsername() { 40 return username; 41 } 42 43 public void setUsername(String username) { 44 this.username = username; 45 } 46 47 public void setLoginName(String loginName) { 48 this.username = loginName; 49 } 50 51 public String getPassword() { 52 return password; 53 } 54 55 public void setPassword(String password) { 56 this.password = password; 57 } 58 59 /** 60 * 非过期账户 61 */ 62 @Override 63 public boolean isAccountNonExpired() { 64 return true; 65 } 66 67 @Override 68 public boolean isAccountNonLocked() { 69 return true; 70 } 71 72 @Override 73 public boolean isCredentialsNonExpired() { 74 return true; 75 } 76 77 @Override 78 public boolean isEnabled() { 79 return true; 80 } 81 82}
###写个处理类,继承UserDetailsService
1<!-- lang: java --> 2package com.lqz.b2c.base.service.impl; 3 4import javax.annotation.Resource; 5 6import org.springframework.dao.DataAccessException; 7import org.springframework.stereotype.Service; 8import org.springframework.transaction.annotation.Transactional; 9 10import com.lqz.b2c.base.entity.Passport; 11import com.lqz.b2c.base.repository.IPassportDao; 12import com.lqz.b2c.base.service.IPassportMgr; 13import com.lqz.b2c.base.web.controller.member.support.LoginUserSupport; 14import com.lqz.base.auth.UsernameNotFoundException; 15import com.lqz.base.auth.userdetails.UserDetails; 16import com.lqz.base.auth.userdetails.UserDetailsService; 17 18/** 19 * @author 小败 20 * 21 */ 22@Service("passportMgrImpl") 23@Transactional(readOnly = true) 24public class PassportMgrImpl implements IPassportMgr, UserDetailsService { 25 26 27 28 29 @Override 30 public UserDetails loadUser(Long userId, String username) 31 throws UsernameNotFoundException, DataAccessException { 32 Passport passport = passportDao.findByIDAndLoginName(userId, username); 33 LoginUserSupport user = new LoginUserSupport(passport); 34 return user; 35 } 36 37 38 39 /** 注入 **/ 40 41 private IPassportDao passportDao; 42 43 @Resource(name = "passportDao") 44 public void setPassportDao(IPassportDao passportDao) { 45 this.passportDao = passportDao; 46 } 47 48}
###登录处使用
1<!-- lang: java --> 2 @RequestMapping(method = RequestMethod.POST) 3public String login(LoginUserSupport user, HttpServletRequest request, 4 HttpServletResponse response, RedirectAttributes redirectAttributes) { 5 Passport passport = passportMgr.login(user.getUsername(), 6 user.getPassword()); 7 if (passport != null) { 8 user.setId(passport.getId()); 9 user.setPassword(passport.getPassword()); 10 rememberMeService.loginSuccess(request, response, user); 11 return passportMgr.login(request.getSession(), passport); 12 } 13 redirectAttributes.addFlashAttribute("login_error", "登录失败"); 14 return "redirect:/login"; 15}
###退出登录处理
1<!-- lang: java --> 2 public String logout(HttpServletRequest request, 3 HttpServletResponse response, HttpSession session) { 4 logger.info("LogoutController#logout"); 5 rememberMeService.logout(request, response); 6 session.invalidate(); 7 return "redirect:/"; 8 }
###拦截器自动登录实现
1<!-- lang: java --> 2 public boolean preHandle(HttpServletRequest request, 3 HttpServletResponse response, Object obj) throws Exception { 4 /** 5 * 判断用户有没有登录 6 */ 7 Passport account = (Passport) WebUtils.getSessionAttribute(request, "passport"); 8 if (account != null) { 9 return true; 10 } 11 12 /** 13 * 判断有没有Cookie 有的话提取Cookie 内容 14 */ 15 UserDetails user = rememberMeService.autoLogin(request, response); 16 if (user == null) { 17 return true; 18 } 19 20 /** 21 * 自动登录 22 */ 23 Passport passport = passportMgr.getPassportById(user.getId()); 24 if (passport != null) { 25 passportMgr.login(request.getSession(), passport); 26 } else { 27 rememberMeService.loginFail(request, response); 28 } 29 return true; 30}
Spring 配置
1<!-- lang: xml --> 2 <bean id="rememberMeService" class="com.lqz.base.auth.rememberme.TokenBasedRememberMeServices"> 3 <property name="key" value="20130411192953"/> 4 <property name="domain" value=".lqz.com"/><!-- option --> 5 <property name="parameter" value="rememberMe"/><!-- defult: remember_me --> 6 <property name="userDetailsService" ref="passportMgrImpl"/> 7</bean>
原理
登录时,把数据以[用户名:时间:密码:key:id]形式加密 其中密码与key是单项加密
自动登录时,首先使用id与用户名加载用户信息. 然后把查询出来的密码与key再次加密,与上次结果比较 如果两次加密相等,则登录成功