knife4j 4.1.0(OpenAPI3)实现spring security或shiro权限注解内容显示

news2024/10/3 8:25:32

前两天写了个knife4j(swagger2)实现spring security或shiro权限注解内容显示,主要是使用knife4j 2.0.5来实现权限注解内容显示的扩展。

在Spring Boot 3 中只支持OpenAPI3规范,集成knife4j的stater:knife4j-openapi3-jakarta-spring-boot-starter,同时又想实现以上功能时,则可以实现官方提供的OperationCustomizer接口,从而实现以上功能。

项目使用到哪个权限框架,就用哪个配置就行,能直接使用。

1 Spring Security 注解展示

将Spring Security的PostAuthorizePostFilterPreAuthorizePreFilter的注解信息追加到接口描述中.

import io.swagger.v3.oas.models.Operation;
import org.springdoc.core.customizers.OperationCustomizer;
import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.security.access.prepost.PostAuthorize;
import org.springframework.security.access.prepost.PostFilter;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.access.prepost.PreFilter;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;

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

@Component
public class SecurityOperationCustomizer implements OperationCustomizer {

    @Override
    public Operation customize(Operation operation, HandlerMethod handlerMethod) {
        StringBuilder notesBuilder = new StringBuilder(operation.getDescription() == null ? "" : operation.getDescription());
        getClassAnnotationNote(notesBuilder, handlerMethod);
        getMethodAnnotationNote(notesBuilder, handlerMethod);
        operation.setDescription(notesBuilder.toString());
        return operation;
    }

    private void getClassAnnotationNote(StringBuilder notesBuilder, HandlerMethod handlerMethod) {
        List<String> values = new ArrayList<>();
        PostAuthorize postAuthorize = AnnotatedElementUtils.findMergedAnnotation(handlerMethod.getBeanType(), PostAuthorize.class);
        if (postAuthorize != null) {
            values.add(postAuthorize.value());
        }
        PostFilter postFilter = AnnotatedElementUtils.findMergedAnnotation(handlerMethod.getBeanType(), PostFilter.class);
        if (postFilter != null) {
            values.add(postFilter.value());
        }
        PreAuthorize preAuthorize = AnnotatedElementUtils.findMergedAnnotation(handlerMethod.getBeanType(), PreAuthorize.class);
        if (preAuthorize != null) {
            values.add(preAuthorize.value());
        }
        PreFilter preFilter = AnnotatedElementUtils.findMergedAnnotation(handlerMethod.getBeanType(), PreFilter.class);
        if (preFilter != null) {
            values.add(preFilter.value());
        }
        if (!values.isEmpty()) {
            notesBuilder.append("<p />").append("class: ").append(String.join(",", values));
        }
    }

    private void getMethodAnnotationNote(StringBuilder notesBuilder, HandlerMethod handlerMethod) {
        List<String> values = new ArrayList<>();
        PostAuthorize postAuthorize = handlerMethod.getMethodAnnotation(PostAuthorize.class);
        if (postAuthorize != null) {
            values.add(postAuthorize.value());
        }
        PostFilter postFilter = handlerMethod.getMethodAnnotation(PostFilter.class);
        if (postFilter != null) {
            values.add(postFilter.value());
        }
        PreAuthorize preAuthorize = handlerMethod.getMethodAnnotation(PreAuthorize.class);
        if (preAuthorize != null) {
            values.add(preAuthorize.value());
        }
        PreFilter preFilter = handlerMethod.getMethodAnnotation(PreFilter.class);
        if (preFilter != null) {
            values.add(preFilter.value());
        }
        if (!values.isEmpty()) {
            notesBuilder.append("<p />").append("method: ").append(String.join(",", values));
        }
    }
}

2 Apache Shiro 注解展示

将Apache Shiro的RequiresRolesRequiresPermissions的注解信息追加到接口描述中.

import io.swagger.v3.oas.models.Operation;
import org.apache.shiro.authz.annotation.Logical;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.springdoc.core.customizers.OperationCustomizer;
import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;

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

@Component
public class ShiroOperationCustomizer implements OperationCustomizer {


    private static final String HTML_P = "<p />";
    private static final String PERM = "权限:";
    private static final String ROLE = "角色:";

    @Override
    public Operation customize(Operation operation, HandlerMethod handlerMethod) {
        StringBuilder notesBuilder = new StringBuilder(operation.getDescription() == null ? "" : operation.getDescription());
        getClassAnnotationNote(notesBuilder, handlerMethod);
        getMethodAnnotationNote(notesBuilder, handlerMethod);
        operation.setDescription(notesBuilder.toString());
        return operation;
    }

    private void getClassAnnotationNote(StringBuilder notesBuilder, HandlerMethod handlerMethod) {
        List<String> values = new ArrayList<>();
        RequiresRoles requiresRoles = AnnotatedElementUtils.findMergedAnnotation(handlerMethod.getBeanType(), RequiresRoles.class);
        if (requiresRoles != null) {
            values.add(HTML_P + ROLE + getAnnotationNote(requiresRoles.value(), requiresRoles.logical()));
        }
        RequiresPermissions requiresPermissions = AnnotatedElementUtils.findMergedAnnotation(handlerMethod.getBeanType(), RequiresPermissions.class);
        if (requiresPermissions != null) {
            values.add(HTML_P + PERM + getAnnotationNote(requiresPermissions.value(), requiresPermissions.logical()));
        }
        if (!values.isEmpty()) {
            notesBuilder.append(HTML_P).append("class: ").append(HTML_P).append(String.join("", values));
        }
    }

    private void getMethodAnnotationNote(StringBuilder notesBuilder, HandlerMethod handlerMethod) {
        List<String> values = new ArrayList<>();
        RequiresRoles requiresRoles = handlerMethod.getMethodAnnotation(RequiresRoles.class);
        if (requiresRoles != null) {
            values.add(HTML_P + ROLE + getAnnotationNote(requiresRoles.value(), requiresRoles.logical()));
        }
        RequiresPermissions requiresPermissions = handlerMethod.getMethodAnnotation(RequiresPermissions.class);
        if (requiresPermissions != null) {
            values.add(HTML_P + PERM + getAnnotationNote(requiresPermissions.value(), requiresPermissions.logical()));
        }
        if (!values.isEmpty()) {
            notesBuilder.append(HTML_P).append("method: ").append(HTML_P).append(String.join("", values));
        }
    }

    private String getAnnotationNote(String[] values, Logical logical) {
        if (logical.equals(Logical.AND)) {
            return String.join(" && ", values);
        } else {
            return String.join(" || ", values);
        }
    }
}

3 Controller演示

3.1 spring security

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.security.access.prepost.PostAuthorize;
import org.springframework.security.access.prepost.PostFilter;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.access.prepost.PreFilter;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/swagger")
@Tag(name = "security 注解权限展示")
@PostAuthorize("hasAuthority('class')")
@PostFilter("hasAuthority('class')")
@PreAuthorize("hasAuthority('class')")
@PreFilter("hasAuthority('class')")
public class SecuritySwaggerController {

    @GetMapping("/security")
    @Operation(summary = "security", description = "Spring Security注解追加到接口描述")
    @PostAuthorize("hasAuthority('method')")
    @PostFilter("hasAuthority('method')")
    @PreAuthorize("hasAuthority('method')")
    @PreFilter("hasAuthority('method')")
    public String security() {
        return "hello security";
    }
}

3.2 apache shiro

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.apache.shiro.authz.annotation.Logical;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/swagger")
@Tag(name = "shiro 注解权限展示")
@RequiresRoles(value = {"class:role1","class:role2"})
@RequiresPermissions(value = {"class:prem1","class:perm2"}, logical = Logical.OR)
public class ShiroSwaggerController {

    @GetMapping("/shiro")
    @Operation(summary = "shiro", description = "Apache Shiro注解追加到接口描述")
    @RequiresRoles(value = {"method:role1","method:role2"})
    @RequiresPermissions(value = {"method:prem1","method:perm2"}, logical = Logical.OR)
    public String shiro() {
        return "hello shiro";
    }
}

4 效果展示

在这里插入图片描述
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Deepin 20.08 linux 升级nvidia驱动 黑屏 报错nvrm api mismatch

驱动连接 https://us.download.nvidia.cn/XFree86/Linux-x86_64/535.54.03/NVIDIA-Linux-x86_64-535.54.03.run 安装过程 systemctl set-default multi-user.target reboot 重启到字符界面后 chmod x NVIDIA-Linux-x86_64-535.54.03.run sudo ./NVIDIA-Linux-x86_64-535.5…

C++(11):关联容器

关联容器和顺序容器有着根本的不同&#xff1a;关联容器中的元素是按关键字来保存和访问的。与之相对&#xff0c;顺序容器中的元素是按它们在容器中的位置来顺序保存和访问的。 虽然关联容器的很多行为与顺序容器相同&#xff0c;但其不同之处反映了关键字的作用。 关联容器…

服务器数据中了locked勒索病毒,有关locked勒索病毒的介绍与预防建议

随着网络的普及和科技技术的发展&#xff0c;网络安全问题日益突出。而其中&#xff0c;勒索病毒就是一种常见的网络安全威胁。一旦企业的服务器数据库被勒索病毒攻击&#xff0c;会导致企业内部的重要数据被加密&#xff0c;给工作和生产生活带了极大的困扰。下面就为大家介绍…

Python工具箱系列(三十七)

二进制文件操作&#xff08;上&#xff09; python比较擅长与文本相关的操作。但现实世界中&#xff0c;对于非文本消息的处理也很普遍。例如&#xff1a; ◆通过有线、无线传递传感器获得的测量数据。 ◆卫星通过电磁波发送测量数据。 ◆数据中心的数万台服务器发送当前CP…

Android Studio 配置 DCL 单例脚本

DCL&#xff08;Double-Checked Locking&#xff09;单例是一种用于创建单例对象的设计模式。单例模式是一种创建型模式&#xff0c;用于确保一个类只有一个实例&#xff0c;并提供全局访问点。 DCL单例的核心思想是使用双重检查来保证只有在需要时才对实例进行实例化。它结合…

MIT 6.830 数据库系统 -- Lab One

MIT 6.830 Lab One 项目拉取SimpleDB存储结构一览SimpleDB特性说明Lab One练习一练习二练习三练习四练习五练习六练习七 项目拉取 原项目使用ant进行项目构建&#xff0c;我已经更改为Maven构建&#xff0c;大家直接拉取我改好后的项目即可: https://gitee.com/DaHuYuXiXi/si…

物联网助力鲜花冷链安全——温湿度监控系统

近几年来我国花卉生产的发展尤为迅速&#xff0c;生产面积逐年扩大&#xff0c;产值成倍增长&#xff0c;内销市场越来越旺&#xff0c;出口创汇也有较大幅度上升。 随着人民生活水平的提高和可支配收入的增加&#xff0c;人们对鲜花的需求日益增长&#xff0c;花卉市场的前景…

电子药盒语音芯片ic解决方案WT588F02B-8S,免屏实现精准较时设定

概述&#xff1a;电子药盒是一种具备定时语音提醒服药的贴心智能家居用品&#xff0c;每天的服药时间是预先设定好的&#xff0c;到了设定的时间提醒声音就会响起&#xff0c;服药者因此就可以准时服药。许多需要每天服药的人士&#xff0c;尤其是老年人群体&#xff0c;经常会…

Matlab论文插图绘制模板第105期—带缺口的分组填充箱线图

在之前的文章中&#xff0c;分享了Matlab带缺口的分组箱线图的绘制模板&#xff1a; 进一步&#xff0c;再来分享一下带缺口的分组填充箱线图的绘制模板。 先来看一下成品效果&#xff1a; 特别提示&#xff1a;本期内容『数据代码』已上传资源群中&#xff0c;加群的朋友请自…

算法leetcode|59. 螺旋矩阵 II(rust重拳出击)

文章目录 59. 螺旋矩阵 II&#xff1a;样例 1&#xff1a;样例 2&#xff1a;提示&#xff1a; 分析&#xff1a;题解&#xff1a;rust&#xff1a;go&#xff1a;c&#xff1a;python&#xff1a;java&#xff1a; 59. 螺旋矩阵 II&#xff1a; 给你一个正整数 n &#xff0c…

高速PCB设计中串行/并行信号的仿真与设计技巧

在高速PCB设计中&#xff0c;串行和并行信号的仿真是为了确保信号传输的准确性和完整性&#xff0c;随着系统数据传输速度的提高&#xff0c;准确模拟和优化信号的传输性能对于系统稳定性至关重要&#xff0c;那么你知道在高速PCB设计中&#xff0c;如何针对串行信号和并行信号…

jmeter夸线程组变量引用

通过BeanShell 后置处理程序引用函数&#xff1a; ${__setProperty(newvar,${oldvar},)}如下&#xff1a; 说明&#xff1a;HTTP_1返回结果msg的值为{“code”:200&#xff0c;“msg”:“操作成功”} 1.通过JSON提取器获取到要跨线程组的参数值 2.BeanShell后置处理程序引用…

杂谈:人到中年总得有点兴趣爱好

写在最前面&#xff1a; 前面一段写的是我咋喜欢的铜钱&#xff0c;后面一段是我对学习和转化的一点儿见解&#xff0c;有兴趣可以看看&#xff0c;甚至可以跳过前面去看看后面的内容~ 前几天跟朋友吃饭聊天&#xff0c;不知不觉中大家都到了中年&#xff0c;也都有点儿兴趣爱好…

SAP从入门到放弃系列之工艺路线-物料分配与组件分配-part1

文章概览 一、概述&#xff1a;二、基本概念&#xff1a;2.1、物料分配概览2.1.1物料适用场景&#xff1a;2.1.2物料分配方式&#xff1a; 2.2、组件分配概览2.2.1 组件适用场景2.2.2 组件分配注意事项&#xff1a; 三、测试示例3.1、准备工艺路线组数据&#xff1a;3.2、工艺路…

【Java】数组中的拷贝方法与初步理解深浅拷贝

文章目录 普通的数组拷贝函数可以指定区间拷贝的数组拷贝函数深浅拷贝 普通的数组拷贝函数 Arrays.copyOf(array,array.length) 我们进入到这个函数的源码中&#xff0c;可以看到这两个参数一个是原始数组&#xff0c;一个是拷贝后的新的长度。 例如&#xff1a; public cla…

YOLOv5图像和视频对象生成边界框的目标检测实践(GPU版本PyTorch错误处理)

识别图像和视频里面的对象&#xff0c;在计算机视觉中是一个很重要的应用&#xff0c;比如无人驾驶&#xff0c;这个就需要实时的检测到周边环境的各种对象&#xff0c;并及时做出处理。目标检测在以往的文章中有重点讲解过几种&#xff0c;其中Faster R-CNN的源码解读&#xf…

数据结构之复杂度分析

1、大 O 复杂度表示法 算法的执行效率&#xff0c;粗略地讲&#xff0c;就是算法代码执行的时间 这里有段非常简单的代码&#xff0c;求 1,2,3…n 的累加和。看如何来估算一下这段代码的执行时间 int cal(int n) {int sum 0;int i 1;for (; i < n; i) {sum sum i;}ret…

Vue3版本生命周期详解

介绍 vue3和vue2的生命周期改动不大,下面以图来展现两个版本的周期钩子 使用示例 配置项写法 vue3可以使用vue2版本的周期配置 准备一个HelloWord组件 使用App组件嵌套HelloWorld组件,并进行v-if判断是否卸载该组件,以此查看vue3的卸载钩子 测试: 可以看到当页面刷新后执行…

Maven的安装与使用

一、简介 1.什么是Maven? Maven翻译为“专家“&#xff0c; ”内行”的意思&#xff0c;是著名Apache公司下基于Java开发的开源项目。Maven项目对象模型&#xff08;POM&#xff09;是一个项目管理工具软件&#xff0c;可以通过简短的中央信息描述来管理项目的搭建&#x…

前端Vue自定义滚动卡片,可以用于商品海报生成

前端Vue自定义滚动卡片&#xff0c;可以用于商品海报生成&#xff0c; 下载完整代码请访问uni-app插件市场地址&#xff1a;https://ext.dcloud.net.cn/plugin?id13189 实现代码如下&#xff1a; # cc-scroolCard #### 使用方法 使用方法 <!-- dataInfo&#xff1a;滚动…