Java는 타사 호출을 제공하는 인터페이스를 개발합니다.

1. 환경

제3자 호출을 제공하기 위해 SpringBoot 기반 인터페이스를 작성합니다. Alibaba의 음성 인식 기능을 사용하는 방법과 유사하게 HTTP 요청을 보내 음성 인식을 수행하는 Alibaba의 패키지 API를 호출할 수 있습니다. 이 기사에서는 주로 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 알고리즘을 사용한 암호화는 그다지 안전하지 않으므로 여기서는 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;

    @Override
    public 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 {
    
    
    @Resource
    private SignatureInterceptor signatureInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
    
    
        registry.addInterceptor(signatureInterceptor).addPathPatterns("/**").excludePathPatterns("/ban");
    }
}

주의점:

  1. @Configuration주석이 필요합니다.
  2. 새로운 사용자 정의 인터셉터 클래스를 사용하여 추가할 수 없으며 주입을 사용하여 주입해야 합니다. 즉, 이렇게 쓸 수는 없습니다.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.xmllombok

오류 코드 클래스 작성: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에 업로드되었습니다. 텍스트 내용을 읽고 싶지 않다면 비디오를 시청할 수도 있습니다.

추천

출처blog.csdn.net/qq_43907505/article/details/135327702