jwt用户登录,网关给微服务传递用户信息,以及微服务间feign调用传递用户信息
1、引入jwt依赖
<dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt</artifactId><version>0.9.1</version></dependency>
2、Jwt工具类,生成token以及解析token
package com.niuniu.gateway.util;import io.jsonwebtoken.Jwt;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;import java.util.Date;
import java.util.HashMap;
import java.util.Map;public class JWTUtil {/*** 密钥*/private static final String jwtToken = "niuniu";public static String createToken(Long userId) {Map<String, Object> claims = new HashMap<>();claims.put("userId", userId);JwtBuilder jwtBuilder = Jwts.builder().signWith(SignatureAlgorithm.HS256, jwtToken) // 签发算法,密钥为jwtToken.setClaims(claims) // body数据,要唯一,自行设置.setIssuedAt(new Date()) // 设置签发时间.setExpiration(new Date(System.currentTimeMillis() + 24 * 60 * 60 * 60 * 1000)); // 一天的有效时间String token = jwtBuilder.compact();return token;}public static Map<String, Object> checkToken(String token) {try {Jwt parse = Jwts.parser().setSigningKey(jwtToken).parse(token);return (Map<String, Object>) parse.getBody();} catch (Exception e) {e.printStackTrace();}return null;}public static Long parseToken(String token) {Map<String, Object> map = JWTUtil.checkToken(token);if (map != null && map.containsKey("userId")) {return Long.parseLong(String.valueOf(map.get("userId")));}return null;}/*** main方法验证一下工具类* @param args*/public static void main(String[] args) {String token = JWTUtil.createToken(1000L);System.out.println("生成的token" + token);System.out.println("解析token" + JWTUtil.checkToken(token));}}
3、网关微服务的依赖
<!-- 负载均衡 --><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-loadbalancer</artifactId></dependency><!--用于被nacos发现该服务 被gateway发现--><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency><!-- 网关 --><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency><dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt</artifactId><version>0.9.1</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-configuration-processor</artifactId></dependency>
4、网关微服务的application.yaml
spring:application:name: gateway-servicecloud:nacos:discovery:server-addr: localhost:8848gateway:routes:- id: order-serviceuri: lb://order-servicepredicates:- Path=/order-service/**- id: product-serviceuri: lb://product-servicepredicates:- Path=/product-service/**- id: user-serviceuri: lb://user-servicepredicates:- Path=/user-service/**
server:port: 8080servlet:context-path: /gateway-service
hm:auth:excludePaths: #不需要登录就能访问的路径- /user-service/user/login- /user-service/user/hello
所有的请求都请求到网关微服务,由网关微服务再映射到对应的微服务。
例如:http://localhost:8080/user-service/user/hello 不需要登录就能访问
登录代码,登录成功给前端返回token
/*** 登录成功给前端返回token* @param name* @param password* @return*/@GetMapping("/login")public Response login(@RequestParam(name = "name") String name, @RequestParam(name = "password") String password){// 1、参数是否合法if (StringUtil.isEmpty(name) || StringUtil.isEmpty(password)) {return Response.fail("用户名或密码不能为空");}// 2、用户是否存在User user = userMapper.login(name, password);// 3、用户不存在,登录失败if (user == null) {return Response.fail("用户不存在");}// 4、用户存在,使用jwt生成token返给前端String token = JWTUtil.createToken(user.getId());// 5、将token放入redis,设置有效期限为1分钟。String key = "token_" + token;redisTemplate.opsForValue().set(key, JSONObject.toJSONString(user),System.currentTimeMillis() + 5 * 60 * 1000L, TimeUnit.MILLISECONDS);return Response.ok(token);}
5、过滤器将token解析为userId,放到请求头里
package com.niuniu.gateway.filter;import com.niuniu.common.CommonConstant;
import com.niuniu.gateway.config.AuthProperties;
import com.niuniu.gateway.util.JWTUtil;
import lombok.RequiredArgsConstructor;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.HttpStatus;
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.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;import javax.annotation.Resource;
import java.util.List;@Component
@RequiredArgsConstructor
public class AuthGlobalFilter implements GlobalFilter, Ordered {private final AuthProperties authProperties;private final AntPathMatcher antPathMatcher = new AntPathMatcher();private final RedisTemplate<String, String> redisTemplate;@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {// 1、获取requestServerHttpRequest request = exchange.getRequest();// 2、判断是否需要做登录拦截if (isExclude(request.getPath().toString())) {// 放行return chain.filter(exchange);}// 3、从请求中获取tokenString token = null;List<String> heads = request.getHeaders().get("token");if (heads != null && !heads.isEmpty()) {token = heads.get(0);}// 4、校验并解析tokenLong userId = JWTUtil.parseToken(token);if (userId == null) { // 解析失败ServerHttpResponse response = exchange.getResponse();response.setStatusCode(HttpStatus.UNAUTHORIZED);return response.setComplete();}// 如果登录超时,需要重新登录String key = CommonConstant.TOKEN_ + token;String value = redisTemplate.opsForValue().get(key);if (value == null) { // 登录超时ServerHttpResponse response = exchange.getResponse();response.setStatusCode(HttpStatus.UNAUTHORIZED);return response.setComplete();}// 5、传递用户信息ServerWebExchange swe = exchange.mutate().request(builder -> builder.header(CommonConstant.userInfo, userId.toString())).build();System.out.println("userId = " + userId);// 6、放行return chain.filter(swe);}@Overridepublic int getOrder() {return 0;}private Boolean isExclude(String path) {for (String excluedePath : authProperties.getExcludePaths()) {if ( antPathMatcher.match(excluedePath, path)) {return true;}}return false;}
}
6、拦截器将用户信息从请求头中取出来并解析,存放到ThreadLocal里
package com.niuniu.common.interceptors;import com.niuniu.common.CommonConstant;
import com.niuniu.common.utils.UserContext;
import jodd.util.StringUtil;
import org.springframework.lang.Nullable;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;/*** 前端请求到网关微服务,网关微服务再映射到具体的微服务* 如果是微服务之间的调用,此种方式则不能传递用户信息*/
public class UserInfoInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {String userInfo = request.getHeader(CommonConstant.userInfo);if (StringUtil.isNotEmpty(userInfo)) {UserContext.setUser(Long.parseLong(userInfo));}return true;}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {UserContext.removeUser();}
}
package com.niuniu.common.utils;public class UserContext {public static final ThreadLocal<Long> threadLocal = new ThreadLocal<>();public static void setUser(Long userId){threadLocal.set(userId);}public static Long getUser(){return threadLocal.get();}public static void removeUser(){threadLocal.remove();}
}
7、微服务间通过feign调用,传递用户信息。
package com.niuniu.common.config;import com.niuniu.common.CommonConstant;
import com.niuniu.common.utils.UserContext;
import feign.Logger;
import feign.RequestInterceptor;
import feign.RequestTemplate;
import org.springframework.context.annotation.Bean;public class DefaultFeignConfig {@Beanpublic Logger.Level feignLogLevel(){return Logger.Level.FULL;}@Beanpublic RequestInterceptor userInfoRequestInterceptor(){return new RequestInterceptor() {@Overridepublic void apply(RequestTemplate requestTemplate) {Long userId = UserContext.getUser();if (userId != null) {requestTemplate.header(CommonConstant.userInfo, String.valueOf(userId));}}};}
}
package com.niuniu.user.feignclient;import com.niuniu.common.config.DefaultFeignConfig;
import com.niuniu.user.model.Order;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;import java.util.List;@Component
@FeignClient(value = "order-service", configuration = DefaultFeignConfig.class)
public interface OrderClient {@GetMapping(value = "/order-service/order/getOrdersByUserId")List<Order> getOrdersByUserId(@RequestParam("userId") Long userId);
}
相关文章:

jwt用户登录,网关给微服务传递用户信息,以及微服务间feign调用传递用户信息
1、引入jwt依赖 <dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt</artifactId><version>0.9.1</version></dependency> 2、Jwt工具类,生成token以及解析token package com.niuniu.gateway.uti…...

ubontu安装anaconda
1.下载 Anaconda 安装脚本 2. 复制到服务器上/home/username文件夹中,进入文件夹,执行: bash Anaconda3-2024.10-1-Linux-x86_64.sh一直按回车,然后输入yes同意协议。 3. 初始化 Anaconda 环境,会自动配置环境变量&a…...

【Docker容器化技术】docker安装与配置、常用命令、容器数据卷、应用部署实战、Dockerfile、服务编排docker-compose、私有仓库
文章目录 一、Docker的安装与配置1、docker概述2、安装docker3、docker架构4、配置镜像加速器 二、Docker命令1、服务相关命令2、镜像相关命令3、容器相关命令 三、Docker容器数据卷1、数据卷概念及作用2、配置数据卷3、配置数据卷容器 四、Docker应用部署实战1、部署MySQL2、部…...
Python模拟A卷实操题
1.某机械公司生产两种产品。A的单件利润分别是100元,B的单件利润是150元。 每种产品由三种材料构成,现给出每种材料的库存(库存小于100000),求利润最大的生产方案。输入说明:第一行给出生产每件A产品所需要…...
Leetcode 检测相邻递增子数组
3349. 检测相邻递增子数组 I 给你一个由 n 个整数组成的数组 nums ,请你找出 k 的 最大值,使得存在 两个 相邻 且长度为 k 的 严格递增 子数组 。具体来说,需要检查是否存在从下标 a 和 b (a < b) 开始的 两个 子数组,并满…...
rockylinux 8安装 gcc11.2
方法 1:从源代码编译安装最新版本的 GCC 下载 GCC 源代码: 访问 GCC 官方网站下载最新版本的源代码,例如: wget https://ftp.gnu.org/gnu/gcc/gcc-11.2.0/gcc-11.2.0.tar.gz tar -xf gcc-11.2.0.tar.gz cd gcc-11.2.0安装依赖项&a…...
【蓝桥等考C++真题】蓝桥杯等级考试C++组第13级L13真题原题(含答案)-奇数序列排序
C L13 奇数序列排序 给定一个长度为N的正整数序列, 请将其中的所有奇数取出,并按增序(从小到大)输出。 输入: 共2行 第1行是一个正整数 N(不大于500); 第2行有 N 个正整数&#x…...
【AI】好用的AI记录
好用的AI 一、国内 KIMI通义 二、国外 GPT4Cursorv0...
linux安装boost.python
前言 boost.python库被用于C与Python代码间的交互,提供了两者间大部分数据类型的转换 相关环境 操作系统:Ubuntu 20.04 python版本:Python 3.8 boost版本:boost 1.78.0 安装 1.boost.python检查与卸载 在安装boost之前需要检…...
AI 扩展开发者思维方式:以 SQL 查询优化为例
在现代软件开发中,AI 技术的兴起让开发者的思维方式发生了显著变化。尤其是在 SQL 查询优化、代码重构以及算法设计等领域,AI 提供的建议不仅扩展了开发者的思考路径,还帮助他们发现以往没有意识到的潜在解决方案。 1. 传统思维模式下的 SQL…...

自定义面板,高效的游戏性能分析利器
为了更有效地聚焦并解决性能问题,UWA报告采用了分模块监控策略,确保每个模块独立成章,各司其职。然而,随着对性能分析需求的不断升级,我们已经意识到,在深入分析某些跨模块的性能瓶颈或优化点时,…...

【Linux进程特别篇】深度理解辨识僵尸进程和孤儿进程
--------------------------------------------------------------------------------------------------------------------------------- 每日鸡汤:每一份坚持都是成功的积累,只要相信自己,总会遇到惊喜。 -----------------------------…...

喜报|超维机器人荣获昇腾AI创新大赛铜奖
近日,在备受瞩目的昇腾AI创新大赛中,超维机器人凭借扎实的技术实力和创新产品,荣获大赛铜奖。这一荣誉不仅展现了超维机器人在智能巡检领域的技术创新与突破,也标志着超维机器人的智能巡检解决方案在人工智能领域获得了广泛认可&a…...
从五种架构风格推导出HTTP的REST架构
在分布式系统中,架构风格(Architectural Style)决定了系统组件如何交互、通信、存储和管理数据。每种架构风格都有其独特的特性和适用场景。本文将从五种典型的架构风格出发,逐步探讨它们如何影响了REST(Representational State Transfer,表述性状态转移)架构风格的设计…...

vue-h5:在h5中实现相机拍照加上身份证人相框和国徽框
方案1:排出来照片太糊了,效果不好 1.基础功能 参考: https://blog.csdn.net/weixin_45148022/article/details/135696629 https://juejin.cn/post/7327353533618978842?searchId20241101133433B2BB37A081FD6A02DA60 https://www.freesio…...

免费HTML模板和CSS样式网站汇总
HTML模板:(注意版权,部分不可商用) 1、Tooplate,免费HTML模板下载 Download 60 Free HTML Templates for your websitesDownload 60 free HTML website templates or responsive Bootstrap templates instantly from T…...
Mac打开time machine(时间机器)备份特殊文件
Mac 打开time machine(时间机器)备份特殊文件 设置“时间机器”的作用具体操作办法 前言:今天在使用Nas同步文件时发现有部分重要文件没有同步,为了省事手动拖拽复制文件,导致其中一份非常重要的文件丢失,尝…...

Qt 学习第十六天:文件和事件
一、创建widget对象(文件) 二、设计ui界面 放一个label标签上去,设置成box就可以显示边框了 三、新建Mylabel类 四、提升ui界面的label标签为Mylabel 五、修改mylabel.h,mylabel.cpp #ifndef MYLABEL_H #define MYLABEL_H#incl…...
nvm 切换 Node.js 版本
nvm 切换 Node.js 版本 0. nvm 安装1. 查看装了哪些 Node.js 版本2. 安装 Node.js 版本安装最新稳定版本.安装个18 3. 切换 Node.js 版本4. 设置默认 Node.js 版本5. 卸载 Node.js 版本6.与项目的配合使用参考资料 0. nvm 安装 安装教程就不写了,直接看别人的。 脚…...

AI绘图最强软件stable diffusion,一文带你迅速了解!
有需要stable diffusion整合包可以扫描下方,免费获取 01 — 什么是 SD Stable Difusion(简称 SD) 其三种概念。 1.用来指代稳定扩散(Stable Diffusion) 技术,如 Midjourney是基于Stable Difusion技术实现的就是指它运用了 Stable Diffusion 的技术原理。 …...

龙虎榜——20250610
上证指数放量收阴线,个股多数下跌,盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型,指数短线有调整的需求,大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的:御银股份、雄帝科技 驱动…...

深入浅出Asp.Net Core MVC应用开发系列-AspNetCore中的日志记录
ASP.NET Core 是一个跨平台的开源框架,用于在 Windows、macOS 或 Linux 上生成基于云的新式 Web 应用。 ASP.NET Core 中的日志记录 .NET 通过 ILogger API 支持高性能结构化日志记录,以帮助监视应用程序行为和诊断问题。 可以通过配置不同的记录提供程…...

微软PowerBI考试 PL300-选择 Power BI 模型框架【附练习数据】
微软PowerBI考试 PL300-选择 Power BI 模型框架 20 多年来,Microsoft 持续对企业商业智能 (BI) 进行大量投资。 Azure Analysis Services (AAS) 和 SQL Server Analysis Services (SSAS) 基于无数企业使用的成熟的 BI 数据建模技术。 同样的技术也是 Power BI 数据…...

大型活动交通拥堵治理的视觉算法应用
大型活动下智慧交通的视觉分析应用 一、背景与挑战 大型活动(如演唱会、马拉松赛事、高考中考等)期间,城市交通面临瞬时人流车流激增、传统摄像头模糊、交通拥堵识别滞后等问题。以演唱会为例,暖城商圈曾因观众集中离场导致周边…...

【HarmonyOS 5.0】DevEco Testing:鸿蒙应用质量保障的终极武器
——全方位测试解决方案与代码实战 一、工具定位与核心能力 DevEco Testing是HarmonyOS官方推出的一体化测试平台,覆盖应用全生命周期测试需求,主要提供五大核心能力: 测试类型检测目标关键指标功能体验基…...

新能源汽车智慧充电桩管理方案:新能源充电桩散热问题及消防安全监管方案
随着新能源汽车的快速普及,充电桩作为核心配套设施,其安全性与可靠性备受关注。然而,在高温、高负荷运行环境下,充电桩的散热问题与消防安全隐患日益凸显,成为制约行业发展的关键瓶颈。 如何通过智慧化管理手段优化散…...
css的定位(position)详解:相对定位 绝对定位 固定定位
在 CSS 中,元素的定位通过 position 属性控制,共有 5 种定位模式:static(静态定位)、relative(相对定位)、absolute(绝对定位)、fixed(固定定位)和…...
在鸿蒙HarmonyOS 5中使用DevEco Studio实现录音机应用
1. 项目配置与权限设置 1.1 配置module.json5 {"module": {"requestPermissions": [{"name": "ohos.permission.MICROPHONE","reason": "录音需要麦克风权限"},{"name": "ohos.permission.WRITE…...

10-Oracle 23 ai Vector Search 概述和参数
一、Oracle AI Vector Search 概述 企业和个人都在尝试各种AI,使用客户端或是内部自己搭建集成大模型的终端,加速与大型语言模型(LLM)的结合,同时使用检索增强生成(Retrieval Augmented Generation &#…...
解决:Android studio 编译后报错\app\src\main\cpp\CMakeLists.txt‘ to exist
现象: android studio报错: [CXX1409] D:\GitLab\xxxxx\app.cxx\Debug\3f3w4y1i\arm64-v8a\android_gradle_build.json : expected buildFiles file ‘D:\GitLab\xxxxx\app\src\main\cpp\CMakeLists.txt’ to exist 解决: 不要动CMakeLists.…...