- 登录
- 验证账号、密码、验证码。
- 成功时,生成登录凭证,发放给客户端。
- 失败时,跳转回登录页。
- 退出
登录
entity
首先我们看一看数据库login_ticket表,id主键,user_id,ticket也就是登录口令,还有status状态,0有效1无效,expired失效日期。根据数据库写实体类,并生成get/set方法。
![]()
1 2 3 4 5
| private int id; private int userId; private String ticket; private int status; private Date expired;
|
dao
然后写dao层接口,新建LoginTicketMapper。之前我们写sql是在resources下mapper目录写xml,这里来演示另一种方法——注解。
- 首先还是@Mapper注解定义接口
- 按照之前的方法写好抽象方法,插入登录口令
- 在方法上加@Insert注解,对应insert方法,可以将sql语句拆分成多个字符串,同样#{}从变量中取值
- @Options使用主键自增
- Select方法也类似
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| @Mapper public interface LoginTicketMapper { @Insert({ "insert into login_ticket(user_id,ticket,status,expired) ", "values(#{userId},#{ticket},#{status},#{expired})" }) @Options(useGeneratedKeys = true,keyProperty = "id") int insertLoginTicket(LoginTicket ticket); @Select({ "select id,user_id,ticket,status,expired ", "from login_ticket where ticket=#{ticket}" }) LoginTicket selectByTicket(String ticket); }
|
第三个@Update演示动态拼接sql语句,首先用标签包裹sql语句,使用判断和拼接,这里直接拼了一个1=1。
1 2 3 4 5 6 7 8 9
| @Update({ "" }) int updateStatus(String ticket,int status);
|
Service
然后写登录服务,这个也算是user相关的,直接写在UserService。
- 返回值使用map返回多种情况的消息,需要浏览器传用户名,密码,过期时间。
- 首先对空值处理,以防浏览器错误传入空值
- 通过用户名查出user,依次验证账号,账号状态,密码
- 验证通过后生成登录凭证,存到数据库,并返回ticket
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
| public Map login(String username,String password,int expiredSeconds){ Map map=new HashMap<>();
if(StringUtils.isBlank(username)){ map.put("usernameMsg","账号不能为空"); return map; } if(StringUtils.isBlank(password)){ map.put("passwordMsg","密码不能为空"); return map; }
User user=userMapper.selectByName(username); if ((user==null)){ map.put("usernameMsg","该账号不存在!"); return map; }
if (user.getStatus()==0){ map.put("usernameMsg","账号未激活"); return map; }
password=CommunityUtil.md5(password+user.getSalt()); if(!user.getPassword().equals(password)){ map.put("passwordMsg","密码不正确"); return map; }
LoginTicket loginTicket=new LoginTicket(); loginTicket.setUserId(user.getId()); loginTicket.setTicket(CommunityUtil.generateUUID()); loginTicket.setStatus(0); loginTicket.setExpired(new Date(System.currentTimeMillis()+expiredSeconds*1000)); loginTicketMapper.insertLoginTicket(loginTicket);
map.put("ticket",loginTicket.getTicket());
return map; }
|
controller
登录一般有记住我选项,也就是登录凭证过期时间不一样,先在CommunityConstant下定义一下不同情况的过期时间。
1 2 3 4 5 6 7 8 9
|
int DEFAULT_EXPIRED_SECONDS=3600*12;
int REMEMBER_EXPIRED_SECONDS=3600*24*100;
|
然后写登录的控制方法。
- 首先访问路径/login,前面已经用过这个路径,但是因为方法不一样,这里要提交表单使用POST方法,所以可以同时存在。
- 接收浏览器传来的用户名、密码、验证码、是否记住我,这里还要用到model、session和response
- 首先判断验证码是否正确,从session中取出登录页面生成的验证码,返回类型是对象,强制转换为String。不正确就返回验证码错误的消息,并返回登录页面
- 首先根据是否记住我,选择登录凭证过期时间,然后调用login,使用map接收返回的信息
- map里有ticket说明登录成功,将ticket存入cookie通过响应发送给浏览器,并重定向到首页
- 登录失败就返回相应错误消息,跳转到登录页
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| @RequestMapping(path = "/login",method = RequestMethod.POST) public String login(String username,String password,String code,boolean rememberMe, Model model,HttpSession session,HttpServletResponse response){ String kaptcha=(String) session.getAttribute("kaptcha"); if (StringUtils.isBlank(kaptcha)||StringUtils.isBlank(code)||!kaptcha.equalsIgnoreCase(code)){ model.addAttribute("codeMsg","验证码不正确"); return "/site/login"; }
int expiredSeconds=rememberMe ? REMEMBER_EXPIRED_SECONDS : DEFAULT_EXPIRED_SECONDS; Map map=userService.login(username,password,expiredSeconds); if (map.containsKey("ticket")){ Cookie cookie=new Cookie("ticket",map.get("ticket").toString()); cookie.setPath(contextPath); cookie.setMaxAge(expiredSeconds); response.addCookie(cookie); return "redirect:/index"; }else { model.addAttribute("usernameMsg",map.get("usernameMsg")); model.addAttribute("passwordMsg",map.get("passwordMsg")); return "/site/login"; } }
|
输入错误的用户名,密码验证码测试,因为还没有做处理,登录争取直接返回首页了。
![]()
退出
退出就很简单了,把ticket状态改为1
1 2 3 4 5 6 7 8 9 10 11
| public void logout(String ticket){ loginTicketMapper.updateStatus(ticket,1); }
@RequestMapping(path = "/logout",method = RequestMethod.GET) public String logout(@CookieValue("ticket") String ticket){ userService.logout(ticket); return "redirect:/login"; }
|