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

物联网平台中的Swagger(二)安全认证与生产实践

企业级物联网平台开发中,API文档的安全性和生产环境部署策略至关重要。本文探讨Swagger在安全认证机制设计、生产环境部署、性能优化等方面的实践经验。

一、安全认证机制设计

1.1 多重安全策略

物联网平台的API文档需要考虑安全性,实现JWT Token和Basic认证的双重保护:

private List<SecurityScheme> securitySchemes() {List<SecurityScheme> securitySchemes = new ArrayList<>();// JWT Token认证securitySchemes.add(new ApiKey("Authorization", "Authorization", "header"));// Basic认证(可选)if (swaggerBasicConfig.isEnable()) {securitySchemes.add(new BasicAuth("basicAuth"));}return securitySchemes;
}private List<SecurityContext> securityContexts() {List<SecurityContext> securityContexts = new ArrayList<>();// JWT Token上下文securityContexts.add(SecurityContext.builder().securityReferences(defaultAuth()).forPaths(PathSelectors.regex(".*v3.*")).build());// Basic认证上下文if (swaggerBasicConfig.isEnable()) {securityContexts.add(SecurityContext.builder().securityReferences(basicAuth()).forPaths(PathSelectors.any()).build());}return securityContexts;
}

1.2 Basic认证过滤器实现

为了保护Swagger文档访问,实现专门的Basic认证过滤器:

@Component
public class SwaggerBasicAuthFilter implements Filter {@Autowiredprivate SwaggerBasicConfig swaggerBasicConfig;@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)throws IOException, ServletException {HttpServletRequest httpRequest = (HttpServletRequest) request;HttpServletResponse httpResponse = (HttpServletResponse) response;String requestURI = httpRequest.getRequestURI();// 检查是否为Swagger相关路径if (isSwaggerPath(requestURI)) {if (swaggerBasicConfig.isEnable()) {if (!authenticate(httpRequest)) {httpResponse.setStatus(HttpServletResponse.SC_UNAUTHORIZED);httpResponse.setHeader("WWW-Authenticate", "Basic realm=\"Swagger\"");httpResponse.getWriter().write("Unauthorized");return;}}}chain.doFilter(request, response);}private boolean isSwaggerPath(String requestURI) {// 排除登录相关路径和静态资源if (requestURI.equals("/") || requestURI.equals("/login") || requestURI.startsWith("/login") ||requestURI.startsWith("/static/") ||requestURI.startsWith("/webjars/") ||requestURI.startsWith("/resources/")) {return false;}return requestURI.contains("/swagger-ui") || requestURI.contains("/doc.html") ||requestURI.contains("/swagger-resources") ||requestURI.contains("/v2/api-docs");}private boolean authenticate(HttpServletRequest request) {String authHeader = request.getHeader("Authorization");if (!StringUtils.hasText(authHeader) || !authHeader.startsWith("Basic ")) {return false;}try {String base64Credentials = authHeader.substring(6);byte[] credDecoded = Base64Utils.decodeFromString(base64Credentials);String credentials = new String(credDecoded, StandardCharsets.UTF_8);String[] values = credentials.split(":", 2);if (values.length != 2) {return false;}String username = values[0];String password = values[1];return swaggerBasicConfig.getUsername().equals(username) && swaggerBasicConfig.getPassword().equals(password);} catch (Exception e) {return false;}}
}

1.3 配置化认证参数

@Component
public class SwaggerBasicConfig {@Value("${swagger.basic.enable}")private boolean enable;@Value("${swagger.basic.username}")private String username;@Value("${swagger.basic.password}")private String password;// getter方法...
}

对应的配置文件:

swagger:basic:enable: trueusername: adminpassword: swagger123

二、Controller层注解

2.1 控制器级别注解

@RestController
@RequestMapping("/algorithmExecute")
@Api(tags = "算法执行接口")
@Slf4j
public class AlgorithmExecuteController extends BaseController {@Autowiredprivate IAlgorithmConfigService algorithmConfigService;@Autowiredprivate IAlgorithmExecuteService algorithmExecuteService;/*** 获取所有可用的算法配置*/@Log(title = "可用算法配置查询", businessType = BusinessTypeEnum.SELECT)@ApiOperation("获取可用算法配置列表")@GetMapping("/listAvailable")public AjaxResult listAvailable() {try {LambdaQueryWrapper<AlgorithmConfig> queryWrapper = new LambdaQueryWrapper<>();queryWrapper.eq(AlgorithmConfig::getStatus, 1);List<AlgorithmConfig> list = algorithmConfigService.list(queryWrapper);return success(list);} catch (Exception e) {log.error("获取可用算法配置列表失败: {}", e.getMessage(), e);return error("获取可用算法配置列表失败: " + e.getMessage());}}/*** 执行算法*/@Log(title = "算法执行操作", businessType = BusinessTypeEnum.OPERATING)@ApiOperation("执行算法")@PostMapping("/execute")public AjaxResult execute(@RequestParam Long algorithmId, @RequestParam String fileUrl) {if (algorithmId == null) {return error("算法ID不能为空");}if (StringUtils.isEmpty(fileUrl)) {return error("文件URL不能为空");}try {JSONObject result = algorithmExecuteService.executeAlgorithm(algorithmId, fileUrl);return success(result);} catch (Exception e) {log.error("算法执行异常: {}", e.getMessage(), e);return error("算法执行异常: " + e.getMessage());}}
}

2.2 实体类注解规范

@Data
@EqualsAndHashCode(callSuper = true)
@ApiModel(value="设备控制对象", description="设备控制字段及数据表")
public class DeviceControl extends BaseEntity {private static final long serialVersionUID = 1L;@ApiModelProperty(value = "主键")@TableId(value = "id", type = IdType.AUTO)private Integer id;@ApiModelProperty(value = "设备ID")@TableField("node_id")private Integer nodeId;@ApiModelProperty(value = "字段代码")@TableField("field_code")private String fieldCode;@ApiModelProperty(value = "字段名称")@TableField("field_name")private String fieldName;@ApiModelProperty(value = "字段单位")@TableField("field_unit")private String fieldUnit;@ApiModelProperty(value = "字段说明")@TableField("field_desc")private String fieldDesc;@ApiModelProperty(value = "字段值,控制时有用")@TableField("field_value")private String fieldValue;@ApiModelProperty(value = "字段类型(0:值 ,1:按钮)")@TableField("field_type")private String fieldType;@ApiModelProperty(value = "字段是否显示(0:不显示 ,1:显示)")@TableField("field_show")private String fieldShow;@ApiModelProperty(value = "显示顺序")@TableField("order_num")private Integer orderNum;@ApiModelProperty(value = "输入输出 i1输入,o0输出")@TableField("in_out")private String inOut;
}

2.3 复杂参数注解示例

@RestController
@RequestMapping("/admin/device")
@Api(tags = "设备管理")
public class DeviceController extends BaseController {@ApiOperation(value = "设备列表查询", notes = "支持分页和条件查询")@ApiImplicitParams({@ApiImplicitParam(name = "pageNum", value = "页码", defaultValue = "1", dataType = "int", paramType = "query"),@ApiImplicitParam(name = "pageSize", value = "每页数量", defaultValue = "10", dataType = "int", paramType = "query"),@ApiImplicitParam(name = "deviceName", value = "设备名称", dataType = "string", paramType = "query"),@ApiImplicitParam(name = "status", value = "设备状态", dataType = "string", paramType = "query")})@ApiResponses({@ApiResponse(code = 200, message = "查询成功"),@ApiResponse(code = 400, message = "参数错误"),@ApiResponse(code = 500, message = "服务器内部错误")})@GetMapping("/list")public AjaxResult list(@ApiParam(value = "查询条件") DeviceQueryParam queryParam) {// 实现逻辑return success(deviceService.selectDeviceList(queryParam));}@ApiOperation(value = "新增设备", notes = "创建新的物联网设备")@PostMappingpublic AjaxResult add(@ApiParam(value = "设备信息", required = true) @RequestBody @Valid Device device) {return toAjax(deviceService.insertDevice(device));}@ApiOperation(value = "修改设备", notes = "更新设备信息")@PutMappingpublic AjaxResult edit(@ApiParam(value = "设备信息", required = true) @RequestBody @Valid Device device) {return toAjax(deviceService.updateDevice(device));}@ApiOperation(value = "删除设备", notes = "根据设备ID删除设备")@DeleteMapping("/{deviceIds}")public AjaxResult remove(@ApiParam(value = "设备ID数组", required = true) @PathVariable Long[] deviceIds) {return toAjax(deviceService.deleteDeviceByIds(deviceIds));}
}

三、生产环境部署策略

3.1 环境隔离配置

# application-dev.yml (开发环境)
swagger:enabled: truebasic:enable: falseusername: adminpassword: swagger123# application-test.yml (测试环境)
swagger:enabled: truebasic:enable: trueusername: testpassword: test123# application-prod.yml (生产环境)
swagger:enabled: false  # 生产环境禁用

3.2 条件化配置

@EnableKnife4j
@EnableSwagger2
@Profile({"dev", "test"})  // 只在开发和测试环境启用
@ConditionalOnProperty(name = "swagger.enabled", havingValue = "true")
@Configuration
public class SwaggerConfig implements WebMvcConfigurer {// 配置内容
}

3.3 访问地址配置

# 开发环境访问地址
server:port: 8900# 访问URL:
# Swagger UI: http://localhost:8900/swagger-ui.html
# Knife4j文档: http://localhost:8900/doc.html

四、常见问题

4.1 版本兼容性问题

问题:SpringFox 2.9.2版本存在NumberFormatException

解决方案

<dependency><groupId>io.swagger</groupId><artifactId>swagger-models</artifactId><version>1.6.0</version>
</dependency>

4.2 静态资源访问问题

问题:Swagger UI界面无法正常加载

解决方案

@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {registry.addResourceHandler("swagger-ui.html").addResourceLocations("classpath:/META-INF/resources/");registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
}

4.3 安全配置冲突

问题:Swagger与Spring Security配置冲突

解决方案

@Override
public void configure(WebSecurity web) throws Exception {web.ignoring().antMatchers("/swagger-ui.html","/doc.html","/webjars/**","/swagger-resources/**","/v2/api-docs");
}

总结

实际应用中,建议根据项目具体需求和团队规模,适当调整配置策略和使用规范。

参考:https://apifox.com/apiskills/how-to-solve-swagger-api-security/
https://www.cnblogs.com/fortuneju/p/18590291
https://blog.csdn.net/luChenH/article/details/96598433

http://www.dtcms.com/a/356962.html

相关文章:

  • Socket编程核心API与结构解析
  • 【C++】掌握类模板:多参数实战技巧
  • 构筑沉浸式3D世界:渲染、资源与体验的协同之道
  • 云计算学习笔记——逻辑卷管理、进程管理、用户提权RAID篇
  • N32G43x Flash 驱动移植与封装实践
  • DBeaver 的 PostgreSQL 驱动包默认存储位置
  • 序列化和反序列的学习
  • 移动社交时代电商流量获取新路径:基于社群与开源AI智能名片链动2+1模式S2B2C商城小程序的探索
  • 【基础-单选】关于Button组件,下面哪个样式是胶囊型按钮
  • 大模型之RAG, 检索增强生成
  • 【若依】RuoYi-Vue-springboot3分离版
  • RS485、RS232、RS422协议
  • 浔川代码编辑器v2.1.0公测版上线时间公告
  • 基于FPGA的DDR3读写实验学习
  • LeetCode算法日记 - Day 26: 归并排序、交易逆序对的总数
  • 河南葱香鸡蛋,嫩滑香浓超棒!
  • 企业微信如何设置长期有效的获客二维码?3步生成!
  • 机器人视觉检测
  • 决胜财报季,证券投研如何实现财报自动化分析录入?
  • 企微智能表格对接业务系统
  • 指纹手机技术:破解亚马逊多账号运营痛点的底层逻辑与实践
  • useEffect中直接使用 await报错
  • 直流电机驱动与TB6612
  • Shell 中 ()、(())、[]、{} 的用法详解
  • X-anylabeling3.2标注工具的安装与使用
  • Python五天极限复习
  • 突破传统企业组网瓶颈:某科技公司智能组网服务项目深度解析
  • STL容器的连续性及其访问:vector和deque
  • 刷题日记0829
  • 机器学习算法全景解析:从理论到实践