SpringBoot集成Swagger2登录功能和安全认证

本篇文章要实现的功能:

  • 1.集成swagger
  • 2.集成swagger登录功能,访问 /swagger-ui.html需要先登录
  • 3.集成安全认证,访问接口时携带header

在这里插入图片描述


请求接口时携带了上一步输入的header参数和值
在这里插入图片描述

1.集成swagger

jdk11,SpringBoot 2.7.13
pom.xml依赖swagger2.10.5

<dependency>
	<groupId>io.springfox</groupId>
	<artifactId>springfox-swagger2</artifactId>
	<version>2.10.5</version>
</dependency>
<dependency>
	<groupId>io.springfox</groupId>
	<artifactId>springfox-swagger-ui</artifactId>
	<version>2.10.5</version>
</dependency>
<dependency>
	<groupId>io.springfox</groupId>
	<artifactId>springfox-spring-webmvc</artifactId>
	<version>2.10.5</version>
</dependency>

application.yml

swagger:
  enable: true   #是否开启swagger
  basic:
    enable: true  #是否开启登录认证
    username: admin
    password: admin
2.集成swagger登录功能,访问 /swagger-ui.html需要先登录

新建 Swagger2Config

import com.zypcy.mono.interceptor.SwaggerInterceptor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.handler.MappedInterceptor;
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.*;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.service.contexts.SecurityContext;
import springfox.documentation.spring.web.plugins.Docket;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import springfox.documentation.swagger2.annotations.EnableSwagger2WebMvc;

import java.util.ArrayList;
import java.util.List;

@Configuration
@EnableWebMvc
@EnableSwagger2WebMvc
@ConditionalOnProperty(
        name = {"swagger.enable"},
        havingValue = "true",
        matchIfMissing = false
)
public class Swagger2Config implements WebMvcConfigurer {

    @Value("${spring.profiles.active}")
    private String active;
    @Value("${swagger.basic.username:admin}")
    private String username;
    @Value("${swagger.basic.password:admin}")
    private String password;

    private String basePackage = "com.zypcy.mono.controller";

    /**
     * 开放swagger-ui.html资源
     * @param registry
     */
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/**").addResourceLocations("classpath:/static/");
        registry.addResourceHandler("swagger-ui.html").addResourceLocations("classpath:/META-INF/resources/");
        registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
        WebMvcConfigurer.super.addResourceHandlers(registry);
    }

    /* 在此处配置拦截器,要不然拦不到swagger的静态资源 */
    @Bean
    @ConditionalOnProperty(name = "swagger.basic.enable", havingValue = "true")
    public MappedInterceptor getMappedInterceptor() {
        return new MappedInterceptor(new String[]{"/swagger-ui.html", "/v2/api-docs", "/webjars/**"}, new SwaggerInterceptor(username, password));
    }

    @Bean
    public Docket createRestApi() {
        return new Docket(DocumentationType.SWAGGER_2)
                .enable(!"prod".equals(active))
                .apiInfo(apiInfo())
                .select()
                .apis(RequestHandlerSelectors.basePackage(basePackage))
                .paths(PathSelectors.any())
                .build()
                .securitySchemes(securitySchemes())
                .securityContexts(securityContexts());
    }


    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
                .title("Mono API 接口文档")
                .description("Mono REST API 接口文档")
                .termsOfServiceUrl("")
                .contact(new Contact("zhuyu", "https://zhuyu.blog.csdn.net", "645906265@qq.com"))
                .license("Mono License Version 2.0")
                .licenseUrl("http://www.xxx.xxx/licenses/LICENSE-2.0")
                .version("1.0")
                .build();
    }

    //3.集成安全认证,访问接口时携带header
    private List<SecurityScheme> securitySchemes() {
        List<SecurityScheme> res = new ArrayList<>();
        res.add(new ApiKey("AppId", "AppId", "header"));
        res.add(new ApiKey("Authorization", "Authorization", "header"));
        return res;
    }

    private List<SecurityContext> securityContexts() {
        List<SecurityContext> res = new ArrayList<>();
        res.add(SecurityContext.builder()
                .securityReferences(defaultAuth())
                .forPaths(PathSelectors.regex("/.*"))
                .build());
        return res;
    }

    private List<SecurityReference> defaultAuth() {
        List<SecurityReference> res = new ArrayList<>();
        AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything");
        AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
        authorizationScopes[0] = authorizationScope;
        res.add(new SecurityReference("AppId", authorizationScopes));
        res.add(new SecurityReference("Authorization", authorizationScopes));
        return res;
    }

    /**
     * 添加header,调用代码:this.header("x-request-info", "string", false, "appId=101;token=a256f4c4f38a76115355d2d039e2882e;")
     * @param name
     * @param type
     * @param required
     * @param defaultValue
     * @return
     */
    private Parameter header(String name, String type, boolean required, String defaultValue) {
        ParameterBuilder param = new ParameterBuilder();
        return param.name(name).modelRef(new ModelRef(type)).parameterType("header").defaultValue(defaultValue).required(required).build();
    }

}

创建拦截器 SwaggerInterceptor

import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Base64;

/**
 * @Description:
 * @Author: zhuyu
 * @Date: 2023/11/22 20:44
 */
public class SwaggerInterceptor implements HandlerInterceptor {
    private String username;
    private String password;
    public SwaggerInterceptor(String username, String password) {
        this.username = username;
        this.password = password;
    }

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String authorization = request.getHeader("Authorization");
        boolean isAuthSuccess = httpBasicAuth(authorization);
        if (!isAuthSuccess) {
            response.setCharacterEncoding("utf-8");
            response.setStatus(401);
            response.setHeader("WWW-authenticate", "Basic realm=\"Realm\"");
            try (PrintWriter writer = response.getWriter()) {
                writer.print("Forbidden, unauthorized user");
            }
        }
        return isAuthSuccess;
    }
    public boolean httpBasicAuth(String authorization) throws IOException {
        if (authorization != null && authorization.split(" ").length == 2) {
            String userAndPass = new String(Base64.getDecoder().decode((authorization.split(" ")[1])));
            String username = userAndPass.split(":").length == 2 ? userAndPass.split(":")[0] : null;
            String password = userAndPass.split(":").length == 2 ? userAndPass.split(":")[1] : null;
            if (this.username.equals(username) && this.password.equals(password)) {
                return true;
            }
        }
        return false;
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        String uri = request.getRequestURI();
        AntPathMatcher pathMatcher = new AntPathMatcher();
        if (!pathMatcher.match("/swagger-ui.html", uri) && !pathMatcher.match("/webjars/**", uri)) {
            response.setStatus(404);
            return;
        }
        ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        Resource[] resources = resolver.getResources("classpath:/META-INF/resources" + uri);
        if (resources != null && resources.length > 0) {
            FileCopyUtils.copy(resources[0].getInputStream(), response.getOutputStream());
        } else {
            response.setStatus(404);
        }
    }
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

pmp敏捷十二个考点!考前必背!

自从PMP更换了新的考纲&#xff0c;考试中对于敏捷项目管理的知识比重越来越大。因此&#xff0c;掌握敏捷知识成为备考的重点。为了帮助大家更好地掌握敏捷知识点&#xff0c;我整理了12个敏捷考点&#xff0c;希望能对大家有所帮助&#xff01; 一、敏捷宣言十二原则改写如下…

学习Opencv(蝴蝶书/C++)——3. OpenCV的数据类型

文章目录 1. 总览2. 基础类型2.0 基础类型总览2.1 cv::Vec<>类2.2 cv::Matx<>类2.3 cv::Point类(cv::Point3_< >和cv::Point_< >)2.4 cv::Scalar(cv::Scalar_)类2.5 cv::Size(cv::Size_)类、cv::Rect(cv::Rect_)类和cv::RotatedRect 类2.6 基础类型…

嵌入式Linux学习(1)——经典CAN介绍(上)

目录 一. CAN与ISO-OSI Model 二. CAN通信 2.1 接线方式 2.1.1 闭环网络 2.1.2 开环网络 2.2 收发流程 2.2.1 发送 2.2.2 接收 三. CAN BUS访问与仲裁 3.1 “线与”机制​ 3.2 仲裁机制 REF CAN&#xff08;Controller Area Network&#xff09;总线协议是由 BOSC…

五大匹配算法

五大匹配算法 五大匹配算法 BF 匹配、RK 匹配、KMP 匹配、BM 匹配、Sunday 匹配。 1、BF 匹配 // BF 匹配&#xff08;暴力匹配&#xff09; public static int bfMatch(String text, String pattern) {char[] t text.toCharArray();char[] p pattern.toCharArray();int i …

关于2023年11月25日PMI认证考试有关事项的通知

PMP项目管理学习专栏https://blog.csdn.net/xmws_it/category_10954848.html?spm1001.2014.3001.54822023年8月PMP考试成绩出炉|微思通过率95%以上-CSDN博客文章浏览阅读135次。国际注册项目管理师(PMP) 证书是项目管理领域含金量最高的职业资格证书&#xff0c;获得该资质是项…

2023亚太杯数学建模思路 - 案例:粒子群算法

文章目录 1 什么是粒子群算法&#xff1f;2 举个例子3 还是一个例子算法流程算法实现建模资料 # 0 赛题思路 &#xff08;赛题出来以后第一时间在CSDN分享&#xff09; https://blog.csdn.net/dc_sinor?typeblog 1 什么是粒子群算法&#xff1f; 粒子群算法&#xff08;Pa…

被Linux之父称其为艺术品的WireGuard

简介 WireGuard 是一种极其简单但快速且现代的 VPN&#xff0c;它利用了最先进的加密技术。它的目标是比 IPsec 更快、更简单、更精简和更有用&#xff0c;同时避免令人头疼的问题。旨在提供比 OpenVPN 更高的性能。WireGuard 被设计为在嵌入式接口和超级计算机等上运行的通用 …

哈夫曼树你需要了解一下

哈夫曼树介绍哈夫曼数特点哈夫曼应用场景哈夫曼构建过程哈夫曼树示例拓展 哈夫曼树介绍 哈夫曼树&#xff08;Huffman Tree&#xff09;是一种特殊的二叉树&#xff0c;也被称为最优二叉树。在计算机科学中&#xff0c;它是由权值作为叶子节点构造出来的一种二叉树。哈夫曼树的…

【UE】用样条线实现测距功能(上)

目录 效果 步骤 一、创建样条网格体组件3D模型 二、实现点击连线功能 三、实现显示两点间距离功能 效果 步骤 一、创建样条网格体组件3D模型 创建一个圆柱模型&#xff0c;这里底面半径设置为10mm&#xff0c;高度设置为1000mm 注意该模型的坐标轴在如下位置&#xff1…

集团投融资大数据平台解决方案

一、项目背景 项目为集团型公司大数据平台项目&#xff0c;整个项目周期约为6个月&#xff0c;整体呈现了对外的数据大屏驾驶仓和对内的看板报表&#xff0c;减少了客户内部数据上报和报表制作的重复工作量&#xff0c;为集团数据决策奠定基础。 二、项目目标 战略层&#xff…

c++ std::variant用法

std::variant Union类型的问题&#xff1a; 无法知道当前使用的类型是什么union无法自动调用底层数据成员的析构函数。联合体无法对其内部的数据属性的生命周期的全面支持&#xff0c;因为当外部代码调用Union时在切换类型&#xff0c;它无法做到对当前使用的对象&#xff0c…

Java(五)(Object类,克隆,Objects类,包装类,StringBuilder,StringJoiner,BigDecimal)

目录 Object类 Object类的常见方法: 克隆 浅克隆 深克隆 Objects类 包装类 StringBuilder StringJoiner BigDecimal Object类 Object类是java中的祖宗类,因此,Java中所有的类的对象都可以直接使用object类提供的一些方法 Object类的常见方法: public String toStrin…

【黑马甄选离线数仓day01_项目介绍与环境准备】

1. 行业背景 1.1 电商发展历史 电商1.0: 初创阶段20世纪90年代&#xff0c;电商行业刚刚兴起&#xff0c;主要以B2C模式为主&#xff0c;如亚马逊、eBay等 ​ 电商2.0: 发展阶段21世纪初&#xff0c;电商行业进入了快速发展阶段&#xff0c;出现了淘宝、京东等大型电商平台&a…

Halcon Solution Guide I basics(3): Region Of Interest(有兴趣区域/找重点)

文章目录 文章专栏前言文章解读前言创建ROI案例1&#xff1a;直接截取ROI手动截取ROI 总结ROI套路获取窗口句柄截取ROI区域获取有效区域 Stop组合 文章专栏 Halcon开发 Halcon学习 练习项目gitee仓库 CSDN Major 博主Halcon文章推荐 前言 今天来看第三章内容&#xff0c;既然是…

忘记7-zip密码,如何解压文件?

7z压缩包设置了密码&#xff0c;解压的时候就需要输入正确对密码才能顺利解压出文件&#xff0c;正常当我们解压文件或者删除密码的时候&#xff0c;虽然方法多&#xff0c;但是都需要输入正确的密码才能完成。忘记密码就无法进行操作。 那么&#xff0c;忘记了7z压缩包的密码…

代码规范之-理解ESLint、Prettier、EditorConfig

前言 团队多人协同开发项目&#xff0c;困扰团队管理的一个很大的问题就是&#xff1a;无可避免地会出现每个开发者编码习惯不同、代码风格迥异&#xff0c;为了代码高可用、可维护性&#xff0c;需要从项目管理上尽量统一和规范代码。理想的方式需要在项目工程化方面&#xff…

力扣:175. 组合两个表(Python3)

题目&#xff1a; 表: Person ---------------------- | 列名 | 类型 | ---------------------- | PersonId | int | | FirstName | varchar | | LastName | varchar | ---------------------- personId 是该表的主键&#xff08;具有唯一值的列&#…

设计循环队列,解决假溢出问题

什么是假溢出&#xff1f; 当我们使用队列这种基本的数据结构时&#xff0c;很容易发现&#xff0c;随着入队和出队操作的不断进行&#xff0c;队列的数据区域不断地偏向队尾方向移动。当我们的队尾指针指向了队列之外的区域时&#xff0c;我们就不能再进行入队操作了&#xff…

【shell】循环语句(for、while、until)

目录 一、循环语句的特点 二、三种常用的循环 2.1 for循环 2.2 while循环 2.3 until循环 2.4 死循环 2.5 关于continue和break以及exit 三、实操案例 3.1 累加1到100&#xff08;5种办法&#xff0c;穿插多种运算习惯&#xff09; 3.2 批量修改文件名称 3.3 pi…

yapi==使用依赖包里的类作为入参/返回值导出后没有备注

比如模块A中有个MyDemoEntity类,在B中以依赖的形式引入了A,并在B的接口中以MyDemoEntity作为返回值,导出到YAPI发现MyDemoEntity的备注没了。 解决: 将A的内容安装到本地MAVEN仓库,并且需要将源码也一起安装 <build><resources><resource><director…