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

网站 网页电子商务好找工作吗

网站 网页,电子商务好找工作吗,用js做的网站,有哪些做普洱茶网站的2023.12.6 短信登陆如果基于session来实现,会存在session共享问题:多台Tomcat不能共享session存储空间,这会导致当请求切换到不同服务器时出现数据丢失的问题。 早期的解决办法是让session提供一个数据拷贝的功能,即让各个Tomcat的…

2023.12.6

        短信登陆如果基于session来实现,会存在session共享问题:多台Tomcat不能共享session存储空间,这会导致当请求切换到不同服务器时出现数据丢失的问题。

        早期的解决办法是让session提供一个数据拷贝的功能,即让各个Tomcat的数据实现一个互相的拷贝,但是这种方式容易造成内存空间的浪费,并且拷贝是需要时间的,这段时间内依然存在数据不一致的问题。

        于是我们可以基于Redis来完成,由于Redis数据本身就是共享的,就可以避免session共享的问题了,并且redis是基于内存的,读写性能高。

发送短信验证码

         之前是将验证码保存到session中,现在是将验证码保存到redis中,此时需要考虑redis采用什么数据结构来保存验证码:key需要保证唯一性,所以使用用户的手机号作为key;由于验证码就是一个六位数的字符串,所以value直接采用String保存就好。

该模块的代码如下:

    public Result sendCode(String phone, HttpSession session) {//1.校验手机号if(RegexUtils.isPhoneInvalid(phone)){//2.不符合则返回错误信息return Result.fail("手机号格式错误!");}//3.符合,生成验证码String code = RandomUtil.randomNumbers(6);//保存验证码到session//session.setAttribute("code",code);//4.保存验证码到redisstringRedisTemplate.opsForValue().set(LOGIN_CODE_KEY + phone,code,LOGIN_CODE_TTL, TimeUnit.MINUTES);//设置过期时间定期清理redis中的验证码//5.发送验证码log.debug("发送验证码成功,验证码:{}",code);return Result.ok();}

        这里不真的发验证码,就模拟一下就好了,验证码直接输入到控制台上。

短信验证码登陆和注册模块

         这里的redis要存的是用户对象信息,于是我们采用HashMap数据结构去存,该结构可以将对象的每个字段独立存储,方便针对单个字段进行CRUD。

        redis的key的选择这里不选择手机号,而是采用一个随机token作为key,此处的token最终是要返回给前端页面的,类似于之前的session id(登陆凭证),所以key填手机号的话不安全;并且为了后续能够通过这个token得到用户信息,需要将此token返回给客户端。

 该模块代码如下:

@Overridepublic Result login(LoginFormDTO loginForm, HttpSession session) {//1.校验手机号String phone = loginForm.getPhone();if(RegexUtils.isPhoneInvalid(phone)){//2.不符合则返回错误信息return Result.fail("手机号格式错误!");}//3.从redis获取验证码并校验String cacheCode = stringRedisTemplate.opsForValue().get(LOGIN_CODE_KEY + phone);String code = loginForm.getCode();if(cacheCode == null || !cacheCode.equals(code)){//3.验证码不一致,报错return Result.fail("验证码错误");}//4.一致,根据手机号查询用户User user = query().eq("phone", phone).one();//5.判断用户是否存在if(user == null){//6.不存在,创建新用户并保存user = createUserWithPhone(phone);}//7.保存用户信息到redis中//7.1 随机生成token,作为登陆令牌String token = UUID.randomUUID().toString(true);//7.2 将User对象转为HashMap存储UserDTO userDTO = BeanUtil.copyProperties(user, UserDTO.class);Map<String, Object> userMap = BeanUtil.beanToMap(userDTO,new HashMap<>(),CopyOptions.create().setIgnoreNullValue(true).setFieldValueEditor((fieldName,fieldValue) ->fieldValue.toString()));//7.3 存储String tokenKey = LOGIN_USER_KEY + token;stringRedisTemplate.opsForHash().putAll(tokenKey,userMap);//7.4 设置token有效期stringRedisTemplate.expire(tokenKey,LOGIN_USER_TTL,TimeUnit.MINUTES);//        返回tokenreturn Result.ok(token);}private User createUserWithPhone(String phone) {//1.创建用户User user = new User();user.setPhone(phone);user.setNickName(USER_NICK_NAME_PREFIX + RandomUtil.randomString(10));//2.保存用户save(user);return user;}

        此处有个细节,虽然我们设置了token有效期为30分钟,但是不管我们登陆后做什么操作,token始终都是30分钟后被消除。 而正常情况应该是我们登陆后如果有操作行为,token的有效期应该被重置为30分钟。

         于是我们可以使用一个拦截器对请求进行拦截,每当有请求发生,就将token的有效期重置。

拦截器的代码为:

public class RefreshTokenInterceptor implements HandlerInterceptor {private StringRedisTemplate stringRedisTemplate;public RefreshTokenInterceptor(StringRedisTemplate stringRedisTemplate) {this.stringRedisTemplate = stringRedisTemplate;}@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {//1.获取请求头中的tokenString token = request.getHeader("authorization");if (StrUtil.isBlank(token)){return true;}//2.基于Token获取redis中的用户String key = RedisConstants.LOGIN_USER_KEY+token;Map<Object, Object> userMap = stringRedisTemplate.opsForHash().entries(RedisConstants.LOGIN_USER_KEY + token);//3.判断用户是否存在if(userMap.isEmpty()){return true;}//5.将查询到的Hash数据转为UserDTO对象UserDTO userDTO = BeanUtil.fillBeanWithMap(userMap, new UserDTO(), false);//6.保存用户信息到ThreadLocalUserHolder.saveUser(userDTO);//7.刷新token有效期stringRedisTemplate.expire(key,RedisConstants.LOGIN_USER_TTL, TimeUnit.MINUTES);return true;}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {UserHolder.removeUser();}
}

        写完拦截器的代码之后,还需要在MvcConfig中进行配置:

@Configuration
public class MvcConfig implements WebMvcConfigurer {@Resourceprivate StringRedisTemplate stringRedisTemplate;@Overridepublic void addInterceptors(InterceptorRegistry registry) {//登陆拦截器registry.addInterceptor(new LoginInterceptor()).excludePathPatterns("/shop/**","/voucher/**","/shop-type/**","/upload/**","/blog/hot","/user/code","/user/login").order(1);//token刷新拦截器registry.addInterceptor(new RefreshTokenInterceptor(stringRedisTemplate)).order(0);}
}

         这里虽然是在第二行配置的刷新有效期拦截器,但是它会先进行拦截,因为我们order里填的数字是0,数字越小优先级越高。

        第一行的拦截器是用来进行登陆校验的,即如果你访问了除代码中路径以外的路径的话,需要判断你有没有登陆,那如何判断你有没有登陆呢?只需要查看当前ThreadLocal中有无用户信息就知道了,该拦截器代码如下:

public class LoginInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {//判断是否需要拦截(即ThreadLocal中是否有用户)if(UserHolder.getUser() == null){response.setStatus(401);return false;}return true;}}

        拦截器的整体架构图如下:

http://www.yayakq.cn/news/607401/

相关文章:

  • php网站开发套模板步骤企业办公软件排名
  • 襄阳网站seo公司合肥网站优化排名推广
  • 网站开发的研究背景网站建设服务器对比
  • 备案的网站是公司吗淘宝客怎么在微博做网站
  • php7跨设备网站开发pdfwordpress链接插件
  • 制作网站软件不懂代码可以制作吗什么公司网站建设比较好
  • 抚顺营销型网站建设wordpress锁
  • 视频网站的做制作中秋网页素材
  • 网站如何开通微信支付接口域名对网站有什么影响
  • 做照片的网站有哪些软件龙岩到永定汽车时刻表
  • 网站续费文档有没有什么做热力图的图表网站
  • 专业做图片制作网站网站是别人做的我这就没有根目录
  • 如何导入旧网站数据库个人介绍网站内容
  • 手机网页及网站设计wordpress搬家显示重新安装
  • 淘宝联盟网站建设源码怎么夸一个网站开发公司
  • 智慧旅游类网站开发商WordPress显示不出广告
  • 山东省建设工程管理局网站百度外推发帖软件
  • rap做词网站公司邮箱是什么
  • 香山网站建设集团做网站
  • 网站后台登录不显示验证码建设网站公司是什么
  • 做相册视频的网站建筑工程公司名字
  • 网站开发mvc架构网站个人备案需要什么
  • 普定县建设局网站内部oa管理系统
  • 重庆网站建设搜外企业安全文化建设论文
  • 外贸企业 访问国外网站做百度移动网站点
  • 郑州做品牌网站的公司wordpress 关闭邮件
  • 建筑公司企业愿景及理念模板镇江网站关键字优化机构
  • 2021年最火装修风格网络优化是什么专业
  • 湖南张家界建设局网站网站 改版
  • 网站可以自己备案吗泰兴市城乡住房建设局网站