登录和退出(五)
主要流程入下:
- 访问登录页面
- 点击顶部区域内的链接,打开登录页面。
- 登录
- 验证账号、密码、验证码。
- 成功时,生成登录凭证,发放给客户端。
- 失败时,跳转回登录页。
- 退出
- 将登录凭证修改为失效状态。
- 跳转至网站首页。
一、访问登录页面
控制层代码入下。
@GetMapping("/login")
public String getLoginPage() {
return "/site/login";
}
登录界面入下。
二、登录功能
登录功能,在服务端验证账号、密码、验证码。成功时,服务端生成登录凭证,并将其发送给客户端。失败时,则跳转到回登录页面。
1.编写Mapper代码
登录凭证类LoginTicket
入下,由MybatisX自动生成。
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable;
import java.util.Date;
import lombok.Data;
/**
*
* @TableName login_ticket
*/
@TableName(value ="login_ticket")
@Data
public class LoginTicket implements Serializable {
/**
* id
*/
@TableId(type = IdType.AUTO)
private Integer id;
/**
* 用户
*/
private Integer userId;
/**
* 登录凭证
*/
private String ticket;
/**
* 0-有效; 1-无效;
*/
private Integer status;
/**
* 到期时间
*/
private Date expired;
@TableField(exist = false)
private static final long serialVersionUID = 1L;
}
LoginTicketMapper
接口入下,其实可也可不定义方法,Mybatis plus自带的方法足够。
import com.nowcoder.community.entity.LoginTicket;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Update;
/**
* @Entity com.nowcoder.community.entity.LoginTicket
*/
public interface LoginTicketMapper extends BaseMapper<LoginTicket> {
//通过登录凭证更新状态
@Update({
"update login_ticket set status = #{status} where ticket = #{ticket}"
})
int updateStatus(String ticket, int status);
}
2.编写业务层代码
/**
* 登录
*
* @param username 用户名
* @param password 密码
* @param expiredSeconds 过期时间(秒)
* @return
*/
public Map<String, Object> login(String username, String password, int expiredSeconds) {
Map<String, Object> map = new HashMap<>();
if (StringUtils.isBlank(username)) {
map.put("usernameMsg", "账号不能为空!");
return map;
}
if (StringUtils.isBlank(password)) {
map.put("passwordMsg", "密码不能为空");
return map;
}
//查询账号
LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<>();
lqw.eq(User::getUsername, username);
User user = getOne(lqw);
//验证账号
if (user == null) {
map.put("usernameMsg", "该账号不存在!");
return map;
}
//验证状态
if (user.getStatus() == 0) {
map.put("usernameMsg", "该账号未激活!");
return map;
}
//验证密码
password = CommunityUtils.md5(password + user.getSalt());
if (!password.equals(password)) {
map.put("passwordMsg", "密码错误!");
return map;
}
//生成登录凭证
LoginTicket loginTicket = new LoginTicket();
loginTicket.setUserId(user.getId());
loginTicket.setTicket(CommunityUtils.generateUUID());
loginTicket.setExpired(new Date(System.currentTimeMillis() + expiredSeconds * 1000));
loginTicketMapper.insert(loginTicket);
map.put("ticket", loginTicket.getTicket());
return map;
}
3.编写控制层代码
@PostMapping("/login")
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<String, Object> map = userService.login(username, password, expiredSeconds);
//成功
if (map.containsKey("ticket")) {
//将登录凭证放到cookie中
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";
}
}
cookie中的登录凭证入下:
数据库中的登录凭证入下,二者保持一致
三、退出功能
退出功能,在点击退出链接时将登录凭证改为失效状态,并跳转到网站首页。
业务层,修改登录凭证状态,使其失效
/**
* 退出
* @param ticket 登录凭证
*/
public void logout(String ticket) {
loginTicketMapper.updateStatus(ticket, 1);
}
控制层,返回到登录界面
@GetMapping("/logout")
public String logout(@CookieValue("ticket") String ticket) {
userService.logout(ticket);
return "redirect:/login";
}
修改后的登录凭证。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)