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);
}

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

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

相关文章

SQL练习(2)

题源&#xff1a;牛客官网 选择题 假设创建新用户nkw&#xff0c;现在想对于任何IP的连接&#xff0c;仅拥有user数据库里面的select和insert权限&#xff0c;则列表语句中能够实现这一要求的语句是&#xff08;&#xff09; A grant select ,insert on *.* to nkw% B grant…

【MySQL从入门到放弃】InnoDB磁盘结构(一)

前言 从MySQL 5.5版本开始默认 使用InnoDB作为引擎&#xff0c;它擅长处理事务&#xff0c;具有自动崩溃恢复的特性&#xff0c;在日常开发中使用非常广泛。 下面是官方的InnoDB引擎架构图&#xff0c;主要分为内存结构和磁盘结构两大部分。 上一篇文章&#xff0c;我们解析了…

RT-DETR融合CVPR[2020]轻量化卷积模块Ghost Module模块

RT-DETR使用教程&#xff1a; RT-DETR使用教程 RT-DETR改进汇总贴&#xff1a;RT-DETR更新汇总贴 《GhostNet: More Features from Cheap Operations》 一、 模块介绍 论文链接&#xff1a;https://arxiv.org/abs/1911.11907 代码链接&#xff1a;GitHub - huawei-noah/Effici…

《TCP/IP网络编程》学习笔记 | Chapter 11:进程间通信

《TCP/IP网络编程》学习笔记 | Chapter 11&#xff1a;进程间通信 《TCP/IP网络编程》学习笔记 | Chapter 11&#xff1a;进程间通信进程间通信的基本概念通过管道实现进程间通信通过管道进行进程间双向通信 运用进程间通信习题&#xff08;1&#xff09;什么是进程间通信&…

2024 kali操作系统安装Docker步骤

1、更新系统 在开始之前&#xff0c;确保你的Kali系统是最新的。打开终端并运行以下命令&#xff1a; apt update 2、安装 apt install docker.io 3、查看启动状态 systemctl status docker 4、安装完 Docker 后&#xff0c;启动 systemctl start docker 5、启动并使…

LLMs之Code:Github Spark的简介、安装和使用方法、案例应用之详细攻略

LLMs之Code&#xff1a;Github Spark的简介、安装和使用方法、案例应用之详细攻略 目录 Github Spark的简介 Github Spark的安装和使用方法 1、安装 2、使用方法 Github Spark的案例应用 Github Spark的简介 2024年10月30日&#xff0c;GitHub 重磅发布GitHub Spark 是一…

MySQL数据库:SQL语言入门 【上】(学习笔记)

SQL&#xff08;Structured Query Language&#xff09;是结构化查询语言的简称&#xff0c;它是一种数据库查询和程序设计语言&#xff0c;同时也是目前使用最广泛的关系型数据库操作语言。&#xff08;95%适用于所有关系型数据库&#xff09; 【 SQL是关系型数据库通用的操作…

腾讯云nginx SSL证书配置

本章教程,记录在使用腾讯云域名nginx证书配置SSL配置过程。 一、nginx配置 域名和证书,替换成自己的即可。证书文件可以自定义路径位置。服务器安全组或者防火墙需要开放80和443端口。 server {#SSL 默认访问端口号为 443listen 443 ssl; #请填写绑定证书的域名server_name c…

使用electron-egg把vue项目在linux Ubuntu环境下打包并安装运行

electron-egg一个入门简单、跨平台、企业级桌面软件开发框架https://www.kaka996.com/electron-egg 跳转地址 1,使用 git下载代码到本地,如果没有git需要进行安装 # gitee git clone https://gitee.com/dromara/electron-egg.git # github git clone https://github.com/dro…

Nginx配置自带的stub状态实现活动监控指标

场景 为了确保应用以最佳性能和精度运行&#xff0c;需要清晰地了解有关其活动的监控指标。 NGINX 提供了多种监控选项&#xff0c;例如 stub 状态。 注&#xff1a; 博客&#xff1a;霸道流氓气质-CSDN博客 实现 启用 NGINX stub 状态 启用 NGINX HTTP 服务器内 locati…

vscode下nuget包的本地引入方法

优势&#xff1a; nuget包的本地引入可以方便打包后的本地测试&#xff0c;确保打包正确、功能完善后再上传至nuget服务端本地引入方式也极为简单&#xff0c;三步操作即可搞定&#xff0c;熟悉之后这个操作2分钟内就可以搞定 具体步骤&#xff08;以引入Epic.RobotService包…

【知识科普】SPA单页应用程序介绍

SPA单页应用程序 概述和传统的多页应用有什么区别&#xff1f;用户体验架构和开发性能和优化SEO&#xff08;搜索引擎优化&#xff09;维护和扩展 如何优化SEO服务端渲染和预渲染有什么区别&#xff1f; 概述 SPA&#xff0c;全称为Single Page Application&#xff08;单页应用…

免费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…

深入理解接口测试:实用指南与最佳实践5.0(二)

✨博客主页&#xff1a; https://blog.csdn.net/m0_63815035?typeblog &#x1f497;《博客内容》&#xff1a;.NET、Java.测试开发、Python、Android、Go、Node、Android前端小程序等相关领域知识 &#x1f4e2;博客专栏&#xff1a; https://blog.csdn.net/m0_63815035/cat…

【go从零单排】Random Numbers、Number Parsing

&#x1f308;Don’t worry , just coding! 内耗与overthinking只会削弱你的精力&#xff0c;虚度你的光阴&#xff0c;每天迈出一小步&#xff0c;回头时发现已经走了很远。 &#x1f4d7;概念 这里是引用 &#x1f4bb;代码 Random Numbers package mainimport ("fmt…

网页web无插件播放器EasyPlayer.js点播播放器遇到视频地址播放不了的现象及措施

在数字媒体时代&#xff0c;视频点播已成为用户获取信息和娱乐的重要方式。EasyPlayer.js作为一款流行的点播播放器&#xff0c;以其强大的功能和易用性受到广泛欢迎。然而&#xff0c;在使用过程中&#xff0c;用户可能会遇到视频地址无法播放的问题&#xff0c;这不仅影响用户…

mysql5.7安装SSL报错解决(2),总结

Caused by: java.io.EOFException: SSL peer shut down incorrectly 在java里面连接mysql5.7.17数据库&#xff0c;报以上错误&#xff0c; 将数据库升级到mysql5.7.44就可以了。 这两天处理java连接mysql的问题&#xff0c;报了各种错误&#xff0c;总结一下就是openssl和mysq…

vue项目npm run serve出现【- Network: unavailable】(从排查到放弃)

1. 问题现象 环境&#xff1a; 系统&#xff1a;win11node&#xff1a;v16.20.2“vue”: “2.6.10” 执行npm run serve启动vue项目&#xff0c;期望&#xff1a; App running at:- Local: http://localhost:9528/ - Network: http://x.x.x.x:9528/实际&#xff1a; App runn…

【vue2.0入门】vue单文件组件

目录 引言一、配置编辑器vue2代码片段模版1. 配置vue2代码模版2. 使用vue模版 二、模版介绍1. template区域2. script 区域2.1 name2.2 components2.3 props2.4 data2.5 computed2.6 watch2.7 methods2.8 生命周期函数 3. style 区域 三、总结 引言 本系列教程旨在帮助一些零基…

外星人入侵

学习于Python编程从入门到实践&#xff08;Eric Matthes 著&#xff09; 整体目录&#xff1a;外星人入侵文件夹是打包后的不必在意 图片和音效都是网上下载的 音效下载网站&#xff1a;Free 游戏爆击中 Sound Effects Download - Pixabay 运行效果&#xff1a;可以上下左右移…