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

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工具类&#xff0c;生成token以及解析token package com.niuniu.gateway.uti…...

ubontu安装anaconda

1.下载 Anaconda 安装脚本 2. 复制到服务器上/home/username文件夹中&#xff0c;进入文件夹&#xff0c;执行&#xff1a; bash Anaconda3-2024.10-1-Linux-x86_64.sh一直按回车&#xff0c;然后输入yes同意协议。 3. 初始化 Anaconda 环境&#xff0c;会自动配置环境变量&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元&#xff0c;B的单件利润是150元。 每种产品由三种材料构成&#xff0c;现给出每种材料的库存&#xff08;库存小于100000&#xff09;&#xff0c;求利润最大的生产方案。输入说明&#xff1a;第一行给出生产每件A产品所需要…...

Leetcode 检测相邻递增子数组

3349. 检测相邻递增子数组 I 给你一个由 n 个整数组成的数组 nums &#xff0c;请你找出 k 的 最大值&#xff0c;使得存在 两个 相邻 且长度为 k 的 严格递增 子数组 。具体来说&#xff0c;需要检查是否存在从下标 a 和 b (a < b) 开始的 两个 子数组&#xff0c;并满…...

rockylinux 8安装 gcc11.2

方法 1&#xff1a;从源代码编译安装最新版本的 GCC 下载 GCC 源代码&#xff1a; 访问 GCC 官方网站下载最新版本的源代码&#xff0c;例如&#xff1a; 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的正整数序列&#xff0c; 请将其中的所有奇数取出&#xff0c;并按增序&#xff08;从小到大&#xff09;输出。 输入&#xff1a; 共2行 第1行是一个正整数 N&#xff08;不大于500&#xff09;&#xff1b; 第2行有 N 个正整数&#x…...

【AI】好用的AI记录

好用的AI 一、国内 KIMI通义 二、国外 GPT4Cursorv0...

linux安装boost.python

前言 boost.python库被用于C与Python代码间的交互&#xff0c;提供了两者间大部分数据类型的转换 相关环境 操作系统&#xff1a;Ubuntu 20.04 python版本&#xff1a;Python 3.8 boost版本&#xff1a;boost 1.78.0 安装 1.boost.python检查与卸载 在安装boost之前需要检…...

AI 扩展开发者思维方式:以 SQL 查询优化为例

在现代软件开发中&#xff0c;AI 技术的兴起让开发者的思维方式发生了显著变化。尤其是在 SQL 查询优化、代码重构以及算法设计等领域&#xff0c;AI 提供的建议不仅扩展了开发者的思考路径&#xff0c;还帮助他们发现以往没有意识到的潜在解决方案。 1. 传统思维模式下的 SQL…...

自定义面板,高效的游戏性能分析利器

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

【Linux进程特别篇】深度理解辨识僵尸进程和孤儿进程

--------------------------------------------------------------------------------------------------------------------------------- 每日鸡汤&#xff1a;每一份坚持都是成功的积累&#xff0c;只要相信自己&#xff0c;总会遇到惊喜。 -----------------------------…...

喜报|超维机器人荣获昇腾AI创新大赛铜奖

近日&#xff0c;在备受瞩目的昇腾AI创新大赛中&#xff0c;超维机器人凭借扎实的技术实力和创新产品&#xff0c;荣获大赛铜奖。这一荣誉不仅展现了超维机器人在智能巡检领域的技术创新与突破&#xff0c;也标志着超维机器人的智能巡检解决方案在人工智能领域获得了广泛认可&a…...

从五种架构风格推导出HTTP的REST架构

在分布式系统中,架构风格(Architectural Style)决定了系统组件如何交互、通信、存储和管理数据。每种架构风格都有其独特的特性和适用场景。本文将从五种典型的架构风格出发,逐步探讨它们如何影响了REST(Representational State Transfer,表述性状态转移)架构风格的设计…...

vue-h5:在h5中实现相机拍照加上身份证人相框和国徽框

方案1&#xff1a;排出来照片太糊了&#xff0c;效果不好 1.基础功能 参考&#xff1a; https://blog.csdn.net/weixin_45148022/article/details/135696629 https://juejin.cn/post/7327353533618978842?searchId20241101133433B2BB37A081FD6A02DA60 https://www.freesio…...

免费HTML模板和CSS样式网站汇总

HTML模板&#xff1a;&#xff08;注意版权&#xff0c;部分不可商用&#xff09; 1、Tooplate&#xff0c;免费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&#xff08;时间机器&#xff09;备份特殊文件 设置“时间机器”的作用具体操作办法 前言&#xff1a;今天在使用Nas同步文件时发现有部分重要文件没有同步&#xff0c;为了省事手动拖拽复制文件&#xff0c;导致其中一份非常重要的文件丢失&#xff0c;尝…...

Qt 学习第十六天:文件和事件

一、创建widget对象&#xff08;文件&#xff09; 二、设计ui界面 放一个label标签上去&#xff0c;设置成box就可以显示边框了 三、新建Mylabel类 四、提升ui界面的label标签为Mylabel 五、修改mylabel.h&#xff0c;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 安装 安装教程就不写了&#xff0c;直接看别人的。 脚…...

AI绘图最强软件stable diffusion,一文带你迅速了解!

有需要stable diffusion整合包可以扫描下方&#xff0c;免费获取 01 — 什么是 SD ​ Stable Difusion(简称 SD) 其三种概念。 1.用来指代稳定扩散(Stable Diffusion) 技术,如 Midjourney是基于Stable Difusion技术实现的就是指它运用了 Stable Diffusion 的技术原理。 …...

idea大量爆红问题解决

问题描述 在学习和工作中&#xff0c;idea是程序员不可缺少的一个工具&#xff0c;但是突然在有些时候就会出现大量爆红的问题&#xff0c;发现无法跳转&#xff0c;无论是关机重启或者是替换root都无法解决 就是如上所展示的问题&#xff0c;但是程序依然可以启动。 问题解决…...

vscode里如何用git

打开vs终端执行如下&#xff1a; 1 初始化 Git 仓库&#xff08;如果尚未初始化&#xff09; git init 2 添加文件到 Git 仓库 git add . 3 使用 git commit 命令来提交你的更改。确保在提交时加上一个有用的消息。 git commit -m "备注信息" 4 …...

linux之kylin系统nginx的安装

一、nginx的作用 1.可做高性能的web服务器 直接处理静态资源&#xff08;HTML/CSS/图片等&#xff09;&#xff0c;响应速度远超传统服务器类似apache支持高并发连接 2.反向代理服务器 隐藏后端服务器IP地址&#xff0c;提高安全性 3.负载均衡服务器 支持多种策略分发流量…...

逻辑回归:给不确定性划界的分类大师

想象你是一名医生。面对患者的检查报告&#xff08;肿瘤大小、血液指标&#xff09;&#xff0c;你需要做出一个**决定性判断**&#xff1a;恶性还是良性&#xff1f;这种“非黑即白”的抉择&#xff0c;正是**逻辑回归&#xff08;Logistic Regression&#xff09;** 的战场&a…...

ssc377d修改flash分区大小

1、flash的分区默认分配16M、 / # df -h Filesystem Size Used Available Use% Mounted on /dev/root 1.9M 1.9M 0 100% / /dev/mtdblock4 3.0M...

【配置 YOLOX 用于按目录分类的图片数据集】

现在的图标点选越来越多&#xff0c;如何一步解决&#xff0c;采用 YOLOX 目标检测模式则可以轻松解决 要在 YOLOX 中使用按目录分类的图片数据集&#xff08;每个目录代表一个类别&#xff0c;目录下是该类别的所有图片&#xff09;&#xff0c;你需要进行以下配置步骤&#x…...

从零实现STL哈希容器:unordered_map/unordered_set封装详解

本篇文章是对C学习的STL哈希容器自主实现部分的学习分享 希望也能为你带来些帮助~ 那咱们废话不多说&#xff0c;直接开始吧&#xff01; 一、源码结构分析 1. SGISTL30实现剖析 // hash_set核心结构 template <class Value, class HashFcn, ...> class hash_set {ty…...

土地利用/土地覆盖遥感解译与基于CLUE模型未来变化情景预测;从基础到高级,涵盖ArcGIS数据处理、ENVI遥感解译与CLUE模型情景模拟等

&#x1f50d; 土地利用/土地覆盖数据是生态、环境和气象等诸多领域模型的关键输入参数。通过遥感影像解译技术&#xff0c;可以精准获取历史或当前任何一个区域的土地利用/土地覆盖情况。这些数据不仅能够用于评估区域生态环境的变化趋势&#xff0c;还能有效评价重大生态工程…...

12.找到字符串中所有字母异位词

&#x1f9e0; 题目解析 题目描述&#xff1a; 给定两个字符串 s 和 p&#xff0c;找出 s 中所有 p 的字母异位词的起始索引。 返回的答案以数组形式表示。 字母异位词定义&#xff1a; 若两个字符串包含的字符种类和出现次数完全相同&#xff0c;顺序无所谓&#xff0c;则互为…...

tree 树组件大数据卡顿问题优化

问题背景 项目中有用到树组件用来做文件目录&#xff0c;但是由于这个树组件的节点越来越多&#xff0c;导致页面在滚动这个树组件的时候浏览器就很容易卡死。这种问题基本上都是因为dom节点太多&#xff0c;导致的浏览器卡顿&#xff0c;这里很明显就需要用到虚拟列表的技术&…...