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.mzph.cn/news/852576.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Unity资源 之 最受欢迎的三消游戏开发包 - Bubble Shooter Kit 【免费领取】

三消游戏开发包 - Bubble Shooter Kit 免费领取 前言资源包内容领取兑换码 前言 如果你是一名 Unity 游戏开发者&#xff0c;并且正在寻找一种快速、简单的方式来创建自己的三消游戏&#xff0c;那么 Bubble Shooter Kit 就是你所需要的。 资源包内容 Bubble Shooter Kit 是…

英文语法工具Grammarly for Word下载和安装

前言&#xff1a;论文写作语法检查和润色的时候&#xff0c;可以用Grammarly进行帮助。 Grammarly for Word的下载、安装、使用 官网下载Grammarly for Microsoft Office安装GrammarlyWord使用GrammarlyGrammarly使用 官网下载Grammarly for Microsoft Office 地址&#xff1…

【全开源】ChatGPT 机器人公众号小程序h5源码开源交付支持二开

AI机器人系统对接OPENAI&#xff1a;智能互联的无限可能 &#x1f310; 一、引言&#xff1a;AI机器人系统与OPENAI的碰撞 在科技日新月异的今天&#xff0c;AI机器人系统正逐渐渗透到我们生活的各个角落。而当这一智能系统与全球领先的OPENAI技术相结合&#xff0c;又将擦出…

【CT】LeetCode手撕—33. 搜索旋转排序数组

目录 题目1-思路1-1 模式识别&#xff1a;1-2 二分模板 && 本质二分红色边界二分绿色边界 1-3 本题思路①二分出第一个区间②判断 target 在哪个区间③利用二分性质 2- 实现⭐33. 搜索旋转排序数组——题解思路 3- ACM实现 题目 原题连接&#xff1a;33. 搜索旋转排序…

MathTpye7最新版软件下载与安装步骤2024最新新手小白教程

在2024年&#xff0c;作为软件开发者的你&#xff0c;一定知道MathType这款广受欢迎的数学公式编辑器吧&#xff01;&#x1f4f1;&#x1f50b;&#x1f4b0;&#x1f9ee; MathType是一款功能强大的数学公式编辑工具。无论是学术研究&#x1f4da;还是数字教育&#x1f469;‍…

火车头采集怎么使用GPT等AI原创文章

火车头采集官方并没有GPT、百度文心一言AI、阿里通义千问AI、Kimi大模型等AI功能&#xff0c;但支持接入插件&#xff0c;可以编写相应人工智能AI原创文章插件&#xff08;火车头采集支持PHP和c#这2种语言的插件编写&#xff09;&#xff0c;或者导入第三方封装好的GPT等AI原创…

【收藏】Web 前端知识体系精简【文末福利!】赠2024Web 前端/安全工程师资料视频教程+源码+课件

目录 JAVASCRIPT 篇 0、基础语法 1、函数原型链 2、函数作用域 3、函数指针 this 4、构造函数 new 5、闭包 6、单线程和异步队列 7、异步通讯 Ajax技术 8、DOM对象 document 9、事件系统 Event 10、全局对象 window CSS 篇 1、选择器 2、定位 3、浮动 4、盒子…

人脸识别系统---人脸对比

一、人脸对比 1.定义全局变量来存储选择的图片路径和标签 save_image1 None save_image2 None image_label1 None image_label2 None2.定义了一个名为compare_faces的函数&#xff0c;用于比较两张图片中的人脸是否相似 def compare_faces():if save_image1 and save_im…

远程开发端口转发

应用推荐场景&#xff1a; 1.服务器跑后台&#xff0c;本地出前端应用。 比如Stable Diffusion的大模型打标应用。 2.Docker容器服务器。 对于本地服务想要转出去&#xff0c;跑出来前端。该项能克服虚拟机的端口与ip访问问题。 正文&#xff1a; 涉及的软件&#xff1a; …

二级造价师精选基础知识题库(含答案)

一.单项选择题: 1.大中型建设工程项目立项批准后&#xff0c;在工程开工前&#xff0c;应当由( )按照有关规定申请领取施工许可证。A.建设单位 B.施工单位 C.总承包单位 D.监理单位 2.建设单位申领建筑工程施工许可证后&#xff0c;既不开工又不申请延期或者超过延期时限的&a…

14,15-EET/DHET Hypertension ELISA Kit--Detroit RD

用于14,15-EET/DHET测量的DH2与用于14,15-DHET测量的DH1相同。与DH2相比&#xff0c;与DH1的唯一区别是样品制备步骤&#xff08;而不是Elisa试剂盒&#xff09;&#xff0c;其中EET被化学改为DHET。 货号&#xff1a;DH2 名称&#xff1a;14,15-EET/DHET Hypertension ELISA…

C#——值类型和引用类型的区别详情

值类型和引用类型的区别 值类型 值类型&#xff1a; 常用的基本数据类型都是值类型&#xff1a;bool 、char、int、 double、 float、long 、 byte 、ulong、uint、枚举类型、 结构体类型等特点: 在赋值的过程当中&#xff0c;把值的本身赋值给另一个变量&#xff0c;再修改…

使用 PNPM 从零搭建 Monorepo,测试组件并发布

1 目标 通过 PNPM 创建一个 monorepo&#xff08;多个项目在一个代码仓库&#xff09;项目&#xff0c;形成一个通用的仓库模板。 这里以在该 monorepo 项目中搭建 web components 类型的组件库为例&#xff0c;介绍从仓库搭建、组件测试到组件发布的整个流程。 这个仓库既可…

gpt、llama大模型模型结构细节探索

参考&#xff1a; https://github.com/naklecha/llama3-from-scratch&#xff08;一定要看看&#xff09; https://github.com/karpathy/build-nanogpt/blob/master/play.ipynb 视频&#xff1a; https://www.youtube.com/watch?vl8pRSuU81PU https://tiktokenizer.vercel…

SiLM59xx系列SiLM5932SHOCG-DG 一款支持主动短路保护功能(ASC)单通道隔离驱动器

SiLM59xx系列SiLM5932SHOCG-DG是一款单通道隔离驱动器&#xff0c;提供12A源电流和12A灌电流。主动保护功能包括退饱和过流检测、UVLO、隔离故障报警和 4A 米勒钳位。输入侧电源的工作电压为3V至5.5V&#xff0c;输出侧电源的工作电压范围为13V至30V。所有电源电压引脚都有欠压…

Java面向对象之static关键字,可变参数,递归,数组常见算法,对象数组,方法参数

第一章.static关键字 1.static的介绍以及基本使用 1.概述:static是一个静态关键字 2.使用:a.修饰一个成员变量:static 数据类型 变量名b.修饰一个方法:修饰符 static 返回值类型 方法名(形参){方法体return 结果}3.调用静态成员:类名直接调用(不用new对象)4.静态成员特点:a.静…

后端返回前端时间格式化

时间格式化的方法总共包含以下 5 种。 1.前端时间格式化 JS 版时间格式化 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 function dateFormat(fmt, date) { let ret; const opt { "Y": date.getFullYear().toString(), // 年 …

Python学习从0开始——Kaggle深度学习002

Python学习从0开始——Kaggle深度学习002 一、单个神经元1.深度学习2.线性单元示例 - 线性单元作为模型多个输入 3.Keras中的线性单元 二、深度神经网络1.层多种类型的层 2.激活函数3.堆叠密集层4.构建Sequential模型 三、随机梯度下降1.介绍2.损失函数3.梯度下降法1.梯度下降法…

FL Studio(FL 21)软件下载-详细安装教程视频

​fl studio 编曲软件即,简称FL,是音乐人熟知的水果编曲软件.可以完成完整的音乐制作环境或数字音频工作站(DAW)就是大家熟悉的水果 编曲软件&#xff0c;一个全能的音乐制作软件&#xff0c;包括编曲、录音、剪辑和混音等诸多功能&#xff0c;让你的电脑编程一个全能的录音室。…

海南云亿商务咨询有限公司解锁抖音电商新纪元

在当今数字化浪潮中&#xff0c;抖音电商以其独特的魅力和强大的用户基础&#xff0c;迅速成为企业营销的新宠。海南云亿商务咨询有限公司&#xff0c;作为专注于抖音电商服务的领先企业&#xff0c;凭借专业的团队和丰富的经验&#xff0c;为众多企业提供了高效、精准的电商服…