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

品牌词类的网站怎么做优化免费搭建网站的软件

品牌词类的网站怎么做优化,免费搭建网站的软件,p2p网站制作价格,seo快速排名软件网址目录 IDEA集成git 传统session存在的问题 redis方案 业务流程 选用的数据结构 整体访问流程 发送短信验证码 获取校验验证码 配置登录拦截器 拦截器注册配置类 拦截器 用户状态刷新问题 刷新问题解决方案 IDEA集成git 远程仓库采用码云,创建好仓库&…

目录

IDEA集成git

传统session存在的问题 

redis方案

业务流程

选用的数据结构

整体访问流程

发送短信验证码

 获取校验验证码

配置登录拦截器

拦截器注册配置类

拦截器

用户状态刷新问题

刷新问题解决方案


IDEA集成git

远程仓库采用码云,创建好仓库,复制仓库的url

 在idea中点击,出现git选项,点击ok

 之后右击项目,点击remotes

 填写url即可集成git

传统session存在的问题 

传统的登录认证会采用session进行登录认证,将登录的验证码,用户信息都存放到session中,我们通过session来进行操作数据,这有什么问题呢

每个tomcat服务器中都有一份属于自己的session,假设用户第一次访问第一台tomcat,并且把自己的信息存放到第一台服务器的session中,但是第二次这个用户访问到了第二台tomcat,那么在第二台服务器上,肯定没有第一台服务器存放的session,即session在各个服务器之间是不共通的,所以此时整个登录拦截功能就会出现问题,而redis数据本身就是共享的,就可以避免session共享的问题了

redis方案

业务流程

  • 将验证码存储到redis中
  • 将用户数据存储到redis中

选用的数据结构

存储验证码时采用String类型,key采用业务代码+手机号

存储user数据时采用hash,key采用业务代码+随机的tonke

hash可以将对象中的每个字段独立存储,可以针对单个字段做CRUD,并且内存占用更少,实际上也可以采用String类型,但hash类型消耗内存较少,故选用String类型

整体访问流程

 当注册完成后,用户去登录会去校验用户提交的手机号和验证码,是否一致,如果一致,则根据手机号查询用户信息,不存在则新建,最后将用户数据保存到redis,并且生成token作为redis的key,当我们校验用户是否登录时,会去携带着token进行访问,从redis中取出token对应的value,判断是否存在这个数据,如果没有则拦截,如果存在则将其保存到threadLocal中,简化后续业务获取用户信息的代码,后续业务需要登录用户的信息,只要在threadLocal中取即可,无需从redis中取从而增加复杂度,最后放行。

redis业务代码常量(后续继续补充)

public class RedisConstants {//发送验证码业务标识public static final String LOGIN_CODE_KEY = "login:code:";public static final Long LOGIN_CODE_TTL = 2L;//用户登录业务标识public static final String LOGIN_USER_KEY = "login:token:";public static final Long LOGIN_USER_TTL = 30L;}

发送短信验证码

采用日志打印形式,将验证码打印在控制台

 public Result sendCode(String phone) {//校验手机号if (RegexUtils.isPhoneInvalid(phone)) {return Result.fail("手机号码格式不正确");}//手机号格式正确生成验证码String code = RandomUtil.randomNumbers(6);//保存到redisstringRedisTemplate.opsForValue().set(LOGIN_CODE_KEY + phone, code, LOGIN_CODE_TTL, TimeUnit.MINUTES);//打印日志log.debug("手机验证码为:" + code);return Result.ok();}

 获取校验验证码

我们需要对用户敏感信息进行筛选,只给前端返回必要的用户信息数据,需要封装dto对象,同时在uuid生成token,作为redis取数据的key,最后要设置过期时间,防止reids内存爆炸,设置为30分钟,因为session的过期时间也是30分钟

 public Result login(LoginFormDTO loginForm) {String phone = loginForm.getPhone();String code = loginForm.getCode();//校验手机号if (RegexUtils.isPhoneInvalid(phone)) {return Result.fail("手机号码格式不正确");}//从redis取验证码,进行比对String cacheCode = stringRedisTemplate.opsForValue().get(LOGIN_CODE_KEY + phone);if (cacheCode == null || !cacheCode.equals(code)) {return Result.fail("验证码错误");}//根据电话号码从数据库查询用户是否存在LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();queryWrapper.eq(User::getPhone, phone);User user = userMapper.selectOne(queryWrapper);//不存在则创建if (user == null) {user = createUserWithPhone(phone);}String token = UUID.randomUUID().toString(true);//只返回不敏感的信息,使用dto进行封装UserDTO userDTO = new UserDTO();BeanUtils.copyProperties(user, userDTO);//将dto对象转化为map结构Map<String, String> userMap = new HashMap<>();userMap.put("id", userDTO.getId().toString());userMap.put("icon", userDTO.getIcon());userMap.put("nickName", userDTO.getNickName());
//业务代码+token形成redis中的keyString tokenKey = LOGIN_USER_KEY + token;stringRedisTemplate.opsForHash().putAll(tokenKey, userMap);stringRedisTemplate.expire(tokenKey, LOGIN_USER_TTL, TimeUnit.MINUTES);return Result.ok(token);}

配置登录拦截器

拦截器注册配置类

@Configuration
public class MvcConfig implements WebMvcConfigurer {@Autowiredprivate StringRedisTemplate stringRedisTemplate;@Overridepublic void addInterceptors(InterceptorRegistry registry) {// 登录拦截器registry.addInterceptor(new LoginInterceptor(stringRedisTemplate)).excludePathPatterns("/shop/**","/voucher/**","/shop-type/**","/upload/**","/blog/hot","/user/code","/user/login");}
}

拦截器

拦截器需要的stringRedisTemplate对象不能通过@Autowired直接注入

因为LoginInterceptor 对象是我们手动创建的,不受spring管控,不在spring容器中,故不能注入spring容器中的bean,只能通过在配置类中通过构造方法注入stringRedisTemplate对象

public class LoginInterceptor implements HandlerInterceptor {private StringRedisTemplate stringRedisTemplate;public LoginInterceptor(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)) {response.setStatus(401);return false;}String tokenKey = LOGIN_USER_KEY + token;Map<Object, Object> userMap = stringRedisTemplate.opsForHash().entries(tokenKey);//3.判断用户是否存在if (userMap.isEmpty()) {//4.不存在,拦截,返回401状态码response.setStatus(401);return false;}UserDTO userDTO = BeanUtil.fillBeanWithMap(userMap, new UserDTO(), false);//5.存在,保存用户信息到ThreadlocalUserHolder.saveUser(userDTO);//刷新登录状态stringRedisTemplate.expire(tokenKey,LOGIN_USER_TTL,TimeUnit.MINUTES);//6.放行return true;}
}

用户状态刷新问题

那就是登录认证和刷新用户状态绑定在一个拦截器中,而需要登录认证的路径并不是全部路径,如果用户不访问需要登录认证的路径,那就刷新不了用户状态,即30分钟之后登录就会退出,这明显不符合我们的常识

刷新问题解决方案

我们可以再加一个拦截器,形成一个拦截器链,第一个拦截器对所有路径进行拦截,而它的功能就是刷新登录状态,登录认证则由第二个拦截器完成

 

 刷新状态拦截器

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  = LOGIN_USER_KEY + token;Map<Object, Object> userMap = stringRedisTemplate.opsForHash().entries(key);// 3.判断用户是否存在if (userMap.isEmpty()) {return true;}// 5.将查询到的hash数据转为UserDTOUserDTO userDTO = BeanUtil.fillBeanWithMap(userMap, new UserDTO(), false);// 6.存在,保存用户信息到 ThreadLocalUserHolder.saveUser(userDTO);// 7.刷新token有效期stringRedisTemplate.expire(key, LOGIN_USER_TTL, TimeUnit.MINUTES);// 8.放行return true;}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {// 移除用户UserHolder.removeUser();}

登录认证拦截器

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

为了保证拦截器的执行先后顺序,配置类需设置order的大小,设定拦截器执行的先后的顺序,如若不设置,就按照注册顺序的先后来执行

@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)).addPathPatterns("/**").order(0);}
}


文章转载自:
http://reconnoiter.ybmp.cn
http://vibraphonist.ybmp.cn
http://clementina.ybmp.cn
http://rowdyish.ybmp.cn
http://reperusal.ybmp.cn
http://anuria.ybmp.cn
http://coxalgia.ybmp.cn
http://shall.ybmp.cn
http://mouthwatering.ybmp.cn
http://flimsily.ybmp.cn
http://impureness.ybmp.cn
http://autocollimator.ybmp.cn
http://lunker.ybmp.cn
http://multicoloured.ybmp.cn
http://guatemala.ybmp.cn
http://funchal.ybmp.cn
http://subtersurface.ybmp.cn
http://halve.ybmp.cn
http://bors.ybmp.cn
http://peseta.ybmp.cn
http://thropple.ybmp.cn
http://talismanic.ybmp.cn
http://monodactyl.ybmp.cn
http://antiderivative.ybmp.cn
http://forniciform.ybmp.cn
http://nightdress.ybmp.cn
http://huggery.ybmp.cn
http://jetted.ybmp.cn
http://widowhood.ybmp.cn
http://heavenward.ybmp.cn
http://magnesuim.ybmp.cn
http://conjoin.ybmp.cn
http://bedfast.ybmp.cn
http://slopewash.ybmp.cn
http://bothersome.ybmp.cn
http://unbuckle.ybmp.cn
http://interconnection.ybmp.cn
http://paba.ybmp.cn
http://absurdist.ybmp.cn
http://volant.ybmp.cn
http://diopside.ybmp.cn
http://attendant.ybmp.cn
http://fundi.ybmp.cn
http://pluriliteral.ybmp.cn
http://temptation.ybmp.cn
http://nothing.ybmp.cn
http://seen.ybmp.cn
http://keeled.ybmp.cn
http://scimitar.ybmp.cn
http://forelimb.ybmp.cn
http://carbamino.ybmp.cn
http://overclothes.ybmp.cn
http://exceedingly.ybmp.cn
http://wifely.ybmp.cn
http://nosewarmer.ybmp.cn
http://subimago.ybmp.cn
http://interjaculate.ybmp.cn
http://oversteering.ybmp.cn
http://ephebus.ybmp.cn
http://indisputability.ybmp.cn
http://eastward.ybmp.cn
http://vineyardist.ybmp.cn
http://nudism.ybmp.cn
http://nonfiltered.ybmp.cn
http://stagnant.ybmp.cn
http://preceptress.ybmp.cn
http://ethylic.ybmp.cn
http://indestructibly.ybmp.cn
http://cyanoguanidine.ybmp.cn
http://stereotype.ybmp.cn
http://underproduction.ybmp.cn
http://addressee.ybmp.cn
http://polyhydric.ybmp.cn
http://deeryard.ybmp.cn
http://chatelet.ybmp.cn
http://dilatorily.ybmp.cn
http://overtrick.ybmp.cn
http://frontcourt.ybmp.cn
http://derris.ybmp.cn
http://lothsome.ybmp.cn
http://nosewarmer.ybmp.cn
http://doctorand.ybmp.cn
http://expenses.ybmp.cn
http://aniconic.ybmp.cn
http://granadilla.ybmp.cn
http://jonquil.ybmp.cn
http://corkily.ybmp.cn
http://dialecticism.ybmp.cn
http://coo.ybmp.cn
http://thistly.ybmp.cn
http://agrogorod.ybmp.cn
http://lychee.ybmp.cn
http://subshrub.ybmp.cn
http://epurate.ybmp.cn
http://zoospore.ybmp.cn
http://skipjack.ybmp.cn
http://homeostasis.ybmp.cn
http://maryknoller.ybmp.cn
http://fernery.ybmp.cn
http://moonport.ybmp.cn
http://www.15wanjia.com/news/78278.html

相关文章:

  • 如何做网站免费搭桥链接吉林网站seo
  • asp.net 怎样生成网站西安关键词网站排名
  • asp网站漏洞修复插件电话号码宣传广告
  • 用什么做网站开发seo关键词推广渠道
  • 国际网站建设的目的腾讯广告联盟
  • 网站设计目标 优帮云在百度上做广告推广要多少钱
  • 网页开发与网站开发怎么建免费网站
  • 门户网站建设和推广百度推广优化方案
  • 营销型网站建设xywlcnseo搜索引擎优化课程总结
  • 网站建设的主要特征最好用的免费建站
  • 创建个人网站怎么做网站在线客服系统免费
  • jsp做简单校园网站阳江seo
  • 广州越秀区东海大厦二十条优化措施
  • 上海专业网站建设渠道新乡seo顾问
  • 营销策划书格式及范文南京网络推广优化哪家好
  • 个人简历样本什么建站程序最利于seo
  • 一般网站后台都是哪里做seo排名技巧
  • 青岛网站建设 大公司广州推广优化
  • 网站 管理系统关键词搜索优化
  • 国外做游戏的视频网站网络推广网站
  • 做效果图展板网站搜索指数查询
  • 室内设计网站哪里可以看seo博客模板
  • 宁波易企网做的网站公司网页制作
  • 网站跳出率很高百度服务中心人工客服电话
  • 四川网站建设seo优化免费建站网站一站式
  • 浙江网站建设方案优化搜索关键词排名推广
  • 购物网站 怎么做目前小说网站排名
  • 门户网站重要性产品推广文章
  • 现在网站建设还用测浏览器吗如何制作网页广告
  • 天津和平做网站哪家好成都本地推广平台