当前位置: 首页 > news >正文

浙江品牌网站设计专家php网站 缓存

浙江品牌网站设计专家,php网站 缓存,如何查看网站图片尺寸,海淀手机网站设计公司使用Session完成登录 1. 手机号发送验证码 逻辑步骤#xff1a; 校验手机号格式是否正确。生成验证码#xff08;例如使用Hutool工具类#xff09;。将手机号和验证码存入Session。返回验证码发送成功的响应。 2. 用户登录逻辑 逻辑步骤#xff1a; 从Session中获取存…使用Session完成登录 1. 手机号发送验证码 逻辑步骤 校验手机号格式是否正确。生成验证码例如使用Hutool工具类。将手机号和验证码存入Session。返回验证码发送成功的响应。 2. 用户登录逻辑 逻辑步骤 从Session中获取存储的手机号和验证码。校验前端传来的手机号和验证码是否与Session中一致。如果一致根据手机号查询用户是否存在。 如果不存在创建新用户并随机生成用户名。将用户信息存入Session。 package com.hmdp.service.impl;import cn.hutool.core.util.RandomUtil; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.hmdp.dto.LoginFormDTO; import com.hmdp.dto.Result; import com.hmdp.entity.User; import com.hmdp.mapper.UserMapper; import com.hmdp.service.IUserService; import com.hmdp.utils.RegexUtils; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service;import javax.servlet.http.HttpSession;import static com.hmdp.utils.SystemConstants.USER_NICK_NAME_PREFIX;/*** p* 服务实现类* /p** author 虎哥* since 2021-12-22*/ Service Slf4j public class UserServiceImpl extends ServiceImplUserMapper, User implements IUserService {Overridepublic Result sendCode(String phone, HttpSession session) {// 校验手机号if (RegexUtils.isPhoneInvalid(phone)) {// 不符合 返回错误信息return Result.fail(手机号格式错误);}// 生成验证码String code RandomUtil.randomNumbers(6);// 保存验证码到Sessionsession.setAttribute(code,code);session.setAttribute(phone,phone);//TODO 发送验证码 需要调用第三方log.debug(发送验证码成功验证码{},code);// 返回成功return Result.ok();}Overridepublic Result login(LoginFormDTO loginForm, HttpSession session) {// 校验手机号和验证码if (!loginForm.getPhone().equals(session.getAttribute(phone))) {return Result.fail(手机号和之前的不同);}// 校验码不一致报错if (!session.getAttribute(code).equals(loginForm.getCode())) {return Result.fail(验证码不正确);}// 一致根据手机号查询用户User user query().eq(phone, loginForm.getPhone()).one();if (usernull) {// 用户不存在 创建新的用户 保存用户到数据库保存用户到Sessionuser createUserWithPhone(loginForm.getPhone());}// 用户存在直接保存用户到Sessionsession.setAttribute(user,user);return Result.ok();}private User createUserWithPhone(String phone) {User user new User();user.setPhone(phone);user.setNickName(USER_NICK_NAME_PREFIXRandomUtil.randomString(10)); // 设置默认的用户名save(user);return user;} }3. 登录校验拦截器 逻辑步骤 拦截所有需要登录验证的请求。检查Session中是否存在user对象。如果不存在返回未登录的错误信息否则将user信息转换为只含有id昵称和头像地址的类之后保护用户隐私信息存入TreadLocal当中并且放行。 public class LoginInterceptor implements HandlerInterceptor {Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {Object user request.getSession().getAttribute(user);if (user null) {response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);response.getWriter().write(未登录请先登录);return false;}// 将用户信息存入 ThreadLocal // 为了保护用户的隐私需要专门设置一个类只存储用户的昵id,称和头像地址UserDTO userDTO BeanUtil.copyProperties(user, UserDTO.class);UserContext.setUser(userDTO );return true;}Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {// 清理 ThreadLocal 防止内存泄漏UserContext.clear();} }UserContext 工具类 public class UserContext {private static final ThreadLocalUserDTO tl new ThreadLocal();public static void saveUser(UserDTO user){tl.set(user);}public static UserDTO getUser(){return tl.get();}public static void removeUser(){tl.remove();} }还需要在MvcConfig当中配置拦截器 package com.hmdp.config;import com.hmdp.interceptor.LoginInterceptor; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;Configuration public class MvcConfig implements WebMvcConfigurer {Overridepublic void addInterceptors(InterceptorRegistry registry) {// 登录拦截器registry.addInterceptor(new LoginInterceptor()).excludePathPatterns(/user/code,/user/login,/blog/hot,/shop/**,/shop-type/**,/voucher/**).order(0);} }session 在服务器端有默认的时长过期时间这是由服务器配置决定的。默认情况下Session 的有效期会受到服务器设置的影响而无需手动设置时长。如果需要自定义时长可以进行配置。 默认值 在大多数 Servlet 容器如 Tomcat、Jetty中Session 的默认超时时间是 30分钟。 这个时间表示如果用户在 30 分钟内没有访问服务器Session 会被销毁。 基于Redis代替Session登录 问题Session 是存储在服务器内存中的默认情况下每个服务器实例维护自己的 Session 数据。在分布式系统中不同的请求可能被分配到不同的服务器实例从而导致无法访问原始 Session。  虽然 Session 使用方便但在分布式、高并发、跨平台场景下其缺点可能带来较大的限制。因此很多现代应用倾向于采用 无状态认证如 JWT 或集中式存储方案如 Redis来代替传统的 Session。选择方案时需要根据业务需求、系统架构和可接受的复杂性权衡决定。 1. 手机号发送验证码 逻辑 校验手机号是否规范。使用 Hutool 工具生成验证码。将验证码存入 Redis设置过期时间为 2 分钟。 2. 用户登录逻辑 逻辑 从 Redis 获取验证码并与前端提交的验证码比对。根据手机号查询用户不存在则创建新用户。生成登录令牌token将用户信息转换为 Hash 并存入 Redis设置有效期为 30 分钟。返回 token 给前端。 package com.hmdp.service.impl;import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.bean.copier.CopyOptions; import cn.hutool.core.lang.UUID; import cn.hutool.core.util.RandomUtil; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.hmdp.dto.LoginFormDTO; import com.hmdp.dto.Result; import com.hmdp.dto.UserDTO; import com.hmdp.entity.User; import com.hmdp.mapper.UserMapper; import com.hmdp.service.IUserService; import com.hmdp.utils.RegexUtils; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.stereotype.Service;import javax.annotation.Resource; import javax.servlet.http.HttpSession;import java.util.HashMap; import java.util.Map; import java.util.concurrent.TimeUnit;import static com.hmdp.utils.RedisConstants.*; import static com.hmdp.utils.SystemConstants.USER_NICK_NAME_PREFIX;/*** p* 服务实现类* /p** author 虎哥* since 2021-12-22*/ Service Slf4j RequiredArgsConstructor public class UserServiceImpl extends ServiceImplUserMapper, User implements IUserService {final private StringRedisTemplate stringRedisTemplate;Overridepublic Result sendCode(String phone, HttpSession session) {// 校验手机号if (RegexUtils.isPhoneInvalid(phone)) {// 不符合 返回错误信息return Result.fail(手机号格式错误);}// 生成验证码String code RandomUtil.randomNumbers(6);/*// 保存验证码到Sessionsession.setAttribute(code,code);session.setAttribute(phone,phone);*/// 存储到Redis中stringRedisTemplate.opsForValue().set(LOGIN_CODE_KEYphone,code,LOGIN_CODE_TTL, TimeUnit.MINUTES);//TODO 发送验证码 需要调用第三方log.debug(发送验证码成功验证码{},code);// 返回成功return Result.ok();}Overridepublic Result login(LoginFormDTO loginForm, HttpSession session) {/*// 校验手机号和验证码if (!loginForm.getPhone().equals(session.getAttribute(phone))) {return Result.fail(手机号和之前的不同);}// 校验码不一致报错if (!session.getAttribute(code).equals(loginForm.getCode())) {return Result.fail(验证码不正确);}*///String code stringRedisTemplate.opsForValue().get(LOGIN_CODE_KEY loginForm.getPhone());if(code null || ! code.equals(loginForm.getCode())){return Result.fail(验证码不正确或者手机号错误);}// 一致根据手机号查询用户User user query().eq(phone, loginForm.getPhone()).one();if (usernull) {// 用户不存在 创建新的用户 保存用户到数据库保存用户到Sessionuser createUserWithPhone(loginForm.getPhone());}// 用户存在直接保存用户到Session // session.setAttribute(user,user);// 保存到Redis中 以hash模式存储// 随机生成一个token作为登录令牌String token UUID.randomUUID().toString(true);// 将User对象转为UserDTO 再以token为keyHash形式存储UserDTO userDTO BeanUtil.copyProperties(user, UserDTO.class);// 将userDTO转换为mapMapString, Object Usermap BeanUtil.beanToMap(userDTO,new HashMap(),CopyOptions.create().setIgnoreNullValue(true).setFieldValueEditor((fieldName,fieldValue)- fieldValue.toString()));stringRedisTemplate.opsForHash().putAll(LOGIN_USER_KEY token,Usermap);// 设置有效期stringRedisTemplate.expire(LOGIN_USER_KEYtoken,LOGIN_USER_TTL,TimeUnit.MINUTES);// 返回tokenreturn Result.ok(token);}private User createUserWithPhone(String phone) {User user new User();user.setPhone(phone);user.setNickName(USER_NICK_NAME_PREFIXRandomUtil.randomString(10)); // 设置默认的用户名save(user);return user;} }3. 登录拦截器 逻辑 从请求头中获取 token。使用 token 从 Redis 获取用户信息。如果用户信息为空拦截请求。将用户信息保存到 ThreadLocal。刷新 token 的有效期。 但是如果我们还是只在登录的拦截器当中刷新token的有效值那么就只会在局部范围内保证token有效。而不是全局范围内保证用户的token不会过期。 所以我们需要加一层 加一层拦截器RefreshTokenInterceptor虽然说是拦截器但是他不进行拦截操作拦截操作还是有LoginInterceptor进行拦截。 什么只在 LoginInterceptor 中刷新 token 不够 局限性 LoginInterceptor 只对需要登录的接口进行拦截。如果用户只访问公开页面或非登录接口如 /home、/shop 等这些请求不会经过 LoginInterceptor导致 token 无法刷新。 如果用户长时间浏览公开页面后访问需要登录的页面可能因 token 过期被迫重新登录影响用户体验。 全局活跃性保证 用户访问任何页面都应该被视为活跃状态无论页面是否需要登录都需要刷新 token 的有效期。单独依赖 LoginInterceptor 只能保证在局部范围需要登录的接口内刷新 token。 为什么需要 RefreshTokenInterceptor RefreshTokenInterceptor 的目的是在全局范围内检测 token 并刷新其有效期。它负责在所有请求无论是否需要登录中检查 token并且将用户保存到TreadLocal当中但不进行登录状态的校验。真正的拦截操作判断用户是否登录仍由 LoginInterceptor 执行。LoginInterceptor 可以查看ThreadLocal中是否存在user就可以判断是否登录了 RefreshTokenInterceptor的代码  package com.hmdp.Interceptor;import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.util.StrUtil; import com.hmdp.dto.UserDTO; import com.hmdp.utils.UserHolder; import lombok.RequiredArgsConstructor; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.web.servlet.HandlerInterceptor;import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.util.Map; import java.util.concurrent.TimeUnit;import static com.hmdp.utils.RedisConstants.LOGIN_USER_KEY; import static com.hmdp.utils.RedisConstants.LOGIN_USER_TTL;RequiredArgsConstructor public class RefreshTokenInterceptor implements HandlerInterceptor {final StringRedisTemplate stringRedisTemplate;Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {// 从请求头当中获取tokenString token request.getHeader(authorization);//如果 string token ; 这个 token ! null而是 长度为0。所以不可以直接用 nullif (StrUtil.isBlankIfStr(token)) {response.setStatus(401);return true;}String key LOGIN_USER_KEY token;// 从Redis获取用户MapObject, Object userMap stringRedisTemplate.opsForHash().entries(key);// 判断userMapif (userMap.isEmpty()) {response.setStatus(401);return true;}// 将userMap转换为BeanUserDTO userDTO BeanUtil.fillBeanWithMap(userMap, new UserDTO(),false); // UserDTO userDTO BeanUtil.copyProperties(user, UserDTO.class);// 保存到ThreadLocal里面UserHolder.saveUser(userDTO);// 刷新token的有效期stringRedisTemplate.expire(key,LOGIN_USER_TTL, TimeUnit.MINUTES);return true;}Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {UserHolder.removeUser();} }LoginInterceptor拦截器代码  package com.hmdp.Interceptor; import com.hmdp.dto.UserDTO; import com.hmdp.utils.UserHolder; import org.springframework.web.servlet.HandlerInterceptor; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse;// 判断是否需要拦截也就是TreadLocal当中是否存在user public class LoginInterceptor implements HandlerInterceptor {Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {UserDTO userDTO UserHolder.getUser();if (userDTO null) {response.setStatus(401);return false;}// 有用户放行return true;}Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {UserHolder.removeUser();} }MvcConfig配置  package com.hmdp.config;import com.hmdp.Interceptor.LoginInterceptor; import com.hmdp.Interceptor.RefreshTokenInterceptor; import lombok.RequiredArgsConstructor; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; Configuration RequiredArgsConstructor public class MvcConfig implements WebMvcConfigurer {final StringRedisTemplate stringRedisTemplate;Overridepublic void addInterceptors(InterceptorRegistry registry) {// 拦截所有 执行顺序默认都是0按照添加顺序执行指定Order越小越先执行// token刷新拦截器registry.addInterceptor(new RefreshTokenInterceptor(stringRedisTemplate)).order(0);// 拦截部分请求registry.addInterceptor(new LoginInterceptor()).excludePathPatterns(/user/code,/user/login,blog/hot,/shop/**,/shop-type/**,/voucher/**).order(1);} }MvcConfig作为Spring管理的Bean可以通过构造注入或字段注入获取StringRedisTemplate。由于拦截器实例是手动创建的MvcConfig需要将StringRedisTemplate显式传递给LoginInterceptor的构造方法。
http://www.hkea.cn/news/14287659/

相关文章:

  • wordpress建站比较建设网站的价值
  • 合肥做网站行吗码支付wordpress用不
  • 网站建设是什么部门wordpress 首页设置幻灯片
  • 辽宁住房建设厅网站wordpress在哪儿设置关键词和描述
  • 免费word模板网站163企业邮箱注册怎么注册
  • 网站二级页面设计个体户做网站有用吗
  • 网站报价单模板电子商务网站怎么备案
  • 网站如何备案icp备案一份完整的品牌策划方案
  • 做外贸建网站视频网站系统开发
  • 我想做网站怎么做网站logo设计教程
  • 专业的网站建设哪家快wordpress 微信登录插件下载
  • 甘肃建网站互联网营销师怎么考
  • 公司理念网站餐厅网站页面设计
  • 网站和网页的区别百度网站是怎么建设的
  • 做二手货的网站有哪些为什么自己做的网站打开是乱码
  • 北京朝阳网站嘉兴房产网站建设
  • 小型网站维护商田科技网站
  • 网站建设 每年收费个人dw网页设计
  • 鄞州区建设局网站360未经证实的网站如何做
  • 山西两学一做登录网站网站首页大图的尺寸
  • 网站漏洞微信服务号开发方案
  • 找网站建设客户百度搜索风云榜小说
  • 郑州网站开发douyanet施工企业高级工程师土建答辩
  • wordpress整站备份网页素材有哪几大类
  • 如何设计营销 网站建设wordpress首页显示摘要插件
  • wordpress qiniu-uploader 使用2020站群seo系统
  • 网页模板快速建站工具网站运营管理主要内容
  • 新乡手机网站建设官网怎样管理网站
  • 邯郸网站建设外包自己做网站能赚到广告费吗
  • wordpress企业站主题下载地址网站开发流程甘特图