springcloud+gateway微服务整合swagger
单一的微服务集成swagger:
maven:
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
</dependency>
package fwz.cpjiang.ums.utils; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.ParameterBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.schema.ModelRef;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Parameter;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2; import java.util.ArrayList;
import java.util.List; @Configuration
@EnableSwagger2
public class SwaggerConfig { @Bean
public Docket createRestApi(){
ParameterBuilder tokenPar = new ParameterBuilder(); List<Parameter> pars = new ArrayList<Parameter>();
tokenPar.name("token").description("令牌").modelRef(new ModelRef("string")).parameterType("header").required(false).build();
pars.add(tokenPar.build());
return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.any())
.paths(PathSelectors.any()).build().globalOperationParameters(pars);
} private ApiInfo apiInfo(){
return new ApiInfoBuilder()
.title("用户管理 API Doc")
.description("This is a restful api document of 用户管理.")
.version("1.0")
.build();
} }
此时swagger只是存在于单一的微服务,很不方便
gateway整合swagger:
所有的微服务均按上述配置swagger
然后在gateway微服务中,添加如下配置:
package fwz.cpjiang.gateway.utils; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.swagger.web.SecurityConfiguration;
import springfox.documentation.swagger.web.SecurityConfigurationBuilder;
import springfox.documentation.swagger.web.UiConfiguration;
import springfox.documentation.swagger.web.UiConfigurationBuilder; @Configuration
public class SwaggerConfig { @Bean
public SecurityConfiguration securityConfiguration() {
return SecurityConfigurationBuilder.builder().build();
} @Bean
public UiConfiguration uiConfiguration() {
return UiConfigurationBuilder.builder().build();
} }
package fwz.cpjiang.gateway.utils; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Mono;
import springfox.documentation.swagger.web.*; import java.util.List;
import java.util.Optional; @RestController
@RequestMapping("/swagger-resources")
public class SwaggerHandler { private final SecurityConfiguration securityConfiguration;
private final UiConfiguration uiConfiguration;
private final SwaggerResourcesProvider swaggerResources; @Autowired
public SwaggerHandler(SwaggerResourcesProvider swaggerResources, SecurityConfiguration securityConfiguration, UiConfiguration uiConfiguration) {
this.swaggerResources = swaggerResources;
this.securityConfiguration = securityConfiguration;
this.uiConfiguration = uiConfiguration;
} @GetMapping("/configuration/security")
public Mono<ResponseEntity<SecurityConfiguration>> securityConfiguration() {
return Mono.just(new ResponseEntity<>(
Optional.ofNullable(securityConfiguration).orElse(SecurityConfigurationBuilder.builder().build()),
HttpStatus.OK));
} @GetMapping("/configuration/ui")
public Mono<ResponseEntity<UiConfiguration>> uiConfiguration() {
return Mono.just(new ResponseEntity<>(
Optional.ofNullable(uiConfiguration).orElse(UiConfigurationBuilder.builder().build()), HttpStatus.OK));
} @GetMapping
public Mono<ResponseEntity<List<SwaggerResource>>> swaggerResources() {
return Mono.just((new ResponseEntity<>(swaggerResources.get(), HttpStatus.OK)));
} }
package fwz.cpjiang.gateway.utils; import lombok.AllArgsConstructor;
import org.springframework.cloud.gateway.config.GatewayProperties;
import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.cloud.gateway.support.NameUtils;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Component;
import springfox.documentation.swagger.web.SwaggerResource;
import springfox.documentation.swagger.web.SwaggerResourcesProvider; import java.util.ArrayList;
import java.util.List; @Primary
@Component
@AllArgsConstructor
public class SwaggerProvider implements SwaggerResourcesProvider { public static final String API_URI = "/v2/api-docs";
private final RouteLocator routeLocator;
private final GatewayProperties gatewayProperties; @Override
public List<SwaggerResource> get() {
List<SwaggerResource> resources = new ArrayList<>();
List<String> routes = new ArrayList<>();
routeLocator.getRoutes().subscribe(route -> routes.add(route.getId()));
gatewayProperties.getRoutes().stream()
.filter(routeDefinition -> routes.contains(routeDefinition.getId()))
.forEach(routeDefinition -> routeDefinition.getPredicates().stream()
.filter(predicateDefinition -> ("Path").equalsIgnoreCase(predicateDefinition.getName()))
.forEach(predicateDefinition -> resources
.add(swaggerResource(routeDefinition.getId(), predicateDefinition.getArgs()
.get(NameUtils.GENERATED_NAME_PREFIX + "0").replace("/**", API_URI)))));
return resources;
} private SwaggerResource swaggerResource(String name, String url) {
SwaggerResource swaggerResource = new SwaggerResource();
swaggerResource.setName(name);
swaggerResource.setUrl(url);
swaggerResource.setSwaggerVersion("2.0");
return swaggerResource;
}
}
package fwz.cpjiang.gateway.utils; import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration; import java.util.List; @Configuration
@ConfigurationProperties(prefix = "system")
public class UrlConfig {
// 配置文件使用list接收
private List<String> whiteList; public List<String> getWhiteList() {
return whiteList;
}
public void setWhiteList(List<String> whiteList) {
this.whiteList = whiteList;
}
}
yml配置文件:
system:
whiteList:
- "/swagger-ui.html"
- "/swagger-resources/**"
- "/v2/api-docs"
- "/admin/login"
routes:
- id: hbistc-ums
uri: lb://hbistc-ums
predicates:
- Path=/ums/**
filters:
- StripPrefix=1
- id: hbistc-mall
uri: lb://hbistc-mall
predicates:
- Path=/mall/**
filters:
- StripPrefix=1
package fwz.cpjiang.gateway.utils; import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm; import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;
import java.util.Date;
import java.util.UUID; /**
* JWT工具类
*/
public class JwtUtils { //有效期为
public static final Long JWT_TTL = 3600000L;// 60 * 60 *1000 一个小时
//设置秘钥明文
public static final String JWT_KEY = "joijgisdlwejjjfeawoGdeizeffsaz"; /**
* 创建token
*
* @param id
* @param subject
* @param ttlMillis
* @return
*/
public static String createJWT(String id, String subject, Long ttlMillis) { SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
long nowMillis = System.currentTimeMillis();
Date now = new Date(nowMillis);
if (ttlMillis == null) {
ttlMillis = JwtUtils.JWT_TTL;
}
long expMillis = nowMillis + ttlMillis;
Date expDate = new Date(expMillis);
SecretKey secretKey = generalKey(); JwtBuilder builder = Jwts.builder()
.setId(id) //唯一的ID
.setSubject(subject) // 主题 可以是JSON数据
.setIssuer("admin") // 签发者
.setIssuedAt(now) // 签发时间
.signWith(signatureAlgorithm, secretKey) //使用HS256对称加密算法签名, 第二个参数为秘钥
.setExpiration(expDate);// 设置过期时间
return builder.compact();
} /**
* 生成加密后的秘钥 secretKey
*
* @return
*/
public static SecretKey generalKey() {
byte[] encodedKey = Base64.getDecoder().decode(JwtUtils.JWT_KEY);
SecretKey key = new SecretKeySpec(encodedKey, 0, encodedKey.length, "AES");
return key;
} /**
* 解析
*
* @param jwt
* @return
* @throws Exception
*/
public static Claims parseJWT(String jwt) throws Exception {
SecretKey secretKey = generalKey();
return Jwts.parser()
.setSigningKey(secretKey)
.parseClaimsJws(jwt)
.getBody(); } public static void main(String[] args) throws Exception {
String token = createJWT(UUID.randomUUID().toString(), "ggggggg", null);
System.out.println(token);
Claims c = parseJWT(token);
String id = c.getId();
System.out.println(id);
}
}
package fwz.cpjiang.gateway.filter; import cn.hutool.core.util.StrUtil;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import fwz.cpjiang.gateway.utils.JwtUtils;
import fwz.cpjiang.gateway.utils.UrlConfig;
import org.springframework.beans.factory.annotation.Autowired;
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.web.server.ServerWebExchange;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import reactor.netty.ByteBufFlux; import java.util.HashMap;
import java.util.Map; /**
* 鉴权过滤器 验证token
*/ @Component
public class AuthorizeFilter implements GlobalFilter, Ordered {
private static final String AUTHORIZE_TOKEN = "token";
@Autowired
private UrlConfig urlConfig;
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
//1. 获取请求
ServerHttpRequest request = exchange.getRequest();
//2. 则获取响应
ServerHttpResponse response = exchange.getResponse();
//3. 如果是登录请求则放行
for (int i = 0; i <urlConfig.getWhiteList().size() ; i++) {
if (request.getURI().getPath().contains(urlConfig.getWhiteList().get(i))) {
return chain.filter(exchange);
}
} //4. 获取请求头
HttpHeaders headers = request.getHeaders();
//5. 请求头中获取令牌
String token = headers.getFirst(AUTHORIZE_TOKEN); //6. 判断请求头中是否有令牌
if (StrUtil.isEmpty(token)) {
//7. 响应中放入返回的状态吗, 没有权限访问
response.setStatusCode(HttpStatus.UNAUTHORIZED);
//8. 返回
//return response.setComplete();
//设置响应头信息Content-Type类型
response.getHeaders().add("Content-Type","application/json");
//设置返回json数据
return response.writeAndFlushWith(Flux.just(ByteBufFlux.just(response.bufferFactory().wrap(getWrapData())))); } //9. 如果请求头中有令牌则解析令牌
try {
JwtUtils.parseJWT(token);
} catch (Exception e) {
e.printStackTrace();
//10. 解析jwt令牌出错, 说明令牌过期或者伪造等不合法情况出现
response.setStatusCode(HttpStatus.UNAUTHORIZED);
//11. 返回
//设置响应头信息Content-Type类型
response.getHeaders().add("Content-Type","application/json");
//设置返回json数据
return response.writeAndFlushWith(Flux.just(ByteBufFlux.just(response.bufferFactory().wrap(getWrapData())))); }
//12. 放行
return chain.filter(exchange);
} @Override
public int getOrder() {
return 0;
} private byte[] getWrapData() {
Map<String,String> map = new HashMap<>();
map.put("code","1");
map.put("msg","token is empty or illegal");
try {
return new ObjectMapper().writeValueAsString(map).getBytes();
} catch (JsonProcessingException e) {
//
}
return "".getBytes();
}
}
进行白名单过滤
然后访问网关:
可以发现红框内出现了微服务切换的选项,至此整合完毕
springcloud+gateway微服务整合swagger的更多相关文章
- SpringCloud Gateway微服务网关实战与源码分析-上
概述 定义 Spring Cloud Gateway 官网地址 https://spring.io/projects/spring-cloud-gateway/ 最新版本3.1.3 Spring Cl ...
- 用SpringCloud进行微服务架构演进
在<架构师必须要知道的阿里的中台战略与微服务> 中已经阐明选择SpringCloud进行微服务架构实现中台战略,因此下面介绍SpringCloud的一些内容,SpringCloud已经出来 ...
- SpringCloud学习--微服务架构
目录 微服务架构快速指南 SOA Dubbo Spring Cloud Dubbo与SpringCloud对比 微服务(Microservice)架构快速指南 什么是软件架构? 软件架构是一个包含各种 ...
- springCloud搭建微服务集群+Zuul服务器端负载均衡
概述 最近研究了一下springCloud的微服务集群,主要用到了SpringCloud的服务发现和服务器端负载均衡,所有的项目都是用的springboot,可以和springCloud无缝对接. 技 ...
- SpringCloud与微服务Ⅲ --- SpringCloud入门概述
一. 什么是SpringCloud SpringCloud基于SpringBoot提供了一套微服务解决方案,包括服务注册与发现,配置中心,全链路监控,服务网关,负载均衡,熔断器等组件,除了基于NetF ...
- 一个C#开发者学习SpringCloud搭建微服务的心路历程
前言 Spring Cloud很火,很多文章都有介绍如何使用,但对于我这种初学者,我需要从创建项目开始学起,所以这些文章对于我的启蒙,帮助不大,所以只好自己写一篇文章,用于备忘. SpringClou ...
- 基于Spring-Cloud的微服务框架设计
基于Spring-Cloud的微服务框架设计 先进行大的整体的框架整理,然后在针对每一项进行具体的详细介绍
- SpringCloud与微服务系列专栏
一. 前置知识 学习SpringCloud之前需要具备和掌握如下框架和工具的使用:SpringMVC,Spring,Spring Boot,Mybatis,Maven,Git. SpringCloud ...
- springCloud进阶(微服务架构&Eureka)
springCloud进阶(微服务架构&Eureka) 1. 微服务集群 1.1 为什么要集群 为了提供并发量,有时同一个服务提供者可以部署多个(商品服务).这个客户端在调用时要根据一定的负责 ...
随机推荐
- Java常用的几种设计模式
本来想写点spring相关的东西的,想来想去,先写点设计模式的东西吧 什么是设计模式?套用百度百科的话解释吧 设计模式(Design Pattern)是一套被反复使用.多数人知晓的.经过分类的.代码设 ...
- git -remote: Support for password authentication was removed on August 13, 2021
克隆代码时,报错: Support for password authentication was removed on August 13, 2021. Please use a personal ...
- SYCOJ906瑞士轮
题目-瑞士轮 (shiyancang.cn) 模拟题 #include<bits/stdc++.h> using namespace std; const int N=1e5+520; i ...
- 使用idea时jsp中使用out.print();时报错的解决办法
在用Maven创建web项目时 在jsp页面中out.print();老是报错 这边print显示红色出错因为这边使用的是JSP的API并不是Servlet的,但是可以运行,所以我们只要导包就完事其实 ...
- 华为matebook x pro监听耳机电流声
问题 左耳出现电流声,播放声音就电流声,关闭声音10s后才消失 设备 matebook x pro2018 hd206耳机 原因 matebook设计缺陷充电电流声大,毕竟早期type C快充,监听耳 ...
- 针对vue中请求数据对象新添加的属性不能响应式的解决方法
1.需要给对象添加属性时,不能采用传统的obj.属性=值,obj[属性]=值 来添加属性,在vue页面时需要这样使用 this.$set(obj,"propertyName",&q ...
- qt 简单登录界面(一)
widget.h #ifndef WIDGET_H #define WIDGET_H #include <QWidget> #include<QLineEdit> class ...
- 不难懂------react-flux
一.什么是Flux Flux 是一种架构思想,专门解决软件的结构问题.它跟MVC 架构是同一类东西,但是更加简单和清晰. 二.flux的基本概念 (1) .Flux由4部分组成 1.View:视图层 ...
- 负载均衡的比例(权重,ip_hash,轮询)
目录 一:负载均衡的比例 1.轮询 2.权重 3.ip_hash 二:测试轮询 1.测试 2.重启 3.网址测试 三:测试ip_hash 一:负载均衡的比例 1.轮询 # 默认情况下,Nginx负载均 ...
- python if-elif-else 判断
#!/usr/bin/python #coding=utf-8 #好好学习,天天向上 age=12 if age<4: price=0 elif age<18: price=40 elif ...