H5单点登录分析介绍(登录状态检验状态透传分析)

文章目录

  • 1、单点登录解决方案
    • 1.1、后端保存登录状态
    • 1.2、token模式
  • 2、user服务-登录接口
    • 2.1、UserController
    • 2.2、UserInfoServiceImpl
    • 2.3、载荷
    • 2.4、响应
    • 2.5、Redis Desktop Manager
  • 3、user服务-登录成功获取用户信息回显
    • 3.1、UserController
    • 3.2、UserInfoServiceImpl
    • 3.3、响应
  • 4、登录状态验证&状态透传分析
    • 4.1、gateway-过滤器统一校验登录状态
      • 4.1.1、GlobalAuthFilter
    • 4.2、登录状态透传拦截器
      • 4.2.1、SpzxServiceAuthInterceptor
      • 4.2.2、H5SpzxWebMvcConfigurer
      • 4.2.3、@EnableSpzxServiceAuth
      • 4.2.4、UserInfoServiceImpl
  • 5、登录校验状态透传总结

1、单点登录解决方案

  • 多个系统只有一个登录服务

1.1、后端保存登录状态

在这里插入图片描述

1.2、token模式

在这里插入图片描述

2、user服务-登录接口

2.1、UserController

	@Operation( summary = "用户登录接口")@PostMapping("/login")public Result login(@RequestBody UserInfo userInfo) {String token = userInfoService.login(userInfo);return Result.ok(token);}

2.2、UserInfoServiceImpl

    @Overridepublic String login(UserInfo userInfo) {//1、校验参数String username = userInfo.getUsername();String password = userInfo.getPassword();if (StringUtils.isEmpty(username) || StringUtils.isEmpty(password)) {throw new SpzxException(ResultCodeEnum.LOGIN_PARAMS_ERROR, null);}//2、根据账号查询用户信息UserInfo dbUserInfo = this.getOne(Wrappers.lambdaQuery(UserInfo.class).eq(UserInfo::getUsername, username));if (dbUserInfo == null) {throw new SpzxException(ResultCodeEnum.LOGIN_USERNAME_ERROR, null);}//判断用户状态,用户状态校验if (dbUserInfo.getStatus() != 1) {throw new SpzxException(ResultCodeEnum.LOGIN_USER_STATUS_ERROR, null);}//3、账号存在,校验密码//使用明文密码 和 盐 采用注册的加密方式加密 和数据库密文比较String encodePwd = DigestUtils.md5DigestAsHex((DigestUtils.md5DigestAsHex(password.getBytes()) + dbUserInfo.getSalt()).getBytes());if (!encodePwd.equals(dbUserInfo.getPassword())) {throw new SpzxException(ResultCodeEnum.LOGIN_PASSWORD_ERROR, null);}//密码正确//4、生成token 缓存到redis中String token = IdUtil.getSnowflake(1, 1).nextIdStr();// 将用户密码重置为null,表示清除密码信息dbUserInfo.setPassword(null);// 将用户盐值重置为null,配合密码重置,确保安全性和一致性dbUserInfo.setSalt(null);redisTemplate.opsForValue().set("spzx:user:login:" + token, dbUserInfo, 7, TimeUnit.DAYS);//登录成功:更新用户最后一次登录的时间 和 ip地址ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();HttpServletRequest request = requestAttributes.getRequest();return token;}

2.3、载荷

{"username": "18947628476","password": "123456"
}

2.4、响应

{"code":200,"message":"SUCCESS","data":"1801188891328385024"}

在这里插入图片描述

2.5、Redis Desktop Manager

{"@class": "com.atguigu.spzx.model.entity.h5.UserInfo","id": 1774759294596579329,"createTime": ["java.util.Date","2024-04-01 19:22:44"],"updateTime": ["java.util.Date",1718243055000],"deleted": false,"username": "18947628476","password": null,"nickName": "小弟","avatar": "https://cdn.apifox.com/app/project-icon/builtin/16.jpg","sex": null,"phone": null,"memo": null,"openId": null,"unionId": null,"lastLoginIp": null,"lastLoginTime": null,"status": 1,"salt": null
}

3、user服务-登录成功获取用户信息回显

在这里插入图片描述

3.1、UserController

    //auth:以后需要登录验证的接口会在路径中添加一层auth   前端访问时需要在请求头携带token@Operation( summary = "查询用户信息回显接口")@GetMapping("/auth/getCurrentUserInfo")public Result getCurrentUserInfo(@RequestHeader(value = "token",required = false)String token) {UserInfoVo userInfoVo = userInfoService.getCurrentUserInfo(token);return Result.ok(userInfoVo);}

3.2、UserInfoServiceImpl

    @Overridepublic UserInfoVo getCurrentUserInfo(String token) {UserInfo userInfo = (UserInfo) redisTemplate.opsForValue().get("spzx:user:login:" + token);if (userInfo == null) {//登录状态失效throw new SpzxException(ResultCodeEnum.LOGIN_STATUS_ERROR, null);}//UserInfo userInfo = SpzxServiceAuthInterceptor.THREAD_LOCAL.get();UserInfoVo userInfoVo = new UserInfoVo();userInfoVo.setNickName(userInfo.getNickName());userInfoVo.setAvatar(userInfo.getAvatar());return userInfoVo;}

3.3、响应

{"code": 200,"message": "SUCCESS","data": {"nickName": "小弟","avatar": "https://cdn.apifox.com/app/project-icon/builtin/16.jpg"}
}

4、登录状态验证&状态透传分析

在这里插入图片描述

4.1、gateway-过滤器统一校验登录状态

4.1.1、GlobalAuthFilter

package com.atguigu.spzx.gateway.filter;
import com.alibaba.nacos.shaded.com.google.gson.JsonObject;
import com.atguigu.spzx.model.result.ResultCodeEnum;
import jakarta.annotation.Resource;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.StringUtils;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
@Component
public class GlobalAuthFilter implements GlobalFilter, Ordered {@Resourceprivate RedisTemplate redisTemplate;@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {//1、判断请求路径是否需要验证登录状态ServerHttpRequest request = exchange.getRequest();String path = request.getURI().getPath();AntPathMatcher matcher = new AntPathMatcher();//1.1 不需要:直接放行if (!matcher.match("/**/auth/**", path)) {return chain.filter(exchange);}//1.2 需要:验证//2、获取头中的token到redis中查询登录状态 存在放行不存在返回一个Restful风格的响应报文(响应体设置一个Result对象的json)String token = request.getHeaders().getFirst("token");//redisTemplate必须和 微服务的配置一样if (StringUtils.isEmpty(token) || !redisTemplate.hasKey("spzx:user:login:" + token)) {//token不存在 或者 token 过期ServerHttpResponse response = exchange.getResponse();response.setStatusCode(HttpStatus.OK);//设置状态码//设置响应头:指定响应体内容的类型response.getHeaders().add("Content-Type", MediaType.APPLICATION_JSON_UTF8_VALUE);//设置响应体:ResultJsonObject jsonObject = new JsonObject();jsonObject.addProperty("code", ResultCodeEnum.LOGIN_STATUS_ERROR.getCode());jsonObject.addProperty("message", ResultCodeEnum.LOGIN_STATUS_ERROR.getMessage());String json = jsonObject.toString();DataBuffer buffer = response.bufferFactory().wrap(json.getBytes());//返回自定义响应报文:不放行return response.writeWith(Mono.just(buffer));}//登录状态有效 放行return chain.filter(exchange);}@Overridepublic int getOrder() {return -1;}
}

4.2、登录状态透传拦截器

4.2.1、SpzxServiceAuthInterceptor

package com.atguigu.spzx.common.handler.interceptor;
import com.atguigu.spzx.model.entity.h5.UserInfo;
import jakarta.annotation.Resource;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
@Component
public class SpzxServiceAuthInterceptor implements HandlerInterceptor {@Resourceprivate RedisTemplate redisTemplate;public static ThreadLocal<UserInfo> THREAD_LOCAL = new ThreadLocal();@Overridepublic boolean preHandle(jakarta.servlet.http.HttpServletRequest request, jakarta.servlet.http.HttpServletResponse response, Object handler) throws Exception {String token = request.getHeader("token");UserInfo userInfo = (UserInfo) redisTemplate.opsForValue().get("spzx:user:login:" + token);THREAD_LOCAL.set(userInfo);return true;}@Overridepublic void afterCompletion(jakarta.servlet.http.HttpServletRequest request, jakarta.servlet.http.HttpServletResponse response, Object handler, Exception ex) throws Exception {THREAD_LOCAL.remove();}
}

4.2.2、H5SpzxWebMvcConfigurer

package com.atguigu.spzx.common.handler.interceptor;
import jakarta.annotation.Resource;
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 H5SpzxWebMvcConfigurer implements WebMvcConfigurer {@Resourceprivate SpzxServiceAuthInterceptor spzxServiceAuthInterceptor;@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(spzxServiceAuthInterceptor).addPathPatterns("/**/auth/**");}
}

4.2.3、@EnableSpzxServiceAuth

package com.atguigu.spzx.common.handler.interceptor;
import org.springframework.context.annotation.Import;
import java.lang.annotation.*;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(value = {SpzxServiceAuthInterceptor.class, H5SpzxWebMvcConfigurer.class})
public @interface EnableSpzxServiceAuth {
}

4.2.4、UserInfoServiceImpl

    @Overridepublic UserInfoVo getCurrentUserInfo(String token) {/*UserInfo userInfo = (UserInfo) redisTemplate.opsForValue().get("spzx:user:login:" + token);if (userInfo == null) {//登录状态失效throw new SpzxException(ResultCodeEnum.LOGIN_STATUS_ERROR, null);}*/UserInfo userInfo = SpzxServiceAuthInterceptor.THREAD_LOCAL.get();UserInfoVo userInfoVo = new UserInfoVo();userInfoVo.setNickName(userInfo.getNickName());userInfoVo.setAvatar(userInfo.getAvatar());return userInfoVo;}

在这里插入图片描述

5、登录校验状态透传总结

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/1451258.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

【kubernetes】k8s中包管理工具-----Helm 超详细解读

目录 一、Helm 1.1什么是 Helm 1.2Helm 有三个重要的概念 1.2.1Chart 1.2.2Repository&#xff08;仓库&#xff09; 1.2.3Release 1.3Helm3 与 Helm2 的区别 二、Helm 部署 2.1安装 helm 2.2命令补全 2.3使用 helm 安装 Chart 2.3.1添加常用的 chart 仓库 2.3.2…

【springBoot学习篇】springBoot集成mybatis

目录 第一步&#xff1a;新建spring项目的时候&#xff0c;需要勾选mybatis框架和jdbc连接数据库的包 第二步&#xff1a;在resource目录下面的配置文件当中添加以下的内容&#xff1a;配置数据源 第三步&#xff1a;配置实体类 第四步&#xff1a;添加一个对象的增删改查方…

鸿蒙轻内核Kconfig使用笔记

鸿蒙轻内核使用Kconfig进行图形化配置&#xff0c;本文专门讲解下鸿蒙轻内核LiteOS-M和LiteOS-A的图形化配置方法。本文中所涉及的源码&#xff0c;均可以在开源站点 https://gitee.com/openharmony/kernel_liteos_a 、 https://gitee.com/openharmony/kernel_liteos_m 获取。本…

Ubuntu系统设置中文输入法

重新设置超级用户权限(root)密码(非必要) sudo passwd root 需要注意的是Ubuntu的root密码不能少于8个字符 设置成功后输入命令和新的密码即可无需输入sudo启用root命令 su - 更新软件包列表 sudo apt update sudo apt upgrade 安装fcitx5输入法框架 个别情况需要卸载旧的…

EC20通信模块升级失败 Quectel QDLoader 9008

这里写自定义目录标题 usb驱动下载固件和升级软件下载开始升级上述过程升级失败&#xff0c;出现Quectel QDLoader 9008寻找解决方案&#xff0c;事了QPS t不行&#xff0c;最终使用这个Quectel_Customer_FW_Download_Tool软件解决下载链接&#xff1a; 所有下载驱动、固件、软…

【在线OJ】发帖功能前后段代码实现

一、页面布局 二、前端代码 <template><div id"app"><div style"height: 100vh"><div style"display: flex" ><el-input style"width: 95%" v-model"title" placeholder"输入标题"&g…

【Spine学习07】之跑步动作制作思路总结

前几节试着做了待机和走路动画 现在开始尝试做跑步动作 注意跑步动作和走路一样 暂时不需要使用IK约束但是会用到塞贝尔曲线&#xff08;模拟裙子飞起动效&#xff09; 第一步&#xff1a; 先将人物整体斜放置&#xff08;因为人跑步的时候&#xff0c;身体前倾&#xff09; …

『大模型笔记』主成分分析(PCA)解释:简化机器学习中的复杂数据!

主成分分析(PCA)解释:简化机器学习中的复杂数据 文章目录 一. 主成分分析(PCA)解释:简化机器学习中的复杂数据!二. 参考文献一. 主成分分析(PCA)解释:简化机器学习中的复杂数据! 主成分分析(Principal Component Analysis,简称PCA)通过 将大型数据集中的维度减少…

借助ollama实现AI绘画提示词自由,操作简单只需一个节点!

只需要将ollama部署到本地&#xff0c;借助comfyui ollama节点即可给你的Ai绘画提示词插上想象的翅膀。具体看详细步骤&#xff01; 第一步打开ollama官网&#xff1a;https://ollama.com/&#xff0c;并选择models显存太小选择的是llama3\8b参数的instruct-q6_k的这个模型。 运…

blender bpy将顶点颜色转换为UV纹理vertex color to texture

一、关于环境 安装blender的bpy&#xff0c;不需要额外再安装blender软件。在python控制台中直接输入pip install bpy即可。 二、关于代码 本文所给出代码仅为参考&#xff0c;禁止转载和引用&#xff0c;仅供个人学习。 本文所给出的例子是https://download.csdn.net/downl…

手写轮播列表(最新) 轮播图 swiper

el-row版本: <template><div class="container-div" id="app"><div><!-- 头部开始--><div class="top1"><div class="content"><div class="list"><el-row :gutter=&quo…

在ubuntu中恢复误删除的文件

1、安装 TestDisk 在 Ubuntu 上&#xff0c;可以使用以下命令安装 TestDisk&#xff1a; sudo apt-get install testdisk2、查询你删除的文件所在那个分区 #查询分区 df -h #我这里是/dev/sda2 #也可以使用下面命令查看具体哪个分区 lsblk3、查询该分区是什么系统类型 sudo …

【网络编程】基于UDP的服务器端/客户端

UDP可看作是信件邮寄&#xff0c;邮寄过程可能会信件丢失&#xff0c;是一种不可靠的数据传输服务。 但UDP性能更高&#xff0c;实现更加简洁。流控制是区分UDP和TCP的最重要标志。 IP的作用就是让离开主机B的UDP数据包传递给主机B&#xff0c;UDP根据端口号将传到主机的数据包…

华为大咖说 | AI 是行业的未来, 还是另一个“元宇宙”?

本文作者&#xff1a;陈冠宏&#xff08;华为网络MSSD首席顾问&#xff09;全文约4497字&#xff0c;阅读约需10分钟 在本年度的517电信日上&#xff0c;中国电信高层在产品升级计划发布会中喊出“ALL in AI”战略&#xff0c;其震撼力让人瞩目。 自2022年11月OpenAI推出划时代…

【Oracle篇】rman时间点异机恢复:从RAC环境到单机测试环境的转移(第六篇,总共八篇)

&#x1f4ab;《博主介绍》&#xff1a;✨又是一天没白过&#xff0c;我是奈斯&#xff0c;DBA一名✨ &#x1f4ab;《擅长领域》&#xff1a;✌️擅长Oracle、MySQL、SQLserver、阿里云AnalyticDB for MySQL(分布式数据仓库)、Linux&#xff0c;也在扩展大数据方向的知识面✌️…

Web应用安全测试-业务功能滥用(一)

Web应用安全测试-业务功能滥用&#xff08;一&#xff09; 1、短信定向转发 漏洞描述&#xff1a;短信接收人可任意指定 测试方法&#xff1a;拦截发送短信的请求&#xff0c;将手机号改为测试人员的手机号&#xff0c;测试是否可接收短信验证码。 风险分析&#xff1a;攻击…

node更改npm缓存存储位置-并配置环境变量

更改缓存位置 node安装完成之后,在安装目录中新建一个存放缓存的文件夹node_cache 此时这个文件夹必须使用管理员权限才能更改,这使得命令行下使用npm进行下载的时候总是报权限不足的错误:permit 解决办法: 右键 -> 属性 -> 安全 -> 编辑 -> 选择user -> …

mybatis中resultMap和resultType的区别

总结 基本映射 &#xff1a;&#xff08;resultType&#xff09;使用resultType进行输出映射&#xff0c;只有查询出来的列名和pojo中的属性名一致&#xff0c;该列才可以映射成功。&#xff08;数据库&#xff0c;实体&#xff0c;查询字段,这些全部都得一一对应&#xff09;…

盲盒App开发时有哪些技术框架可以借鉴

在开发盲盒App时&#xff0c;技术框架的选择对于应用的性能、稳定性和用户体验都至关重要。以下是几个可以借鉴的技术框架&#xff0c;它们在不同方面提供了优势&#xff0c;并且结合了参考文章中的相关信息&#xff1a; 前端技术框架 微信小程序框架&#xff1a; 优点&#…

Arrays与Lambda

Arrays 默认排序&#xff1a; 按照指定规则排序&#xff1a; 细节&#xff1a; 底层原理&#xff1a; 代码实现&#xff1a;o1-o2:升序排列 o2-o1:降序排列 Lambda表达式&#xff1a;简化匿名内部类方法 函数式编程&#xff1a; 格式&#xff1a; 总结&#xff1a; …