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

网络运营专业长沙企业seo优化

网络运营专业,长沙企业seo优化,石家庄做网站排名公司,深圳网页制作与网站建设地址文章目录 前言第4章 Redis实战4.1 短信登录4.1.1 基于session实现短信登录4.1.1.1 短信登录逻辑梳理4.1.1.2 创建测试项目4.1.1.3 实现发送短信验证码功能4.1.1.4 实现用户登录功能4.1.1.5 实现登录拦截功能4.1.1.6 session共享问题 4.1.2 基于Redis实现短信登录4.1.2.1 Key-Va… 文章目录 前言第4章 Redis实战4.1 短信登录4.1.1 基于session实现短信登录4.1.1.1 短信登录逻辑梳理4.1.1.2 创建测试项目4.1.1.3 实现发送短信验证码功能4.1.1.4 实现用户登录功能4.1.1.5 实现登录拦截功能4.1.1.6 session共享问题 4.1.2 基于Redis实现短信登录4.1.2.1 Key-Value的结构设计4.1.2.2 发送短信验证码功能改造4.1.2.3 用户登录功能改造4.1.2.4 登录拦截功能改造 前言 前面三章我们对Redis的基础知识进行了深入的学习已经掌握了Redis的基本使用方法。 Redis从入门到精通(一)Redis安装与启动、Redis客户端的使用 Redis从入门到精通(二)Redis的数据类型和常见命令介绍 Redis从入门到精通(三)Jedis客户端、SpringDataRedis客户端 接下来的第4章开始进入实战环节来学习一个Redis实战项目短信登录。 第4章 Redis实战 4.1 短信登录 短信登录功能可以基于session实现也可以基于Redis实现下面分别介绍这两种方式。 4.1.1 基于session实现短信登录 4.1.1.1 短信登录逻辑梳理 1发送验证码 用户在登录页面输入手机号点击“发送验证码”按钮。后台收到请求后校验手机号是否符合格式如果不符合则要求用户重新输入手机号。 如果符合后台随机生成6位数字的验证码并将验证码保存到session然后再通过短信的方式将验证码发送给用户由于没有短信网关可以使用打印日志的方式模拟。 2登录与注册 用户获取到验证码后输入手机号和验证码并点击“登录”按钮。后台收到请求后从session中获取之前保存好的验证码并与用户提交的验证码进行比对如果不一致则登录失败。 如果一致则根据手机号查询数据库的用户信息如果用户不存在则创建一个新的用户保存到数据库如果存在则直接获取然后将用户信息保存到session中方便后续获取当前登录用户信息。 3校验登录状态 用户发起的请求除了获取验证码、用户登录等少数指定的请求外一般都要求用户必须处于登录状态。如果用户并非处于登录状态说明这是一个非法请求必须进行拦截。 用户发起这些请求时后台进行拦截然后从session中拿到用户信息。如果没有获取到用户信息则表示没有用户没有登录要进行拦截。如果获取到了用户信息则说明用户已经登录了则放行。 4.1.1.2 创建测试项目 下面以一个SpringBoot项目来进行测试。 由于项目的创建不是学习的重点这里不进行详述。该测试项目的代码已打包上传有需要请到本文顶部下载绑定的代码资源。 4.1.1.3 实现发送短信验证码功能 接口文档 项目说明请求方式GET请求路径/user/code请求参数phone返回值无 代码实现 在controller目录下的UserController类中实现该接口 GetMapping(/code) public BaseResultString sendCode(String phone, HttpSession httpSession) {// 1.校验手机号格式if(RegexUtils.isPhoneInvalid(phone)) {// 2.如果不符合返回错误信息return BaseResult.setFail(手机号输入有误);}// 3.符合随机生成6位数验证码String code String.valueOf((int)(Math.random() * 900000 100000));// 4.将验证码保存到sessionhttpSession.setAttribute(code, code);// 5.短信方式发送验证码log.info(发送短信验证码成功验证码{}, code);// 6.返回成功return BaseResult.setOk(短信验证码已成功发送至手机号 phone 请注意查收); }功能测试 特别要注意的是由于我们是使用HTTP工具进行发包测试的所以需要设置一下Cookies因为后端是利用Cookies中的JSESSIONID参数来创建session的。为了确保多次请求拿到的session是同一个Cookies也必须要一致。 4.1.1.4 实现用户登录功能 接口文档 项目说明请求方式POST请求路径/user/login请求参数phone,code返回值无 代码实现 在UserController类中编写一个用户登录方法 Resource private IUserService userService;PostMapping(/login) public BaseResult login(RequestBody LoginForm loginForm, HttpSession httpSession) {log.info(用户开始登录...{}, loginForm.toString());// 1.校验手机号if(RegexUtils.isPhoneInvalid(loginForm.getPhone())) {// 2.如果不符合返回错误信息return BaseResult.setFail(手机号输入有误);}// 3.从session中获取验证码并校验Object cacheCode httpSession.getAttribute(code);if(cacheCode null || !cacheCode.toString().equals(loginForm.getCode())) {// 4.验证码不一致返回错误信息return BaseResult.setFail(验证码错误);}// 5.一致根据手机号查询用户User user userService.query().eq(phone, loginForm.getPhone()).one();if(user null) {// 6.用户不存在则创建一个用户user new User();user.setPhone(loginForm.getPhone());user.setNickName(loginForm.getPhone());userService.save(user);}// 7.将用户信息保存到session中httpSession.setAttribute(user, user);log.info({} 登录成功..., loginForm.getPhone());return BaseResult.setOk(登录成功); }功能测试 4.1.1.5 实现登录拦截功能 接口文档 用户发起的请求除了获取验证码、登录等少数指定的请求外一般都要求用户必须处于登录状态。如果用户并非处于登录状态说明这是一个非法请求必须进行拦截。 可以通过拦截器来实现这个功能。 代码实现 要创建一个拦截器只需要创建一个类LoginInterceptor实现org.springframework.web.servlet.HandlerInterceptor接口并重写其preHandle()方法。 public class LoginInterceptor implements HandlerInterceptor {Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {// 1.获取sessionHttpSession session request.getSession();// 2.获取session中的用户Object user session.getAttribute(user);// 3.判断用户是否存在if(user null){// 4.不存在拦截返回401状态码response.setStatus(401);return false;}// 5.存在放行return true;} }其次要对自定义的拦截器进行注册让其生效 Configuration public class InterceptorConfig implements WebMvcConfigurer {Overridepublic void addInterceptors(InterceptorRegistry registry) {// 登录拦截器排除获取验证码和登录请求registry.addInterceptor(new LoginInterceptor()).excludePathPatterns(/user/code,/user/login).order(1);} }功能测试 在未登录的情况下发送请求/user/info报401说明没有通过拦截器的校验 4.1.1.6 session共享问题 基于session实现短信登录在服务端单机的情况下是没问题的但如果服务端采用集群方式则会出现session共享问题。 每个tomcat中都有一份属于自己的session。假设用户第一次访问第一台tomcat并且把自己的信息存放到第一台服务器的session中但是第二次这个用户访问到了第二台tomcat那么在第二台服务器上肯定没有第一台服务器存放的session所以此时整个登录拦截功能就会出现问题。 早期的解决方案是session拷贝即当任意一台服务器的session修改时都会同步给其他的Tomcat服务器的session这样就可以实现session的共享。但这种方法也有弊端第一每台服务器中都有完整的一份session数据服务器压力过大第二session拷贝数据时可能会出现延迟。 基于此更好的解决方案是基于Redis来完成而且Redis数据本身就是共享的。 4.1.2 基于Redis实现短信登录 4.1.2.1 Key-Value的结构设计 由于本案例中要存入Redis的数据比较简单因此可以考虑使用String类型或Hash类型来存储数据。 这两种方式各有优点String类型以JSON字符串保存数据比较直观而Hash类型可以将对象的每个字段独立存储可以针对单个字段做CRUD比较方便。最终根据实际需要选择即可本案例选择使用String类型。 在基于session实现时每个用户都有一个独享的session。但Redis的Key是共享的因此不能再使用基于session方式中的code、user作为Key值。 在设计Key时需要满足两点要求第一Key要有唯一性第二Key要方便携带。 在本案例中如果采用手机号作为Key当然可以它具备唯一性且方便携带并且和验证码息息相关。但从安全角度看手机号毕竟属于敏感数据每次请求都携带手机号是不合适的。 综合考虑本案例将采用login:code:{phone}作为保存验证码的Key而保存用户信息的Key会在后台生成一个随机串token采用login:user:{token}作为Key让用户每次请求都携带这个token。 4.1.2.2 发送短信验证码功能改造 代码实现关注修改部分 Resource private StringRedisTemplate stringRedisTemplate;GetMapping(/code) public BaseResultString sendCode(String phone, HttpSession httpSession) {// 1.校验手机号if(RegexUtils.isPhoneInvalid(phone)) {// 2.如果不符合返回错误信息return BaseResult.setFail(手机号输入有误);}// 3.符合随机生成验证码String code String.valueOf((int)(Math.random() * 900000 100000));// 4.将验证码保存到session// httpSession.setAttribute(code, code);// 修改将验证码保存到Redis// 采用 login:code:{phone} 作为保存验证码的KeystringRedisTemplate.opsForValue().set(login:code: phone, code);// 5.短信方式发送验证码log.info(发送短信验证码成功验证码{}, code);// 6.返回成功return BaseResult.setOk(短信验证码已成功发送至手机号 phone 请注意查收); }功能测试 调用获取验证码接口/user/code?phone18922102123后查看Redis中的数据 4.1.2.3 用户登录功能改造 代码实现关注修改部分 PostMapping(/login) public BaseResultString login(RequestBody LoginForm loginForm, HttpSession httpSession) throws JsonProcessingException {log.info(用户开始登录...{}, loginForm.toString());// 1.校验手机号if(RegexUtils.isPhoneInvalid(loginForm.getPhone())) {// 2.如果不符合返回错误信息return BaseResult.setFail(手机号输入有误);}// 3.从session中获取验证码并校验// Object cacheCode httpSession.getAttribute(code);// 修改从Redis中获取验证码String cacheCode stringRedisTemplate.opsForValue().get(login:code: loginForm.getPhone());if(cacheCode null || !cacheCode.toString().equals(loginForm.getCode())) {// 4.验证码不一致返回错误信息return BaseResult.setFail(验证码错误);}// 5.一致根据手机号查询用户User user userService.query().eq(phone, loginForm.getPhone()).one();if(user null) {// 6.用户不存在则创建一个用户user new User();user.setPhone(loginForm.getPhone());user.setNickName(loginForm.getPhone());userService.save(user);}// 7.将用户信息保存到session中// httpSession.setAttribute(user, user);// 修改将用户信息保存到Redis中// 随机生成tokenString token UUID.randomUUID().toString();log.info(token {}, token);// 保存到RedisstringRedisTemplate.opsForValue().set(login:user: token, new ObjectMapper().writeValueAsString(user));// 设置token有效期2小时stringRedisTemplate.expire(login:user: token, 2, TimeUnit.HOURS);log.info({} 登录成功..., loginForm.getPhone());// 将token返回给前端return BaseResult.setOkWithData(token); }功能测试 调用用户登录接口/user/login后查看Redis中的数据 4.1.2.4 登录拦截功能改造 代码实现关注修改部分 Slf4j 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.获取session// HttpSession session request.getSession();// 2.获取session中的用户// Object user session.getAttribute(user);// 修改基于用户token获取Redis中的用户信息// 获取用户携带的tokenString token request.getHeader(authorization);log.info(token from client {}, token);// 基于token获取Redis中的用户信息String userJosn stringRedisTemplate.opsForValue().get(login:user: token);log.info(user from redis {}, userJosn);// 转为Java对象User user null;if(StrUtil.isNotBlank(userJosn)) {user new ObjectMapper().readValue(userJosn, User.class);}// 3.判断用户是否存在if(user null){// 4.不存在拦截返回401状态码response.setStatus(401);return false;}// 5.存在放行return true;} }注册LoginInterceptor时传入StringRedisTemplate实例 Configuration public class InterceptorConfig implements WebMvcConfigurer {Resourceprivate StringRedisTemplate stringRedisTemplate;Overridepublic void addInterceptors(InterceptorRegistry registry) {// 登录拦截器排除获取验证码和登录请求registry.addInterceptor(new LoginInterceptor(stringRedisTemplate)).excludePathPatterns(/user/code,/user/login).order(1);} }功能测试 调用查询用户详情接口/user/info项目中暂未编写该Controller方法。当携带一个错误token时报401说明未通过拦截器校验 携带一个正确token报404说明已经通过了拦截器校验 … 本节完更多内容请查阅分类专栏Redis从入门到精通 感兴趣的读者还可以查阅我的另外几个专栏 SpringBoot源码解读与原理分析(已完结)MyBatis3源码深度解析(已完结)再探Java为面试赋能(持续更新中…)
http://www.zqtcl.cn/news/462820/

相关文章:

  • 建设网站对企业有什么好处wordpress教程视频下载
  • 郑州网站提升排名上海 企业 网站建设
  • 南昌好的做网站的公司营销型网站 案例
  • 南宁经典网站建设网络运维工程师是干什么的
  • 网站开发算法建网站难不难
  • 茂名模板建站定制网站开发 ide
  • 做网站现在用什么语言网站估价
  • wap开头的网站外贸网站建设官网
  • 做网站说什么5.0啥意思wordpress教程视频 下载
  • 业务型网站做seo郑州网站推广优化
  • 400网站建设南昌网站建设方案详细版
  • 网站评论回复如何做中国住建部和城乡建设官网
  • 怎么建设网站南京做南京华美整容网站
  • 有哪些可以做1元夺宝的网站推广网站哪家做的好
  • 网站备案 域名不是自己的成都电子商务网站
  • 网站内容管理系统建设2021年建站赚钱
  • 网站建设交流发言稿找做网站的上什么app
  • 企业如何应用网站的wordpress lensnews
  • 可信的邢台做网站学电商运营需要多少钱
  • 网站中文名称做微商进哪个网站安全
  • 网站前端建设需要学会什么意思wordpress 快递查询 插件
  • 网站建设腾讯云与阿里云做网站上市的公司
  • 视频直播网站app开发网站备案主体是
  • 做的好的微信商城网站建设商务网站
  • 小白用网站建设工具专做奢侈品品牌的网站
  • 安装vs2015网站开发外包公司为什么没人去
  • 网站关键字多少合适唐河微网站开发
  • 临沂网站建站专业公司网站开发 文学
  • 乐清网站建设服务定制企业网站建设
  • 简单公司网站模版百度站长工具抓取诊断