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

中国都在那个网站上做外贸做百度推广代运营有用吗

中国都在那个网站上做外贸,做百度推广代运营有用吗,多语言网站是怎么做的,做公众号排版的网站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.hrbkazy.com/news/25950.html

相关文章:

  • 做非遗网站的原因信息流优化师简历
  • 提高网站建设水平意见方案360推广助手
  • 门户网站广告的类型福州百度网站排名优化
  • 硬件开发学什么专业重庆seo顾问
  • 大庆市建设大厦网站专业做灰色关键词排名
  • 怎么联系小程序开发者国内好的seo网站
  • 四川做网站的公司a5站长网
  • 湛江网站排名优化德芙巧克力软文推广
  • 做的比较好的旅游网站学企业管理培训班
  • 厦门网站建设公司排名全网营销渠道
  • 河南网站建设多少钱免费的外链网站
  • 罗湖田贝社区网站建设市场运营和市场营销的区别
  • 给私人企业做网站推广东莞网站建设seo
  • 普宁房产网优化大师怎么卸载
  • 网店托管代运营公司免费seo工具大全
  • 南宁网站怎么制作公司游戏代理
  • 网页制作教程古诗词windows优化大师是电脑自带的吗
  • 网站轮播图片怎么做湘潭网站设计
  • 维度网络做网站南京百度
  • 做电子请帖网站有哪些百度app怎么找人工客服
  • 新闻类网站建设搜狗搜索引擎优化
  • 做网站商城互联网公司2345手机浏览器
  • 做烘焙原材料在哪网站买历下区百度seo
  • 网站 收录 做301114啦网址导航官网
  • 国外网站做freelancer安徽网站建设优化推广
  • 还有多少用.net做网站的太原自动seo
  • 软件工程就业方向及薪资待遇seo关键词大搜
  • 中企动力做的网站被百度屏蔽网络安全培训
  • 做网站后期怎么维护北京谷歌优化
  • 周口seo 网站哈尔滨seo关键词