登录功能
-
目的:[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TsphRgbO-1646368004133)(C:\Users\dooth\AppData\Roaming\Typora\typora-user-images\image-20220301201106487.png)]
-
步骤: 数据访问层dao —> 业务层 -->表现层
-
实体类entity包封装登陆凭证数据:
public class LoginTicket { private int id; private int UserId; private String ticket; private int status; private Date expired; //到期时间 @Override public String toString() { return "LoginTicket{" + "id=" + id + ", UserId=" + UserId + ", ticket='" + ticket + '\'' + ", status=" + status + ", expired=" + expired + '}'; } public int getId() { return id; } public void setId(int id) { this.id = id; } public int getUserId() { return UserId; } public void setUserId(int userId) { UserId = userId; } public String getTicket() { return ticket; } public void setTicket(String ticket) { this.ticket = ticket; } public int getStatus() { return status; } public void setStatus(int status) { this.status = status; } public Date getExpired() { return expired; } public void setExpired(Date expired) { this.expired = expired; } }
-
dao接口代码(这是不同于xml配置的另一种写sql语句的方法)
@Mapper //声明mapper对象 public interface LoginTicketMapper { //增加凭证 @Insert({//可以多个字符串拼接sql语句 "insert into login_ticket(user_id,ticket,status,expired) ",//每一句之间留一个空格,防止拼接时连一起 "values(#{userId},#{ticket},#{status},#{expired}) " }) @Options(useGeneratedKeys = true,keyProperty = "id")//注入主键 int insertLoginTicket(LoginTicket loginTicket); //通过凭证查找 @Select({ "select id,user_id,,ticket,status,expired ", "from login_ticket where ticket=#{ticket}" }) LoginTicket selectByTicket(String ticket); //修改凭证的状态 //注解写sql也可以写动态sql,比如if等等 (\"是对"的转义,不能直接打出) @Update({ "<script>", "update login_ticket set status=#{status} where ticket=#{ticket}", "<if test=\"ticket != null\">", "and 1=1", "</if>", "</script>" }) int updateStatus(String ticket,int status); } //动态时一定要带上"<script>","</script>"其他与html差不多
-
测试类测试:
@Autowired private LoginTicketMapper loginTicketMapper; @Test public void testInsertLoginTicket(){ LoginTicket loginTicket = new LoginTicket(1,123,"abc",0,new Date(System.currentTimeMillis()+1000*60*10)); loginTicketMapper.insertLoginTicket(loginTicket); } @Test public void testUpdateLoginTicket(){ LoginTicket loginTicket = loginTicketMapper.selectByTicket("abc"); System.out.println(loginTicket); loginTicketMapper.updateStatus("abc",1); loginTicket = loginTicketMapper.selectByTicket("abc"); System.out.println(loginTicket); }
-
service类中方法,写在UserService类中
@Autowired private LoginTicketMapper loginTicketMapper; public Map<String,Object> login(String username,String password,int expiredSeconds){ Map<String,Object> map = new HashMap<>(); //空值验证 if (StringUtils.isBlank(username)){ map.put("usernameMag","账号不能为空!"); return map; } if (StringUtils.isBlank(password)){ map.put("passwordMag","密码不能为空!"); return map; } //验证账号是否存在 User user = userMapper.selectByName(username); if (user==null){ map.put("usernameMag","账号不存在!"); return map; } //验证账号是否状态 if (user.getStatus() == 0){ map.put("usernameMag","账号未激活"); return map; } //验证密码 password = CommunityUtil.md5(password+user.getSalt()); if (!user.getPassword().equals(password)){ map.put("passwordMag","密码错误!"); 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
@RequestMapping(path = "/login",method = RequestMethod.POST) public String login(String username,String password,String code,boolean remember,Model model,HttpSession session,HttpServletResponse response){ //检查验证码 String kaptcha= (String)session.getAttribute("kaptcha"); if (StringUtils.isBlank(kaptcha) || StringUtils.isBlank(code)|| !kaptcha.equalsIgnoreCase(code)){ model.addAttribute("codeMag","验证码不正确"); return "site/login"; } //验证账号和密码 int expiredSeconds = remember ? REMEMBER_EXPIRED_SECONDS : DEFAULT_EXPIRED_SECONDS; Map<String, Object> map = userService.login(username, password, expiredSeconds); if (map.containsKey("ticket")){ Cookie cookie = new Cookie("ticket",map.get("ticket").toString()); cookie.setPath(contextPath); response.addCookie(cookie); return "redirect:/index"; }else { if (map.containsKey("usernameMag")){ model.addAttribute("usernameMag",map.get("usernameMag").toString()); }else { model.addAttribute("usernameMag",null); } if (map.containsKey("passwordMag")){ model.addAttribute("passwordMag",map.get("passwordMag").toString()); }else { model.addAttribute("passwordMag",null); } return "site/login"; } }
-
login.html
-
登录失败页面自动填入:方法中那种从页面获取的参数会被存放到modal中可以直接获取,但是普通的可以去reqs对象中获取
th:value="${param.username}"
-
-
退出登录
-
service类
//退出登录 public void logout(String ticket){ loginTicketMapper.updateStatus(ticket,1);//1表示无效 }
-
表现层controller
@RequestMapping(path = "/logout",method = RequestMethod.GET) public String logout(@CookieValue("ticket") String ticket){ userService.logout(ticket); return "redirect:/login"; }
@RequestMapping(path = “/logout”,method = RequestMethod.GET)
public String logout(@CookieValue(“ticket”) String ticket){
userService.logout(ticket);
return “redirect:/login”;
} -
html设置
-