public Result login(LoginFormDTO loginForm, HttpSession session) { String code = loginForm.getCode(); String phone = loginForm.getPhone(); // 1.校验手机号 if(RegexUtils.isPhoneInvalid(phone)){ return Result.fail("手机号格式错误"); } // 2.校验验证码 Object cacheCode = session.getAttribute(phone); if(cacheCode == null || !cacheCode.toString().equals(code)){ // 3.不合法,返回错误信息 return Result.fail("验证码错误"); } // 4.合法,根据手机号查询用户 User user = query().eq("phone", phone).one(); // 5.用户存在,跳过 // 6.用户不存在 if(user == null){ // 6.1 注册 user = createUserWithPhone(phone); } // 7 保存到session中 session.setAttribute("user", user); return Result.ok(); }
校验登录是放在拦截器中的,这样每个业务不用单独再实现校验登录,但是这样会出现线程安全问题,可以用TreadLocal(线程级,tomcat中每个请求都会有一个独立线程)。
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { // 1.获取session HttpSession session = request.getSession(); // 2.获取session中的user Object user = session.getAttribute("user"); // 3.判断user是否存在 if(user == null){ // 4.不存在,拦截 未授权 response.setStatus(401); return false; } // 5.存在,保存用户信息到ThreadLocal中 UserHolder.saveUser((User) user); // 6.放行 return true; } public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { // 移除用户 UserHolder.removeUser(); }public class UserHolder { private static final ThreadLocal<User> tl = new ThreadLocal<>(); public static void saveUser(User user){ tl.set(user); } public static User getUser(){ return tl.get(); } public static void removeUser(){ tl.remove(); } }@Configuration public class MvcConfig implements WebMvcConfigurer { @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new LoginInterceptor()) .excludePathPatterns( "/user/code", "/user/login", "/blog/hot", "/shop/**", "/shop-type/**", "/upload/**", "/voucher/**" ); } }
因为session是基于Cookie的,故先聊聊cookie。 Cookie是由Web服务器发送到用户浏览器并存储在用户计算机的小型数据文件,用来在用户访问网站时存储和发送有关用户信息,帮助网站记住用户的状态和偏好。
session(域对象),用于一次会话期间保存共享数据的对象。 session是基于Cookie的,用户第一次使用session时(访问页面),服务器会为用户创建一个session域对象,使用jsessionid和session对象关联,以后请求体都会增加:jessionid=xxxx
。
Cookie:服务器通过设置一个带有jsessionid的cookie发送给客户端。之后的每次请求,浏览器自动附带该cookie,便于服务器识别对应的会话。
URL重写:某些情况下,cookie无法使用(被禁用等),jsessionid附加到URL中,格式为URL;jsessionid=xxxx
。
JWT令牌, 一种用于安全传输信息的紧凑的URL安全的令牌格式(头部,负载,签名)。
Session是为了解决HTTP无状态性问题。
session解决Cookie的局限:Cookie过多时,增加了客户端与服务端的数据传输量,而且浏览器对Cookie是有数量限制的,所以我们不能在Cookie中保存过多的信息。
session的作用就是在服务器端保存一些用户数据,然后传递给用户一个名为jsessionid的Cookie,一个jsessionid对应一个session对象,通过jsessionid就可以获取到用户的信息
常用于用户身份认证、个性化设置、购物车功能等。
为了保障Session的安全性,防止会话劫持(如Session Fixation攻击),通常会采取以下措施:
session ID的随机性和不可预测性: 确保Session ID的生成是随机的,且不可预测。
HTTPS: 使用HTTPS加密传输数据,防止session ID在传输过程中被窃取。
session固定攻击的防护: 在用户登录后重新生成session ID。
session过期时间: 设置合理的session过期时间,防止长期未操作的session被利用。
###