Java开发一个接口提供给第三方调用

1. 环境

基于SpringBoot编写一个接口,提供给第三方调用。类似于我们使用阿里的语音识别功能,我们可以调用阿里封装好的api,也就是通过发送HTTP请求的方式来做语音识别。本篇文章主要记录在SpringBoot中我们是如何开发接口并让别人可以安全调用的。

使用到的依赖: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><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>3.2.1</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>top.lukeewin</groupId><artifactId>Signature</artifactId><version>0.0.1-SNAPSHOT</version><name>Signature</name><description>Signature</description><properties><java.version>17</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>org.apache.commons</groupId><artifactId>commons-lang3</artifactId></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><configuration><excludes><exclude><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></exclude></excludes></configuration></plugin></plugins></build>
</project>

2. 加密算法的选择

使用MD5这种算法加密是不太安全的,所以这里我们使用hash算法中的HmacSHA256加密算法来生成签名,当我们请求接口时,我们使用把签名和时间戳带上,为啥还要带上时间戳呢,是因为我们之后要控制签名的过期时间需要根据这个前端传递过来的时间戳来计算过期时间。

下面是加密工具类:

public class SignatureUtil {public static String getSignature(String timestamp, String apiKey, String apiSecret) {// 构建签名字符串String signatureString = apiKey + timestamp;String signature = null;// 计算签名try {Mac sha256Hmac = Mac.getInstance("HmacSHA256");SecretKeySpec secretKey = new SecretKeySpec(apiSecret.getBytes(StandardCharsets.UTF_8), "HmacSHA256");sha256Hmac.init(secretKey);byte[] signatureBytes = sha256Hmac.doFinal(signatureString.getBytes(StandardCharsets.UTF_8));signature = Base64.getEncoder().encodeToString(signatureBytes);} catch (NoSuchAlgorithmException | InvalidKeyException e) {throw new RuntimeException(e);}return signature;}
}

3. 编写一个接口

这里简单编写一个音频转码的接口,来模拟我们开发接口的整个过程。

@RestController
public class TransferController {@RequestMapping("/transfer")public BaseResponse transfer() {return BaseResponse.success("转码成功");}@RequestMapping("/ban")public BaseResponse ban() {return BaseResponse.error(ErrorCode.VERIFY_NO_PASS);}
}

4. 自定义一个拦截器

自定义拦截器,对全面请求进行拦截判断是否传递了签名和时间戳,并且判断传递过来的签名和后端计算出来的签名一不一致,还需判断传递到后端时这个签名有没有过期,如果上面这些条件有一个不成立就进行拦截,否则放行。

@Component
public class SignatureInterceptor implements HandlerInterceptor {@Value("${apiKey}")private String apiKey;@Value("${apiSecret}")private String apiSecret;@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {String sign = request.getParameter("sign");String timestamp = request.getParameter("timestamp");if (StringUtils.isNotBlank(sign) && StringUtils.isNotBlank(timestamp)) {String signature = SignatureUtil.getSignature(timestamp, apiKey, apiSecret);if (StringUtils.isNotBlank(signature) && signature.equals(sign) && System.currentTimeMillis() - Long.parseLong(timestamp) < 50 * 1000) {return true;} else {request.getRequestDispatcher("/ban").forward(request, response);return false;}} else {request.getRequestDispatcher("/ban").forward(request, response);return false;}}
}

注意点:

  1. 必须要把该类交给Spring IOC容器进行管理,也就是需要在类上面添加一个注解@Component
  2. 拦截后需要给调用方一个提示,否则调用方不知道是否被拦截,所以这里需要使用request.getRequestDispatcher("/ban").forward(request, response);
  3. 必须要放行拦截的URL,如果不放行,会产生死循环,在这里也就是需要放行/ban接口

5. 编写一个拦截器的配置类

编写拦截器配置类,把自定义的拦截器添加到配置类中。

@Configuration
public class InterceptorConfig implements WebMvcConfigurer {@Resourceprivate SignatureInterceptor signatureInterceptor;@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(signatureInterceptor).addPathPatterns("/**").excludePathPatterns("/ban");}
}

注意点:

  1. 必须要有@Configuration注解
  2. 不能使用new 自定义拦截器类的方式添加进来,必须要使用注入的方式注入进来。也就是不能写成这样registry.addInterceptor(new SignatureInterceptor()).addPathPatterns("/**")

6. 统一接口的响应格式

创建两个工具类,一个是响应基类,一个是错误类。

响应基类:BaseResponse

@Data
public class BaseResponse<T> implements Serializable {private static final long serialVersionUID = 4L;private Integer code;private String message;private Long timestamp = System.currentTimeMillis();private T data;public static <T> BaseResponse<T> success(T data) {BaseResponse<T> resultData = new BaseResponse<>();resultData.setCode(200);resultData.setMessage("OK");resultData.setData(data);return resultData;}public static BaseResponse error(ErrorCode errorCode) {BaseResponse resultData = new BaseResponse();resultData.setCode(errorCode.getCode());resultData.setMessage(errorCode.getMessage());return resultData;}
}

这里用到了@Data注解,是lombok提供的一个注解,所以你需要在pom.xml中引入lombok依赖。

编写错误码类:ErrorCode

public enum ErrorCode {VERIFY_NO_PASS(300, "签名验证未通过");private final Integer code;private final String message;ErrorCode(Integer code, String message) {this.code = code;this.message = message;}public Integer getCode() {return code;}public String getMessage() {return message;}
}

7. 配置文件

在自定义拦截器中,我们通过@Value注解从项目的配置文件application.yml中获取apiKeyapiSecret

application.yml文件如下:

apiKey: dhkadj123fda
apiSecret: hgjdakf12314sdf

对应的视频教程已经上传到B站中,如果不喜欢看文字内容,也可以看视频

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

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

相关文章

一文掌握Java注解之@SpringBootApplication知识文集(1)

&#x1f3c6;作者简介&#xff0c;普修罗双战士&#xff0c;一直追求不断学习和成长&#xff0c;在技术的道路上持续探索和实践。 &#x1f3c6;多年互联网行业从业经验&#xff0c;历任核心研发工程师&#xff0c;项目技术负责人。 &#x1f389;欢迎 &#x1f44d;点赞✍评论…

Spring Cloud Gateway + Nacos 实现动态路由

1、maven 依赖 主要依赖 <!-- 网关 --><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId></dependency>案件差不多完整主要依赖 <!--Spring boot 依赖(微服务基…

51单片机的串口驱动的代码逻辑

什么是串口通信&#xff1f; 51单片机中&#xff0c;串口通信指的是单片机和其他的机器传递数据的时候是通过一个bit一个bit的形式传输的&#xff0c;值得一提的话&#xff0c;串口通信是硬件串口。什么意思呢&#xff1f;也就是在传递比特的时候&#xff0c;不用软件来模拟比…

fanout(扇出模型)

在广播的流程下&#xff0c;消息发送的流程如下&#xff1a; 可以有多个消费者。 每个消费者有自己的queue(队列)。 每个队列都要绑定到Exchange(交换机)。 生产者发送的消息&#xff0c;只能发送到交换机&#xff0c;交换机来决定要发给哪个队列&#xff0c;生产者也无法决…

oracle物化视图

物化视图定义 视图是一个虚拟表&#xff08;也可以认为是一条语句&#xff09;&#xff0c;基于它创建时指定的查询语句返回的结果集&#xff0c;每次访问它都会导致这个查询语句被执行一次&#xff0c;为了避免每次访问都执行这个查询&#xff0c;可以将这个查询结果集存储到…

【算法题】矩阵顺时针旋转90° (js)

力扣链接&#xff1a;https://leetcode.cn/problems/rotate-matrix-lcci/description/ 本人题解&#xff1a; /*** param {number[][]} matrix* return {void} Do not return anything, modify matrix in-place instead.*/ var rotate function (matrix) {const x matrix.le…

Spring高手之路-Spring事务的传播机制(行为、特性)

目录 含义 七种事务传播机制 1.REQUIRED&#xff08;默认&#xff09; 2.REQUIRES_NEW 3.SUPPORTS 4.NOT_SUPPORTED 5.MANDATORY 6.NEVER 7.NESTED 含义 Spring事务的传播机制是指在多个事务方法相互调用时&#xff0c;如何处理这些事务的传播行为。对应七种事务传播行为…

【Git】git基础

Git 命令 git config --globle user.name ""git config --globle user.email ""git config -lgit config --globle --unset []git add []git commit -m ""]git log//当行且美观 git log --prettyoneline//以图形化和简短的方式 git log --grap…

Halcon闭运算closing

Halcon闭运算 文章目录 Halcon闭运算 闭运算的计算步骤&#xff0c;为先膨胀&#xff0c;后腐蚀。这两步操作能将看起来很接近的元素&#xff0c;如区域内部的空洞或外部孤立的点连接成一体&#xff0c;区域的外观和面积也不会有明显的改变。通俗地说&#xff0c;就是类似于“填…

Linux 权限掌控术:深入探索和用户管理

文章目录 前言1.外壳程序是什么&#xff1f;外壳程为什么存在&#xff1f;工作原理外壳程序怎么个事&#xff1f; 2. Linux权限的概念2.1 什么是权限2.2权限的本质2.3 Linux中的用户 3. 普通用户变成rootlinux中有三种人 4.Linux中文件的权限4.1文件的属性权限4.2 掌握修改权限…

TCP发送和接受数据

发送数据 public class sendmessage {public static void main (String[] args) throws IOException {//创建socket对象//在创建的同时会连接服务器,若连接不上,代码会报错Socket socketnew Socket("127.0.0.1",10086);//从连接通道中获取输出流OutputStream ossock…

2024.1.1每日一题

LeetCode每日一题 新的一年开始了&#xff0c;祝大家新年快乐&#xff0c;坚持做每日一题。 1599.经营摩天轮的最大利润 1599. 经营摩天轮的最大利润 - 力扣&#xff08;LeetCode&#xff09; 题目描述 你正在经营一座摩天轮&#xff0c;该摩天轮共有 4 个座舱 &#xff0…

DevOps系列之 JNI实现Java调用C的实现案例

JNI&#xff08;Java Native Interface&#xff09;允许Java代码与其他语言编写的代码进行交互。以下是一个简单的JNI示例&#xff0c;演示如何使用JNI在Java中调用C/C函数。 最终的目录结构如下&#xff1a; JNI&#xff08;Java Native Interface&#xff09;允许Java代码与其…

服务器硬件及RAID配置实战

目录 1、RAID的概念 2、RAID的实现方式 3、标准的RAID 3.1 RAID 0 3.2 RAID 1 3.3 RAID 5 3.4 RAID 10 4、建立硬件 RAID的过程步骤 1、进入RAID 1.1 重启服务器 1.2 进入RAID界面 1.3 在RAID界面切换目录 2、创建RAID 2.1 移动到RAID卡 2.2 按F2&#xff0c;选择…

lenovo联想拯救者8.8英寸掌上游戏机Legion Go 8APU1(83E1)原装出厂Windows11预装系统

链接&#xff1a;https://pan.baidu.com/s/1d586XWXcAWVxlLyV2Oku7Q?pwdd74t 提取码&#xff1a;d74t 系统自带所有驱动、出厂主题壁纸、Office办公软件、联想电脑管家等预装程序 所需要工具&#xff1a;16G或以上的U盘 文件格式&#xff1a;ISO 文件大小&#xff1a;…

C# json 转匿名对象及C#关键字的处理

调用第三方接口&#xff0c;返回的json字符串&#xff0c;为了方便使用转为C#匿名对象&#xff1a; /// <summary>/// json转为匿名对象/// </summary>/// <typeparam name"T"></typeparam>/// <param name"json"></para…

适用于各种危险区域的火焰识别摄像机,实时监测、火灾预防、安全监控,为安全保驾护航

火灾是一种极具破坏力的灾难&#xff0c;对人们的生命和财产造成了严重的威胁。为了更好地预防和防范火灾&#xff0c;火焰识别摄像机作为一种先进的监控设备&#xff0c;正逐渐受到人们的重视和应用。本文将介绍火焰识别摄像机在安全监控和火灾预防方面的全面应用方案。 一、火…

8.Java异常处理和错误码 注意点

异常问题 (一) 错误码 1.【强制】错误码的制定原则&#xff1a;快速溯源、沟通标准化。 说明&#xff1a; 错误码想得过于完美和复杂&#xff0c;就像康熙字典中的生僻字一样&#xff0c;用词似乎精准&#xff0c;但是字典不容易随身 携带并且简单易懂。 正例&#xff1a;错误…

操作系统(Operator System)

这里写目录标题 1. 什么是操作系统2. 主要功能3. 计算机的层状结构4. 什么叫做管理5. 总结6. 为什么要有操作系统7. 最后 1. 什么是操作系统 操作系统&#xff08;英语&#xff1a;Operating System&#xff0c;缩写&#xff1a;OS&#xff09;是一组主管并控制计算机操作、运…

CRM客户关系管理系统

系统开发环境以及版本 操作系统&#xff1a; Windows_7集成开发工具&#xff1a; Eclipse EE_4.7编译环境&#xff1a;JDK_1.8Web服务器&#xff1a;Tomcat_9.0数据库&#xff1a;MySQL_5.7.23 系统框架 spring框架springmvc框架mybatis框架Logback日志框架安全验证框架maven框…