访问登录页面
登陆: 验证账号+密码+验证码
-成功时生成登录凭证,发放给客户端 cookie
(记录登陆状态,让状态在多个业务中可以连续)
-如果失败,跳转回登陆页
退出
需要完成:1.将登陆凭证改为失效
2.跳转至网站首页
回忆:曾经设计的表中 登录凭证表有这几个字段
login_ticke 表:
id user id ticket status(0 有效,1 无效) expired (过期时间)
开始开发 从底向上的逻辑;
数据访问层:登陆凭证相关操作: entity 里添加loginticket (根据数据库建的表)
package com.nowcoder.community.entity;
import java.util.Date;
public class LoginTicket {
private int id;
private int userId;
private String ticket;
private int status;
private Date expired;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getUserId() {
return userId;
}
public void setUserId(int userId) {
this.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;
}
@Override
public String toString() {
return "LoginTicket{" +
"id=" + id +
", userId=" + userId +
", ticket='" + ticket + ''' +
", status=" + status +
", expired=" + expired +
'}';
}
}
dao层 此地直接用注解写sql语句
packagecom.nowcoder.community.dao;
importcom.nowcoder.community.entity.LoginTicket;
importorg.apache.ibatis.annotations.*;
@Mapper
public interfaceLoginTicketMapper {
@Insert({
"insert into login_ticket(user_id,ticket,status,expired)",
"values(#{userId},#{ticket},#{status},#{expired})"
})
@Options(useGeneratedKeys =true, keyProperty ="id")
intinsertLoginTicket(LoginTicket loginTicket);
@Select({
"select id,user_id,ticket,status,expired",
"from login_ticket where ticket=#{ticket}"
})
LoginTicket selectByTicket(String ticket);
@Update({
""
})
intupdateStatus(@Param("ticket") String ticket, @Param("status")intstatus);
}
业务层:
登陆的时候接收页面传入的条件包括用户名,密码 + 账号的过期时间
还在userservice里写
先注入loginmapper
登陆的情况很多所以将返回值设置为 map
用户在页面上输入的是明文-所以要对密码加密和数据库里的数据比对
public Maplogin (String username, String password,int expiredSecond){ Map map=new HashMap<>(); if (StringUtils.isBlank(username)){ map.put("usernameMsg","账号不能为空"); return map; } if (StringUtils.isBlank(password)){ map.put("passwardMsg","账号不能为空"); 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.setTicket(CommunityUtil.generateUUID()); loginTicket.setUserId(user.getId()); loginTicket.setStatus(0); loginTicket.setExpired(new Date(System.currentTimeMillis()+expiredSecond*1000)); loginTicketMapper.insertLoginTicket(loginTicket); map.put("ticke",loginTicket.getTicket()); return map; }
在service 层
写login 的服务
对于/login 我们之前有相同路径下的请求,但是这里我们是提交表单数据所以用post,这样两种方法就可以区分开来。
对于方法里传入的参数: 我们需要比对用户名,密码,rememberme 是记住状态的勾选,code 验证码;获得验证码,因为验证码是存在session 里我们还需要session 还需要cookie 保存
@RequestMapping(path="/login",method =RequestMethod.POST)
//用post提交表单数据
publicString login(String username, String password,String code,booleanrememberme ,
Model model,HttpSession session,HttpServletResponse response){
在utilconstant 类下声明两个常量 并用@Value 注入进来
@RequestMapping(path="/login",method =RequestMethod.POST)
//用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_EXOIRED_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("passwardMsg",map.get("passwardMsg"));
return"site/login";
}}}
退出的话
在service层加 让ticket 失效
public void logout(String ticket){
loginTicketMapper.updateStatus(ticket,1);
}



