swagger在微服务下的实战应用(微服务整合token认证规范化入参)

Posted 张子行的博客

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了swagger在微服务下的实战应用(微服务整合token认证规范化入参)相关的知识,希望对你有一定的参考价值。

本文目录

前言

6月19入的职到现在的7月27号,没错我已经实习了1个多月了,emmm怎么来说呢,拿我在学校敲代码的状态来比喻吧,如果把我在学校敲的代码比喻成一匹矫健驰骋在草原的黑马,那么我在公司敲的代码就更像是正规军,驰骋在赛场的汗血宝马了。

个人所感

以前在学校没怎么重视网络编程这块,即使以前有看过springCloud、duuble相关的视频,但是当时看视频的时候觉着这样开发项目太繁琐了,也没有坚持去系统化的去总结这一块的内容。以前我也刷到过牛客网上那些牛逼简历上写的项目是手写RPC框架、基于scoket开发的实时在线聊天系统相关的项目,当时觉着这些技术简直可以用俩个字“牛逼”来形容。当时本人痴迷于一个集合类、spring框架的源码分析就没有太注意这一块的技术。但是现在在公司开发的是一个微服务项目,核心业务都是涉及到网络编程相关的,迫于压力也是对于技术的一种热爱,于是我现在研究起了微服务相关框架的使用、源码、scoket、netty、dubbo、springCloud这些技术了,后续会陆续更新相关文章。

模块间依赖关系

email:依赖payment模块
gateway:网关负责路由相关到对应的实例(注册中心用的nacos)
payment:单独的模块

email、payment模块添加swagger依赖支持

 <dependency>
        <groupId>io.springfox</groupId>
        <artifactId>springfox-swagger2</artifactId>
        <version>2.9.2</version>
    </dependency>
    <dependency>
        <groupId>io.swagger</groupId>
        <artifactId>swagger-annotations</artifactId>
        <version>1.5.20</version>
    </dependency>
    <dependency>
        <groupId>io.springfox</groupId>
        <artifactId>springfox-swagger-ui</artifactId>
        <version>2.9.2</version>
    </dependency>

email、payment模块开启swagger模块配置

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.web.context.request.async.DeferredResult;
import springfox.bean.validators.configuration.BeanValidatorPluginsConfiguration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.ResponseMessageBuilder;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.ResponseMessage;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

import java.util.Arrays;

@Configuration
@EnableSwagger2
@Import(BeanValidatorPluginsConfiguration.class)
public class Swagger2Config 

	@Bean
	public Docket customDocket() 
		return new Docket(DocumentationType.SWAGGER_2)
				.genericModelSubstitutes(DeferredResult.class)
				.useDefaultResponseMessages(false)
				.forCodeGeneration(false)
				.pathMapping("/")
				.apiInfo(apiInfo())
				.select()
				.build();
	

	private ApiInfo apiInfo() 
		return new ApiInfoBuilder()
				.title("接口文档title")
				.description("接口文档说明")
				.version("1.0.0")
				.build();
	

网关模块配置(重点)

添加swagger接口支撑

/**
 * zzh
 */
@RestController
class SwaggerHandler 
    @Autowired(required = false)
    private SecurityConfiguration securityConfiguration;
    @Autowired(required = false)
    private UiConfiguration uiConfiguration;
    private final SwaggerResourcesProvider swaggerResources;

    @Autowired
    public SwaggerHandler(SwaggerResourcesProvider swaggerResources) 
        this.swaggerResources = swaggerResources;
    


    @GetMapping("/swagger-resources/configuration/security")
    public Mono<ResponseEntity<SecurityConfiguration>> securityConfiguration() 
        return Mono.just(new ResponseEntity<>(
                Optional.ofNullable(securityConfiguration).orElse(SecurityConfigurationBuilder.builder().build()), HttpStatus.OK));
    

    @GetMapping("/swagger-resources/configuration/ui")
    public Mono<ResponseEntity<UiConfiguration>> uiConfiguration() 
        return Mono.just(new ResponseEntity<>(
                Optional.ofNullable(uiConfiguration).orElse(UiConfigurationBuilder.builder().build()), HttpStatus.OK));
    

    @GetMapping("/swagger-resources")
    public Mono<ResponseEntity> swaggerResources() 
        return Mono.just((new ResponseEntity<>(swaggerResources.get(), HttpStatus.OK)));
    

    @GetMapping("/")
    public Mono<ResponseEntity> swaggerResourcesN() 
        return Mono.just((new ResponseEntity<>(swaggerResources.get(), HttpStatus.OK)));
    

    @GetMapping("/csrf")
    public Mono<ResponseEntity> swaggerResourcesCsrf() 
        return Mono.just((new ResponseEntity<>(swaggerResources.get(), HttpStatus.OK)));
    


对swagger请求进行过滤(可有可无)

/**
 * zzh
 */
@Component
public class SwaggerHeaderFilter extends AbstractGatewayFilterFactory 
 
    private static final String HEADER_NAME = "X-Forwarded-Prefix";

    @Override
    public GatewayFilter apply(Object config) 
        return (exchange, chain) -> 
            ServerHttpRequest request = exchange.getRequest();
            String path = request.getURI().getPath();
            if (!StringUtils.endsWithIgnoreCase(path, SwaggerProvider.API_URI)) 
                return chain.filter(exchange);
            
            String basePath = path.substring(0, path.lastIndexOf(SwaggerProvider.API_URI));
            ServerHttpRequest newRequest = request.mutate().header(HEADER_NAME, basePath).build();
            ServerWebExchange newExchange = exchange.mutate().request(newRequest).build();
            return chain.filter(newExchange);
 
        ;
 
    

全局swagger配置(放在网关模块)

/**
 * 全局swagger配置
 */
@Component
@Primary
@AllArgsConstructor
public class SwaggerProvider implements SwaggerResourcesProvider 
    //注意这个地址
    public static final String API_URI = "/v2/api-docs?urls.primaryName";
    private final RouteLocator routeLocator;
    private final GatewayProperties gatewayProperties;

    /**
     * swagger会与返回值中的SwaggerResource进行路径匹配,如果匹配不到那么会出现swagger页面404无法访问的情况
     *
     * @return
     */
    @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")
                                //swagger API地址
                                .replace("/**", API_URI + routeDefinition.getId())))));
        return resources;
    

    private SwaggerResource swaggerResource(String name, String location) 
        SwaggerResource swaggerResource = new SwaggerResource();
        swaggerResource.setName(name);
        swaggerResource.setLocation(location);
        swaggerResource.setSwaggerVersion("2.0");
        return swaggerResource;
    

网关路由配置

server:
  port: 8005
spring:
  application:
    name: gateway
  cloud:
    discovery:
      locator:
        enabled: true
    gateway:
      routes:
        - id: email_id
          uri: lb://email
          predicates:
            - Path=/email/**
          filters:
            - name: SwaggerHeaderFilter
            - StripPrefix=1
        - id: payment_id
          uri: lb://payment
          predicates:
            - Path=/payment/**
          filters:
            - name: SwaggerHeaderFilter
            - StripPrefix=1
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848
      config:
        server-addr: 127.0.0.1:8848
mybatis-plus:
  mapper-locations: classpath:mapperXml/*.xml

全局token验证、方式一

在swagger配置文件中加入如下配置,每次请求都会把 name为 X-Auth-Token 的参数放入请求中进行请求

/**
 * 对每个接口都添加token认证
 *
 * @return
 */
private List<Parameter> setHeaderToken() 
    ParameterBuilder tokenPar = new ParameterBuilder();
    List<Parameter> pars = new ArrayList<>();
    tokenPar.name("X-Auth-Token").description("token").modelRef(new ModelRef("string")).parameterType("header").required(false).build();
    pars.add(tokenPar.build());
    return pars;

加入swagger配置

全局token验证、方式二

一次添加模块下的所有接口下次请求都会携带 token


    @Bean
    public Docket customDocket() 
        // 配置全局参数返回状态
        java.util.List<ResponseMessage> resMsgList = Arrays.asList(
                new ResponseMessageBuilder().code(200).message("成功!").build(),
                new ResponseMessageBuilder().code(-1).message("失败!").build(),
                new ResponseMessageBuilder().code(401).message("参数校验错误!").build(),
                new ResponseMessageBuilder().code(403).message("没有权限操作,请后台添加相应权限!").build(),
                new ResponseMessageBuilder().code(500).message("服务器内部异常,请稍后重试!").build(),
                new ResponseMessageBuilder().code(501).message("请登录!").build());
        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo()).select()
                .apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
                .paths(PathSelectors.any())
                .build()
                .globalResponseMessage(RequestMethod.GET, resMsgList)
                .globalResponseMessage(RequestMethod.POST, resMsgList)
                .globalResponseMessage(RequestMethod.PUT, resMsgList)
                .globalResponseMessage(RequestMethod.DELETE, resMsgList)
                .globalOperationParameters(setHeaderToken())
                .securityContexts(securityContexts());
    
	/**
     * 以下代码添加全局token配置
     *
     * @return
     */
    private List<ApiKey> security() 
        ArrayList list = new ArrayList();
        list.add(new ApiKey("Authorization", "Authorization", "header"));
        return list;
    

    private List<SecurityContext> securityContexts() 
        List<SecurityContext> securityContexts = new ArrayList<>();
        securityContexts.add(
                SecurityContext.builder()
                        .securityReferences(defaultAuth())
                        .forPaths(PathSelectors.regex("^(?!auth).*$"))
                        .build());
        return securityContexts;
    

    private List<SecurityReference> defaultAuth() 
        AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything");
        Authorizati

以上是关于swagger在微服务下的实战应用(微服务整合token认证规范化入参)的主要内容,如果未能解决你的问题,请参考以下文章

SpringCloud分布式事务实战在微服务1中创建整合函数,调用微服务2

SpringBoot系列十一:SpringBoot整合Restful架构(使用 RestTemplate 模版实现 Rest 服务调用Swagger 集成动态修改日志级别)

微服务架构实战学习:整合Hystrix的两种方式

springcloud+gateway微服务整合swagger

Spring Cloud Zuul集成Swagger

今日头条技术专家:RocketMQ 在微服务架构下的应用实践