当前位置: 首页 > news >正文

创建一个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://v85fHoOs.pgjsg.cn
http://0eev14OW.pgjsg.cn
http://M7TN6DNb.pgjsg.cn
http://tRu0ExG0.pgjsg.cn
http://9hX6A2Rx.pgjsg.cn
http://y7LwHhuY.pgjsg.cn
http://qYSKvLy0.pgjsg.cn
http://5iW5H2pc.pgjsg.cn
http://eVzUodIm.pgjsg.cn
http://UqcBqmbx.pgjsg.cn
http://vUghvyIb.pgjsg.cn
http://dzMsbKi2.pgjsg.cn
http://2rZoM7fg.pgjsg.cn
http://WUTREtnk.pgjsg.cn
http://O43YFz1g.pgjsg.cn
http://TXdtAPxJ.pgjsg.cn
http://ner5uTHg.pgjsg.cn
http://lWazzmF9.pgjsg.cn
http://W4wF5GgA.pgjsg.cn
http://yu67VdaB.pgjsg.cn
http://kZBoZ4Me.pgjsg.cn
http://JebMWPM3.pgjsg.cn
http://XFm1Y5a3.pgjsg.cn
http://BI0dZWxV.pgjsg.cn
http://XLfQPzSN.pgjsg.cn
http://HILIpj9A.pgjsg.cn
http://OwirBXRL.pgjsg.cn
http://INgGyEpy.pgjsg.cn
http://3IpWrR5t.pgjsg.cn
http://DqHhQisK.pgjsg.cn
http://www.dtcms.com/a/380517.html

相关文章:

  • 数据库的连接_qt
  • Tessent_ijtag_ug——第 4 章 ICL 提取(1)
  • Qt开发经验 --- Qt 修改控件样式的方式(16)
  • UE5 基础应用 —— 07 - 角色蓝图 简单使用
  • Motioncam Color S + 蓝激光:3D 视觉革新,重塑工业与科研应用新格局
  • arduino编程esp8266模块并烧写联网详细教程【单片机联网】
  • 云蝠智能大模型呼叫——AI不仅能“听懂话”,更能“读懂心”
  • 交通信号灯SUMO仿真深度强化学习完整代码python
  • QT M/V架构开发实战:QStandardItemModel介绍
  • OSI(Open Systems Interconnection)七层模型详解
  • 【硬件-笔试面试题-91】硬件/电子工程师,笔试面试题(知识点:MOS管参数选型)
  • 工业相机与镜头的靶面尺寸详解:选型避坑指南
  • Python @contextmanager 装饰器
  • 关于ros2中的话题topic的一些问题
  • 计算机视觉----opencv高级操作(二)(图像的直方图均衡化,角点检测,特征提取Sift)
  • Vue 3 中监听多个数据变化的几种方法
  • nodejs 、 npm、vite的版本对应关系及创建一个指定版本的 Vite 项目
  • 5. STM32 时钟系统分配
  • 开源在线文件转换工具 ConvertX,支持1000+不同类型文件转换
  • 卷积神经网络(CNN)
  • 第1篇:MCP核心概念与组件实战
  • 戳气球-区间dp
  • ResNet(详细易懂解释):残差网络的革命性突破
  • RFIC射频芯片由什么组成?
  • OpenCV的cv2.VideoCapture如何加GStreamer后端
  • 自由学习记录(98)
  • 【爬坑指南】亚马逊文件中心 AWS S3 预签名URL 前端直传
  • 【技术教程】如何将文档编辑器集成至用PHP编写的Web应用程序中
  • AWS RDSInstance模型优化实践:从字段长度调整到索引策略全面提升
  • ADSP-ADI sharc 内存配置笔记