maven插件2(spring-api-auth-valid-plugin)

news2025/1/12 22:57:09
  • https://maven.apache.org/guides/mini/guide-configuring-plugins.html
  • https://maven.apache.org/plugin-testing/maven-plugin-testing-harness/getting-started/index.html

plugin-desc

  • 业务功能
    • 所有的endpoint,必须带有指定的安全校验标签,如spring-security的@PreAuthorize,@PostAuthorize
    • 允许收集maven dependencies, 检验dependencies version是否在可用清单中
  • 基础功能
    • 可以仅扫描指定代码目录
    • 扫描不通过的策略: 如:n个项目不通过,就抛出异常

plugin-coding

代码结构

在这里插入图片描述

  • DependencyIssueScanner: 用来比较maven依赖的版本是否legal
  • SpringIssueScanner: 通过反射用来寻找project中所有的spring API,以及筛选出security
  • EndpointAuthMojo: 插件主类

pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>cn.jhs.maven.plugins</groupId>
    <artifactId>endpoint-auth-plugin</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>maven-plugin</packaging>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven-plugin-tools.version>3.13.1</maven-plugin-tools.version>
        <maven-core.version>3.9.6</maven-core.version>

        <!-- Set the Java version -->
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>

        <spring.version>5.0.9.RELEASE</spring.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.apache.maven</groupId>
            <artifactId>maven-plugin-api</artifactId>
            <version>3.0</version>
            <scope>provided</scope>
        </dependency>

        <!-- dependencies to annotations -->
        <dependency>
            <groupId>org.apache.maven.plugin-tools</groupId>
            <artifactId>maven-plugin-annotations</artifactId>
            <version>${maven-plugin-tools.version}</version>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>org.apache.maven</groupId>
            <artifactId>maven-core</artifactId>
            <version>${maven-core.version}</version>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>org.reflections</groupId>
            <artifactId>reflections</artifactId>
            <version>0.9.11</version>
        </dependency>

        <!-- Spring MVC -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>${spring.version}</version>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-core</artifactId>
            <version>${spring.version}</version>
            <scope>provided</scope>
        </dependency>

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-plugin-plugin</artifactId>
                <version>3.13.1</version>
                <configuration>
                    <goalPrefix>auth-plugin</goalPrefix>
                </configuration>
                <executions>
                    <execution>
                        <id>mojo-descriptor</id>
                        <goals>
                            <goal>descriptor</goal>
                        </goals>
                    </execution>
                    <execution>
                        <id>help-goal</id>
                        <goals>
                            <goal>helpmojo</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>


DependencyIssueScanner(略)

SpringIssueScanner

在这里插入图片描述

getShortXXXDescription

在这里插入图片描述

EndpointAuthMojo

@Mojo(name = "validate", requiresDependencyResolution = ResolutionScope.COMPILE, threadSafe = true)
public class EndpointAuthMojo extends AbstractMojo {
    static final String DEFAULT_PACKAGE = "cn.jhs";

    //current customer project
    @Parameter(defaultValue = "${project}", readonly = true)
    private MavenProject mavenProject;

    @Parameter(defaultValue = "${plugin}", readonly = true)
    private PluginDescriptor pluginDescriptor;

    @Parameter(name = "collectSubDependencies", defaultValue = "true")
    private boolean collectSubDependencies;

    @Parameter(name = "forPackages", alias = "packages")
    private String[] forPackages;

    //mvn -DauthFailThreshold=10
    @Parameter(name = "failThreshold", defaultValue = "1",property = "authFailThreshold")
    private int failThreshold;

    private static final Lock LOCK = new ReentrantLock();

    @Override
    public void execute() throws MojoFailureException {
        LOCK.lock();
        Log logger = getLog();
        requireNonNull(mavenProject, "MavenProject not injected by the MavenPluginManager");
        requireNonNull(pluginDescriptor, "PluginDescriptor not injected by the MavenPluginManager");
        LocalDateTime start = LocalDateTime.now();
        try {
            logger.info("start to validate "+mavenProject.getName()+":"+ mavenProject.getVersion());
            executeInternal(logger);
        } catch (DependencyResolutionRequiredException e) {
            throw new RuntimeException(e);
        } finally {
            logger.info(String.format("validate finished, cost %s s.", LocalDateTime.from(start).getSecond()));
            LOCK.unlock();
        }
    }

    private void executeInternal(Log logger) throws MojoFailureException, DependencyResolutionRequiredException {
        boolean isWebArchive = mavenProject.getPackaging() == null
                || mavenProject.getPackaging().trim().equalsIgnoreCase("war");
        String[] packages = (forPackages == null || forPackages.length == 0) ? new String[]{DEFAULT_PACKAGE} : forPackages;
        logger.info("scanning packages:" + String.join(",",packages));
       int dependencyIssues =  new DependencyIssueScanner(logger,mavenProject.getDependencies()).scan();
        int issues = dependencyIssues;
        if (!isWebArchive) {
            if (collectSubDependencies) {
                logger.info("Collecting dependencies");
                addCompileClasspathElements();
            }
            logger.info("Skipping validation: module is not a web archive");
        } else {
            addCompileClasspathElements();
            Reflections reflections = new Reflections(new ConfigurationBuilder()
                    .setUrls(Stream.of(packages).flatMap(p -> ClasspathHelper.forPackage(p).stream()).collect(toSet()))
                    .filterInputsBy(new FilterBuilder().includePackage(packages))
                    .setScanners(new TypeAnnotationsScanner(), new MethodAnnotationsScanner()));
            logger.info(format("API method scanned ( %s APIs)...","Spring"));
            int springIssues = new SpringIssueScanner(logger,reflections).scanSpringAPI();
            issues += springIssues;
        }
        if (issues > failThreshold) {
            throw new MojoFailureException(format( " API method(s) have %d validation errors IS above failThreshold:%d .", issues,failThreshold));
        }
    }

    private void addCompileClasspathElements() throws DependencyResolutionRequiredException {
        requireNonNull(mavenProject);
        requireNonNull(pluginDescriptor);
        ClassRealm realm = pluginDescriptor.getClassRealm();

        mavenProject.getCompileClasspathElements().stream()
                .map(File::new)
                .forEach(file -> {
                    try {
                        realm.addURL(file.toURI().toURL());
                    } catch (MalformedURLException e) {
                        throw new RuntimeException(e);
                    }
                });
    }
}

测试

测试project 引入plugin

 <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>

                    <plugin>
                        <groupId>cn.jhs.maven.plugins</groupId>
                        <artifactId>endpoint-auth-plugin</artifactId>
                        <version>1.0-SNAPSHOT</version>
                        <configuration>
                            <packages>
                                <package>cn.jhs</package>
                                <package>cn.jhs2</package>
                            </packages>
                        </configuration>
                        <executions>
                            <execution>
                                <id>endpoint-auth-validate</id>
                                <goals>
                                    <goal>validate</goal>
                                </goals>
                                <phase>compile</phase>
                            </execution>
                        </executions>
                    </plugin>
        </plugins>
    </build>

执行命令

mvn clean compile -DauthFailThreshold=10

结果

在这里插入图片描述

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

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

相关文章

RabbitMQ 集群安装

在 linux 下手动安装 RabbitMQ 集群。 准备 安装之前的准备工作。 准备内容说明其他3 台服务器centos、redhat 等ErlangRabbitMQ 运行需要的基础环境socatRabbitMQ 运行需要的基础环境logrotateRabbitMQ 运行需要的基础环境这个服务器一般自带了 下面的安装示例中使用的版本…

一键测量仪,能否彻底解决燃气灶配件缺陷问题?

燃气灶配件是指用于燃气灶的附件或零部件&#xff0c;用于安装、维护或改进燃气灶的功能和性能。这些配件通常包括各种零部件、附件和替换件&#xff0c;以确保燃气灶的正常运行和安全使用。燃气灶的火焰头是产生火焰的部件&#xff0c;通常根据不同的燃气类型和火力需求选择合…

python-求四位数(赛氪OJ)

[题目描述] 3025 这个数具有一种独特的性质&#xff1a;将它平分为二段&#xff0c;即 30 和 25&#xff0c;使之相加后求平方&#xff0c;即 (3025)^2&#xff0c;恰好等于 3025 本身。请求出具有这样性质的全部四位数。输入格式&#xff1a; 此题没有输入。输出格式&#xff…

详解并掌握AXI4总线协议(一)、AXI4-FULL接口介绍

系列文章目录 文章目录 系列文章目录一、AXI介绍二、AXI4、AXI-Lite、AXI4-Stream区别三、AXI4读写架构3.1 通道定义3.2 读突发时序3.3 写突发时序 四、AXI4-FULL 总线信号介绍4.1全局信号4.2 写地址通道信号4.3 写数据通道信号4.4 写响应通道信号4.5 读地址通道信号4.6 读数据…

Animate软件基础:在时间轴中添加或插入帧

FlashASer&#xff1a;AdobeAnimate2021软件零基础入门教程https://zhuanlan.zhihu.com/p/633230084 FlashASer&#xff1a;实用的各种Adobe Animate软件教程https://zhuanlan.zhihu.com/p/675680471 FlashASer&#xff1a;Animate教程及作品源文件https://zhuanlan.zhihu.co…

抖音爆火的“拆盲盒”直播,是如何将昂贵的废品卖给消费者的?

抖音直播间掀起了一股“拆盲盒”热潮。 最初&#xff0c;这股热潮主要集中在拆卡直播间。一盒10包起卖的卡牌&#xff0c;价格在100~200不等。拆卡主播拿起剪刀行云流水的开盒、拆卡、过牌&#xff0c;一晚上能轻松跑出数万元的营业额。数据显示&#xff0c;头部卡牌公司卡游仅…

Redis+Unity 数据库搭建

游戏中需要存放排行榜等数据&#xff0c;而且是实时存放&#xff0c;所以就涉及到数据库的问题。这里找服务器大神了解到可以用Redis来做存储&#xff0c;免费的效率极高。 Redis的搭建参考上文的文章&#xff0c;同时也感谢这位网友。 搭建Redis 并测试数据 搭建Redis 1.下…

玩转云服务:Google Cloud谷歌云永久免费云服务器「白嫖」 指南

前几天&#xff0c;和大家分享了&#xff1a; 玩转云服务&#xff1a;Oracle Cloud甲骨文永久免费云服务器注册及配置指南 相信很多同学都卡在了这一步&#xff1a; 可用性域 AD-1 中配置 VM.Standard.E2.1.Micro 的容量不足。请在其他可用性域中创建实例&#xff0c;或稍后…

Kafka设计与原理详解

RocketMQ 是一款开源的分布式消息系统&#xff0c;基于高可用分布式集群技术&#xff0c;提供低延时的、高可靠的消息发布与订阅服务。同时&#xff0c;广泛应用于多个领域&#xff0c;包括异步通信解耦、企业解决方案、金融支付、电信、电子商务、快递物流、广告营销、社交、即…

使用kettle开源工具进行跨库数据同步

数据库同步可以用&#xff1a; 1、Navicat 2、Kettle 3、自己写代码 调用码神工具跨库数据同步 -连接 4、其它 实现 这里使用Kettle来同步&#xff0c;主要是开源的&#xff0c;通过配置就可以实现了 Kettle的图形化界面&#xff08;Spoon&#xff09;安装参考方法 ht…

Maven实战.依赖(依赖范围、传递性依赖、依赖调解、可选依赖等)

文章目录 依赖的配置依赖范围传递性依赖传递性依赖和依赖范围依赖调解可选依赖最佳实践排除依赖归类依赖优化依赖 依赖的配置 依赖会有基本的groupId、artifactld 和 version等元素组成。其实一个依赖声明可以包含如下的一些元素&#xff1a; <project> ...<depende…

单例模式及其思想

本文包括以下几点↓ 结论&#xff1a;设计模式不是简单地将一个固定的代码框架套用到项目中&#xff0c;而是一种严谨的编程思想&#xff0c;旨在提供解决特定问题的经验和指导。 单例模式&#xff08;Singleton Pattern&#xff09; 意图 旨在确保类只有一个实例&#xff…

Linux用户-用户组

作者介绍&#xff1a;简历上没有一个精通的运维工程师。希望大家多多关注我&#xff0c;我尽量把自己会的都分享给大家&#xff0c;下面的思维导图也是预计更新的内容和当前进度(不定时更新)。 Linux是一个多用户多任务操作系统,这意味着它可以同时支持多个用户登录并使用系统。…

每日OJ_牛客HJ74 参数解析

目录 牛客HJ74 参数解析 解析代码1 解析代码2 牛客HJ74 参数解析 参数解析_牛客题霸_牛客网 解析代码1 本题通过以空格和双引号为间隔&#xff0c;统计参数个数。对于双引号&#xff0c;通过添加flag&#xff0c;保证双引号中的空格被输出。 #include <iostream> #i…

解决文件夹打不开难题:数据恢复全攻略

在日常的电脑使用过程中&#xff0c;遇到文件夹无法打开的情况无疑是令人头疼的。这不仅可能影响到我们的工作效率&#xff0c;还可能导致重要数据的丢失。本文将深入探讨文件夹打不开的原因&#xff0c;并为您提供两种高效的数据恢复方案&#xff0c;助您轻松应对这一难题。 一…

p33 指针详解(1)(2)(3)

指针的进阶 1.字符指针 void test(int arr[]) { int szsizeof(arr)/sizeof(arr[0]); printf("%d\n", sz); } int main() { int arr[10] {0}; test(arr); return 0; } 这个代码在64位计算机中是8/42 在32位计算机中的是4/41 int main() {char c…

vue2 搭配 html2canvas 截图并设置截图时样式(不影响页面) 以及 base64转file文件上传 或者下载截图 小记

下载 npm install html2canvas --save引入 import html2canvas from "html2canvas"; //使用 html2canvasForChars() { // 使用that来存储当前Vue组件的上下文&#xff0c;以便在回调函数中使用 let that this; // 获取DOM中id为"charts"的元素&…

3.1 拓扑排序

有向图的存储 邻接矩阵 邻接表 拓扑排序 有向无环图&#xff1a;不存在环的有向图 环&#xff1a; 在有向图中&#xff0c;从一个节点出发&#xff0c;最终回到它自身的路径被称为环 入度&#xff1a; 以节点x为终点的有向边的条数被称为x的入度 出度&#xff1a; 以节…

汽车配件销售系统2024

下载在最后,编号ssm007 技术栈: ssmmysqljsp 展示: 下载地址: CSDN现在上传有问题,有兴趣的朋友先收藏.正常了贴上下载地址 备注: 运行有问题请私信我,私信按钮在文章左边) 另外接各种定制系统,java,spring,c,c,python