spring cloud之gateway和JWT回顾

devtools/2025/1/23 5:24:22/

最开始学习时,没怎么用,只知道它是网关,当时因为经常使用Nginx做网关,慢慢就淡忘了,最近为了代码整合性,就使用它,非常棒。关于JWT以前也使用,后面调用基本以第三方接口开发的比较多,当时自己的服务,添加自己的规则生成token

gateway_1">整合gateway网关

1、pom

<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-client</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis-reactive</artifactId></dependency><dependency><groupId>com.xl</groupId><artifactId>auth-service-api</artifactId><version>${project.version}</version><exclusions><exclusion><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></exclusion></exclusions></dependency></dependencies>

其中auth-service-api和redis后面会用到,当前用不到

2、启动类注解

// 没有什么特别的
@EnableDiscoveryClient
@SpringBootApplication
@EnableFeignClients

启动程序后,直接访问http://localhost:25200/actuator,寻找gateway,在访问/actuator/gateway,c此时会报错404,请求错误,我们要看路由,加上/routes,查看json,大概就知道怎么访问了,http://localhost:25200/feign-client/sayHi,如果是多个feign-client服务,自动就负载均衡了,是不是比nginx方便多了。

3、配置文件

spring:application:name: gateway-sampleredis:host: localhostport: 6379database: 0# 开始配置cloud:gateway:discovery:locator:enabled: truelower-case-service-id: true # FEIGN-CLIENT可以小写访问routes:- id: ymluri: lb://FEIGN-CLIENTpredicates:- Path=/yml/**filters:- StripPrefix=1# 结束配置# 下面这里是限流配置- name: RequestRateLimiterargs:key-resolver: '#{@remoteAddrKeyResolver}'redis-rate-limiter.replenishRate: 1 # 每秒填充令牌redis-rate-limiter.burstCapacity: 1 # 总令牌,举个例子:假设现在令牌是满的,也就是总令牌20个,每秒填充为10,总共20,当前请求数为9,第一秒时,处理了9个,还剩11个,此时每秒会填充10个,此时有21个,但由于限制总令牌为20个,此时就是20个,第二秒时同理,如果每秒30个,第一秒会限流10个,报429,第二秒会限流20个,报429。server:port: 25200
management:cloudfoundry:enabled: falseendpoints:web:exposure:include: "*"endpoint:health:show-details: alwayseureka:client:serviceUrl:defaultZone: http://localhost:15001/eureka,http://localhost:15002/eureka

这里就可以直接将feign-client替换成yml,http://localhost:25200/yml/sayHi

4、配置文件配置

package com.xl.gateway;import com.xl.gateway.resop.ErrorFilter;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
import org.springframework.cloud.gateway.filter.ratelimit.KeyResolver;
import org.springframework.cloud.gateway.filter.ratelimit.RedisRateLimiter;
import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpMethod;
import org.springframework.http.converter.HttpMessageConverter;
import reactor.core.publisher.Mono;import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.stream.Collectors;@Configuration
public class GatewayConfiguration {@Autowiredprivate GatewayFilterIn gatewayFilterIn;@Autowiredprivate AuthFilter authFilter;@Autowiredprivate ErrorFilter errorFilter;@Bean@ConditionalOnMissingBeanpublic HttpMessageConverters messageConverters(ObjectProvider<HttpMessageConverter<?>> converters) {return new HttpMessageConverters(converters.orderedStream().collect(Collectors.toList()));}@Bean@Orderpublic RouteLocator routeLocator(RouteLocatorBuilder builder) {return builder.routes().route(r -> {return r.path("/java/**").and().method(HttpMethod.GET).and().header("name").filters(f -> {return f.stripPrefix(1).addResponseHeader("der", "wer").filter(errorFilter).filter(authFilter)// 限流规则.requestRateLimiter(config -> config.setKeyResolver(this.remoteAddrKeyResolver()).setRateLimiter(this.redisRateLimiter()));}).uri("lb://FEIGN-CLIENT");}).route(r -> {return r.path("/seckill/**").and().between(time("2025-01-15 17:30:00"), time("2025-01-15 17:35:00")).filters(f -> {return f.stripPrefix(1);}).uri("lb://FEIGN-CLIENT");}).build();}// 时间处理public static ZonedDateTime time(String dateTimeStr) {// 定义日期时间格式DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");// 解析字符串为 LocalDateTimeLocalDateTime localDateTime = LocalDateTime.parse(dateTimeStr, formatter);// 转换为 ZonedDateTimereturn ZonedDateTime.of(localDateTime, ZoneId.of("UTC"));}// 限流配置@Beanpublic KeyResolver remoteAddrKeyResolver() {return exchange -> Mono.just(exchange.getRequest().getRemoteAddress().getHostName());}// 限流规则@Beanpublic RedisRateLimiter redisRateLimiter() {// 这里可以设置 RedisRateLimiter 的参数,如 replenishRate、burstCapacity 和 requestedTokensreturn new RedisRateLimiter(1, 1, 1);}
}

这里其实和配置文件大差不差

JWT使用

1、pom

      <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><dependency><groupId>com.auth0</groupId><artifactId>java-jwt</artifactId><version>3.8.1</version></dependency>

2、程序

package com.xl.auth;import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;import java.util.Date;@Slf4j
@Service
public class JwtService {private static final String KEY = "xl";private static final String ISSUE = "ligang";private static final Long EXPIRE_TIME = 60000L;private static final String USER_NAME = "username";public String token(Account account) {Algorithm algorithm = Algorithm.HMAC256(KEY);Date date = new Date();String sign = JWT.create().withIssuer(ISSUE).withIssuedAt(date).withExpiresAt(new Date(date.getTime() + EXPIRE_TIME)).withClaim(USER_NAME, account.getUsername()).sign(algorithm);log.info("jwt generated user:{}", account.getUsername());return sign;}public Boolean verify(String token, String username) {log.info("verifying jwt - username:{}", username);try {Algorithm algorithm = Algorithm.HMAC256(KEY);JWTVerifier verifier = JWT.require(algorithm).withIssuer(ISSUE).withClaim(USER_NAME, username).build();verifier.verify(token);return true;} catch (Exception e) {log.error("auth failed", e);return false;}}}

后面自己对应的接口,比如登录获取token,验证token,续约token等

gatewayJWTtoken_270">gateway添加规则使用JWT验证token

package com.xl.gateway;import com.xl.auth.AuthResponse;
import com.xl.auth.AuthService;
import com.xl.auth.ErrorCode;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpHeaders;
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.StopWatch;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;@Slf4j
@Component("authFilter")
public class AuthFilter implements GatewayFilter, Ordered {private static final String AUTH = "Aothorzation";private static final String USERNAME = "user-name";@Autowiredprivate AuthService authService;@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {log.info("Auth start");ServerHttpRequest request = exchange.getRequest();HttpHeaders header = request.getHeaders();String token = header.getFirst(AUTH);String username = header.getFirst(USERNAME);ServerHttpResponse response = exchange.getResponse();if (StringUtils.isBlank(token)) {log.error("token not found");response.setStatusCode(HttpStatus.UNAUTHORIZED);return response.setComplete();}AuthResponse resp = authService.verify(token, username);if (resp.getCode() != 1L) {log.error("invalid token");response.setStatusCode(HttpStatus.FORBIDDEN);return response.setComplete();}ServerHttpRequest.Builder mutate = request.mutate();mutate.header("user-name", username);ServerHttpRequest build = mutate.build();response.setStatusCode(HttpStatus.OK);response.getHeaders().add("user-name", username);return chain.filter(exchange.mutate().request(build).response(response).build());}@Overridepublic int getOrder() {return 0;}
}

还有很多规则,看官方文档或者看代码源码研究,就摸索出来了,还是很有用的


http://www.ppmy.cn/devtools/152792.html

相关文章

服务化架构 IM 系统之应用 MQ

在微服务化系统中&#xff0c;存在三个最核心的组件&#xff0c;分别是 RPC、注册中心和MQ。 在前面的两篇文章&#xff08;见《服务化架构 IM 系统之应用 RPC》和《服务化架构 IM 系统之应用注册中心》&#xff09;中&#xff0c;我们站在应用的视角分析了普适性的 RPC 和 注…

android studio本地打包后,无法热更,无法执行换包操作,plus.runtime.install没有弹窗

要解决这个问题我们首先要按顺序排查 1.检查安装代码是否正常&#xff0c;下面是一个热更安装进度页面的demo&#xff0c;可以参照一下 <template><view><view class"progress-box"><progress :percent"progress" show-info stroke…

Spring注解篇:@GetMapping详解

全文目录&#xff1a; 开篇语前言摘要概述源码解析使用案例分享应用场景案例优缺点分析核心类方法介绍测试用例测试用例分析使用场景优缺点分析测试用例 小结总结文末 开篇语 哈喽&#xff0c;各位小伙伴们&#xff0c;你们好呀&#xff0c;我是喵手。运营社区&#xff1a;C站/…

Linux -- HTTP 请求 与 响应 报文

目录 请求报文&#xff1a; 请求方法 响应报文&#xff1a; 状态码 与 状态码描述 共性 常见的报头 请求报文&#xff1a; 请求方法 方法说明GET获取资源POST传输实体主体PUT传输文件HEAD获得报文首部DELETE删除文件OPTIONS询问支持的方法TRACE追踪路径CONNECT要求用…

庄小焱——2024年博文总结与展望

摘要 大家好&#xff0c;我是庄小焱。岁末回首&#xff0c;2024 年是我在个人成长、博客创作以及生活平衡方面收获颇丰的一年。这一年的经历如同璀璨星辰&#xff0c;照亮了我前行的道路&#xff0c;也为未来的发展奠定了坚实基础。 1. 个人成长与突破 在 2024 年&#xff0c…

吴恩达深度学习——神经网络介绍

文章内容来自BV11H4y1F7uH&#xff0c;仅为个人学习所用。 文章目录 什么是神经网络引入神经网络神经元激活函数ReLU隐藏单元 用神经网络进行监督学习监督学习与无监督学习举例 什么是神经网络 引入 已经有六个房子的数据集&#xff0c;横轴为房子大小&#xff0c;纵轴为房子…

Linux(Centos 7.6)命令详解:iconv

1.命令作用 将给定文件的编码从一种编码转换为另一种编码(Convert encoding of given files from one encoding to another) 2.命令语法 Usage: iconv [OPTION...] [FILE...] 3.参数详解 OPTION: 输入/输出格式规范: -f, --from-codeNAME&#xff0c;原始文本编码-t, --t…

Linux Bash 中使用重定向运算符的 5 种方法

注&#xff1a;机翻&#xff0c;未校。 Five ways to use redirect operators in Bash Posted: January 22, 2021 | by Damon Garn Redirect operators are a basic but essential part of working at the Bash command line. See how to safely redirect input and output t…