首先是session问题
传统session认证
http协议是一种无状态协议,即浏览器发送请求到服务器,服务器是不知道这个请求是哪个用户发来的。为了让服务器知道请求是哪个用户发来的,需要让用户提供用户名和密码来进行认证。当浏览器第一次访问服务器(假设是登录接口),服务器验证用户名和密码之后,服务器会生成一个sessionid(只有第一次会生成,其它会使用同一个sessionid),并将该session和用户信息关联起来,然后将sessionid返回给浏览器,浏览器收到sessionid保存到Cookie中,当用户第二次访问服务器是就会携带Cookie值,服务器获取到Cookie值,进而获取到sessionid,根据sessionid获取关联的用户信息。
由于前后的分离开发,传统的session方式不能用来做登录认证了,因为存在前端是部署在ngnix代理服务器中,springboot是部署tomcat服务器中,两个项目存在跨域问题,所以session不能共享,每次获取session地址不同,session对象就不同
解决思路
1、首次登录时,后端服务器判断用户账号密码正确之后, 生成 sessionId,设置过期时间保存到redis服务器中并返回给前端
@ApiOperation(value = "登入")
@PostMapping("/login")
public ResultVO loginPost(@RequestParam("userName")String userName, @RequestParam("userPass")String userPass){
//根据前端传递过来的name和passowrd生成shrio的UsernamePasswordToken
userPass = new Md5Hash(userPass,userName,3).toString();
UsernamePasswordToken token = new UsernamePasswordToken(userName, userPass);
//写shiro的认证逻辑
Subject subject = SecurityUtils.getSubject();
//因为可能出现异常,所以直接try catch
try {
//调用login方法,传入token
subject.login(token);
String sid = (String) subject.getSession().getId();
//如果登录没有出现异常的话,就可以通过getPrincinpal()获取登录用户
User user= (User)subject.getPrincipal();
//获取sessionId
String sessionId = (String) subject.getSession().getId();
//成功返回id和对象
LoginVo loginVo=new LoginVo();
loginVo.setUser(user);
loginVo.setSessionId(sessionId);
AppUser appUser=new AppUser();
BeanUtils.copyProperties(user,appUser);
return ResultVOUtil.success(loginVo);
} catch (AuthenticationException e) {
return ResultVOUtil.error(400,e.getMessage());
}
}
2、前端拿到后端返回的 sessionId, 存储在 localStroage/sessionStroage里
const user = {
state: {
id:window.sessionStorage.getItem('id'),
userId:null,
userName:null,
userNickname:null,
u