创建一个Spring Boot Starter风格的Basic认证SDK

文章目录

    • 前言
    • 设计思路
    • SDK实现步骤
      • 1. 创建SDK Maven项目(sdk目录)
      • 2. 实现配置类
      • 3. 实现认证逻辑
      • 4. 实现拦截器
      • 5. 实现自动配置
      • 6. 创建spring.factories文件
    • 使用方集成步骤
      • 1. 引入SDK依赖
      • 2. 配置Application属性
      • 3. 创建测试接口
      • 4. 测试接口访问
    • SDK扩展功能
    • 总结

前言

Spring Boot作为当前最流行的Java开发框架之一,其Starter机制为开发者提供了极大的便利,使得集成各种功能变得更加简单。为了帮助开发者快速实现基于AppID和AppSecret的应用认证功能,我们设计并实现了这个认证SDK。该SDK遵循Spring Boot Starter的最佳实践,可以无缝集成到Spring Boot应用中,提供开箱即用的Basic认证功能。

在这里插入图片描述

设计思路

创建一个Spring Boot Starter风格的SDK,它会:
1.自动配置认证所需的组件
2.提供简单的配置方式管理多个AppID/AppSecret
3.通过拦截器自动保护指定接口
4.提供统一的错误响应处理

下面是整个认证流程的示意图:
在这里插入图片描述

SDK实现步骤

1. 创建SDK Maven项目(sdk目录)

创建sdk/pom.xml文件:

<?xml version="1.0" encoding="UTF-8"?>
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.example</groupId><artifactId>java-basic-sdk</artifactId><version>0.0.1-SNAPSHOT</version><packaging>jar</packaging><name>java-basic-sdk</name><description>java-basic-sdk</description><properties><java.version>1.8</java.version><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding><spring-boot.version>2.6.13</spring-boot.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies><dependencyManagement><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-dependencies</artifactId><version>${spring-boot.version}</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement><build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><configuration><source>${java.version}</source><target>${java.version}</target></configuration></plugin></plugins></build>
</project>

2. 实现配置类

创建配置属性类AppAuthProperties.java:

/*** AppAuthProperties* @author senfel* @version 1.0* @date 2025/9/12 16:17*/
@ConfigurationProperties(prefix = "app.auth")
public class AppAuthProperties {/*** 是否启用App认证*/private boolean enabled = true;/*** 需要认证的路径模式(默认保护/test接口)*/private String[] includePatterns = new String[]{"/test/**"};/*** 排除的路径模式*/private String[] excludePatterns = new String[]{};/*** 存储有效的AppID和AppSecret键值对*/private Map<String, String> clients = new HashMap<>();public boolean isEnabled() {return enabled;}public void setEnabled(boolean enabled) {this.enabled = enabled;}public String[] getIncludePatterns() {return includePatterns;}public void setIncludePatterns(String[] includePatterns) {this.includePatterns = includePatterns;}public String[] getExcludePatterns() {return excludePatterns;}public void setExcludePatterns(String[] excludePatterns) {this.excludePatterns = excludePatterns;}public Map<String, String> getClients() {return clients;}public void setClients(Map<String, String> clients) {this.clients = clients;}
}

3. 实现认证逻辑

创建认证服务类AppAuthService.java:

/*** AppAuthService* @author senfel* @version 1.0* @date 2025/9/12 16:19*/
public class AppAuthService {private final AppAuthProperties properties;public AppAuthService(AppAuthProperties properties) {this.properties = properties;}/*** 验证AppID和AppSecret是否有效*/public boolean validateCredentials(String appId, String appSecret) {if (!StringUtils.hasText(appId) || !StringUtils.hasText(appSecret)) {return false;}// 检查配置中是否存在该AppID且AppSecret匹配return properties.getClients().containsKey(appId) &&properties.getClients().get(appId).equals(appSecret);}/*** 从HTTP Basic认证头中提取凭证*/public String[] extractCredentials(String authorizationHeader) {if (!StringUtils.hasText(authorizationHeader) ||!authorizationHeader.startsWith("Basic ")) {return null;}try {String base64Credentials = authorizationHeader.substring(6);String credentials = new String(Base64.getDecoder().decode(base64Credentials));return credentials.split(":", 2);} catch (Exception e) {return null;}}
}

4. 实现拦截器

创建认证拦截器AppAuthInterceptor.java:

/*** AppAuthInterceptor* @author senfel* @version 1.0* @date 2025/9/12 16:20*/
public class AppAuthInterceptor implements HandlerInterceptor {private final AppAuthService appAuthService;public AppAuthInterceptor(AppAuthService appAuthService) {this.appAuthService = appAuthService;}@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response,Object handler) throws Exception {// 从请求头中获取Authorization信息String authorizationHeader = request.getHeader("Authorization");// 提取AppID和AppSecretString[] credentials = appAuthService.extractCredentials(authorizationHeader);if (credentials == null || credentials.length != 2) {sendErrorResponse(response, "缺少有效的Authorization请求头,请使用Basic认证格式");return false;}String appId = credentials[0];String appSecret = credentials[1];// 验证凭证if (!appAuthService.validateCredentials(appId, appSecret)) {sendErrorResponse(response, "无效的AppID或AppSecret");return false;}return true;}private void sendErrorResponse(HttpServletResponse response, String message)throws Exception {response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);response.setContentType("application/json;charset=UTF-8");response.getWriter().write("{\"code\": 401, \"message\": \"" + message + "\"}");}
}

5. 实现自动配置

创建自动配置类AppAuthAutoConfiguration.java:

/*** AppAuthAutoConfiguration* @author senfel* @version 1.0* @date 2025/9/12 16:22*/
@Configuration
@ConditionalOnWebApplication
@EnableConfigurationProperties(AppAuthProperties.class)
@ConditionalOnProperty(prefix = "app.auth", name = "enabled", havingValue = "true", matchIfMissing = true)
public class AppAuthAutoConfiguration implements WebMvcConfigurer {private final AppAuthProperties properties;public AppAuthAutoConfiguration(AppAuthProperties properties) {this.properties = properties;}@Beanpublic AppAuthService appAuthService() {return new AppAuthService(properties);}@Beanpublic AppAuthInterceptor appAuthInterceptor(AppAuthService appAuthService) {return new AppAuthInterceptor(appAuthService);}@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(appAuthInterceptor(appAuthService())).addPathPatterns(properties.getIncludePatterns()).excludePathPatterns(properties.getExcludePatterns());}
}

6. 创建spring.factories文件

创建sdk/src/main/resources/META-INF/spring.factories文件:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.example.javabasicsdk.config.AppAuthAutoConfiguration

使用方集成步骤

1. 引入SDK依赖

在使用方的项目中添加SDK依赖:

<!--java-basic-sdk-->
<dependency><groupId>com.example</groupId><artifactId>java-basic-sdk</artifactId><version>0.0.1-SNAPSHOT</version>
</dependency>

2. 配置Application属性

在使用方的application.yml中配置允许访问的AppID和AppSecret:

# App认证配置
app:auth:enabled: trueinclude-patterns:- /test/**# 配置允许访问的AppID和AppSecretclients:appid1: "appsecret1"

3. 创建测试接口

创建测试ControllerTestBasicController.java:

/*** TestController* @author senfel* @version 1.0* @date 2025/9/12 16:33*/
@RestController
@RequestMapping("/test")
public class TestBasicController {@GetMappingpublic String test() {return "认证成功,可以访问此接口";}@GetMapping("/sub")public String testSub() {return "认证成功,可以访问子接口";}
}

4. 测试接口访问

不带basic请求头,会提示认证失败:
在这里插入图片描述

带错误的appId/appSecret,会提示验证失败:
在这里插入图片描述

正确的认证信息可以访问:
在这里插入图片描述

SDK扩展功能

如果想进一步增强SDK的功能,可以考虑:
1.添加日志记录:记录认证成功和失败的请求
2.限流功能:为每个AppID添加请求频率限制
3.动态配置:支持从数据库或配置中心动态加载AppID/AppSecret
4.管理接口:提供管理接口用于动态添加/删除AppID和AppSecret
5.多种认证方式:除了Basic认证,支持自定义请求头等方式

总结

通过以上实现,创建一个Spring Boot Starter风格的AppID/AppSecret认证SDK,使用方只需:
1.引入SDK依赖
2.在application.yml中配置允许访问的AppID和AppSecret
3.创建需要保护的接口(如/test)
SDK会自动拦截配置的接口路径,验证请求中的AppID和AppSecret,只有凭证有效的请求才能访问受保护的接口。这种设计提供了开箱即用的体验,同时保持了足够的灵活性,可以通过配置调整保护的范围和允许的凭证。

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

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

相关文章

mybatis处理统计sql进度丢失问题

如何处理统计sql进度丢失 SELECT sum(decimal_column) AS sum_value FROM your_table如上sql执行时没有问题&#xff0c;在数据库可视工具可以正常显示&#xff0c;但是在mybatis执行时&#xff0c;却出现解决办法 使用转 decimal 控制精度 SELECT CAST(SUM(decimal_column) A…

全球首款!科聪控制器获德国 TÜV 莱茵功能安全认证

近日&#xff0c;浙江科聪控制技术有限公司&#xff08;以下简称"科聪"&#xff09;的安全移动机器人控制器MSC5000荣获全球权威认证机构德国莱茵TV集团&#xff08;TV Rheinland&#xff09;颁发的功能安全认证证书。这款控制器是全球首款通过SIL3、PLe 认证的移动机…

pureadmin的动态路由和静态路由

在 PureAdmin&#xff08;基于 Vue3 的后台管理框架&#xff09;中&#xff0c;静态路由和动态路由是实现路由管理的两种方式&#xff0c;主要区别在于路由的定义时机、加载方式和灵活性&#xff0c;具体区别如下&#xff1a; 1. 静态路由 定义方式&#xff1a;路由规则在代码中…

第3章:CPU实战

1. Linux操作系统CPU平均负载 以前我们总认为CPU使用率和CPU平均负载是一样的&#xff0c;负载高了就是CPU使用率提高。但是到底是什么情况呢&#xff1f; 1.1. CPU的平均负载 单位时间内 系统处于 可运行状态 和不可中断状态 的平均进程数&#xff0c;就是平均活跃进程数&a…

【Vue3】06-利用setup编写vue(1)

其它篇章&#xff1a; 1.【Vue3】01-创建Vue3工程 2.【Vue3】02-Vue3工程目录分析 3.【Vue3】03-编写app组件——src 4.【Vue3】04-编写vue实现一个简单效果 5.【Vue3】05-Options API和Composition API的区别 6.【Vue3】06-利用setup编写vue&#xff08;1&#xff09; 7.【Vue…

UDS NRC速查

目录 NRC 一、通用NRC(0x10~0x5F) 二、数据相关NRC(0x70~0x8F) 三、会话与状态NRC 注意事项 UDS中的NRC(Negative Response Code)即否定响应码,用于在诊断通信中表示服务端无法成功执行客户端请求的原因。以下是一些常用的UDS NRC码及其含义: HEX Name Description 01 …

【AI论文】多模态大型语言模型的视觉表征对齐

摘要&#xff1a;通过视觉指令微调训练的多模态大型语言模型&#xff08;MLLMs&#xff09;在各类任务中均取得了优异表现&#xff0c;然而在以视觉为中心的任务&#xff08;如物体计数或空间推理&#xff09;中&#xff0c;其性能仍存在局限。我们将这一差距归因于当前主流的纯…

SKywalking Agent配置+Oracle监控插件安装指南

SKywalking Agent配置Oracle监控插件安装指南前言&#xff1a; SkyWalking Elasticsearch8 容器化部署指南 Skywalking版本&#xff1a;V10.2.0 Skywalking Agent版本&#xff1a;V9.4.0 Skywalking Agent下载地址&#xff1a;Downloads | Apache SkyWalking 插件下载地址&…

ES相关问题汇总

问题一&#xff1a;关于【QueryBuilder对象】和【Query String语法】查询时底层运行方式和结果的差异

5. STM32 时钟系统分配

文章目录下述将以stm32f407 为例1. 时钟系统及频率分析2. 时钟配置下述将以stm32f407 为例 1. 时钟系统及频率分析 上述STM32F4时钟系统图解析入下&#xff1a; STM32F407 系列微控制器&#xff08;基于 Cortex-M4 内核&#xff0c;带 FPU&#xff09;的工作频率配置如下&…

《从 0 建立测试开发认知:先搞懂 “是什么”,再学 “怎么做”》

&#x1f525;个人主页&#xff1a;草莓熊Lotso &#x1f3ac;作者简介&#xff1a;C研发方向学习者 &#x1f4d6;个人专栏&#xff1a; 《C知识分享》《Linux 入门到实践&#xff1a;零基础也能懂》《数据结构与算法》《测试开发实战指南》《算法题闯关指南》 ⭐️人生格言&a…

net::ERR_EMPTY_RESPONSE

net::ERR_EMPTY_RESPONSE表现解决表现 Java后端封装一个接口&#xff0c;透传前端参数&#xff0c;请求到其他模块服务 本地开发环境联调时是没有问题&#xff0c;测试环境上报错 1.前端报错&#xff0c;F12检查&#xff0c;network上的请求&#xff0c;返回response选项中为空…

在线多功能环境音生成器

https://oltool.cc/toolbox/huanjingyins.html 关于环境音生成器介绍&#xff1a; 1、本工具可以混合各种声音&#xff0c;比如下雨声&#xff0c;打雷声&#xff0c;海浪声&#xff0c;鸟叫以及虫鸣声等&#xff0c;生成新的环境声。 2、定时器&#xff1a;可以设置倒计时&…

本地电脑映射端口到外网访问的开启方法和注意事项,内网服务提供跨网使用简单操作实现

在计算机网络中&#xff0c;端口映射是一项重要的技术&#xff0c;它允许外网用户访问局域网内的特定设备或服务。当我们在本地电脑搭建部署项目应用后&#xff0c;就可以通过映射端口的方式&#xff0c;简单快速稳定的提供互联网访问服务。以下将详细介绍如何开启电脑映射端口…

Java 大视界 -- Java 大数据在智能医疗健康档案数据分析与个性化健康管理中的应用(410)

Java 大视界 -- Java 大数据在智能医疗健康档案数据分析与个性化健康管理中的应用&#xff08;410&#xff09;引言&#xff1a;正文&#xff1a;一、2023 年 6 月智能医疗健康档案的核心落地需求&#xff08;政策 业务双驱动&#xff09;1.1 政策倒逼的数据应用痛点&#xff…

微服务架构的基石:Nacos全方位解析与Java实战指南

引言在云原生与微服务浪潮席卷而来的今天&#xff0c;服务的治理与配置的管理变得前所未有的复杂。一个个单一的应用被拆分为数十甚至上百个微服务&#xff0c;如何让这些服务轻松地发现彼此&#xff1f;如何在不重启应用的情况下动态调整所有服务的参数&#xff1f;这些问题直…

IDA pro 生成idapro.hexlic

先安装IDA pro&#xff0c;安装好后&#xff0c;把根目录中的 ida32.dll和ida.dll赋值到python文件脚本同目录中&#xff0c;如图。 直接运行py import json import hashlib import os from datetime import datetime, timedelta import platform import winregname input(&…

【ARMv7-M】复位向量与启动过程

关于ARMv7上电复位后&#xff0c;通过复位向量初始化堆栈位置、PC指针&#xff0c;然后跳转到汇编入口&#xff0c;开始执行系统初始化等等操作&#xff0c;熟悉了解这个过程&#xff0c;对于嵌入式系统软件开发来说至关重要。不同的SOC在BootROM与Flash的地址分配上&#xff0…

【开发者导航】开源免费的金融数据量化与分析项目!

Hello大家好&#xff01;我是助你打破信息差的开发者导航。今天给大家分享的开源项目是OpenBB&#xff0c;一个面向量化与分析的开源金融数据平台&#xff01; 金融分析和量化研究需要可靠的数据来源与灵活的分析工具。OpenBB 正是为金融分析师、量化研究员以及 AI 代理开发者…

如何使用 OCR 提取扫描件 PDF 的文本(Python 实现)

从 PDF 中提取文本一直是很多人的需求。市面上的工具虽然能处理大部分数字 PDF&#xff0c;但遇到扫描件 PDF 时往往无能为力&#xff0c;想要直接复制或获取其中的文字并不容易。其实这个问题并不是没有解法 —— 本文将带你了解如何借助 Python OCR 技术&#xff0c;从扫描 …