Cryptography [java] springboo integration mybatis, swagger, digital signature


insert image description here

project environment

  • JDK19
  • springboot 2.7.6
  • swagger 2.9.2
  • lombok
  • commons-io 2.11.0
  • mysql 8.0.32

A supplement to swagger technology

1.1 Introduction to swagger

  • The OpenAPI Specification (OAS for short) is a project of the Linux Foundation, which attempts to standardize the RESTful service development process by defining a language used to describe the API format or API definition. The current version is V3.0, and it has been released and Open source on github.
  • Swagger is the world's largest OpenAPI Specification (OAS) API development tool framework, supporting the development of the entire API lifecycle from design and documentation to testing and deployment.
  • Spring Boot can integrate Swagger and generate Swagger interfaces. Spring Boot is an artifact in the Java field. It is a framework for quickly building projects under the Spring project

1.2 Basic annotations of swagger

  • swagger generates interface documents through annotations, including interface name, request method, parameters, return information, etc.
note illustrate
@Api Modify the entire class to describe the role of the Controller
@ApiOperation Describe a method of a class, or an interface
@ApiParam Single parameter description
@ApiModel Use the object entity as an input parameter
@ApiProperty When receiving parameters with an object receiver, describe a field of the object
@ApiResponse One of the descriptions in the HTTP response
@ApiResponses Overall description of the HTTP response
@ApiIgnore Use this annotation to ignore this API
@ApiError Information returned by an error
@ApiImplicitParam a request parameter
@ApiImplicitParams multiple request parameters

  • @Api
    • Modify the entire class to describe the role of the Controller
    @Controller
    @RequestMapping("/queryAll")
    @Api(value = "查询所有记录")
    public class queryAll {
          
          
        //...
    }
    

  • @ApiOperation
    • Used to describe a method or interface, the parameter form that can be added:
    @ApiOperation(value = “接口说明”, httpMethod = “接口请求方式”, response = “接口返回参数类型”, notes = “接口发布说明”)
    
    @RequestMapping("/swagger")
    @ResponseBody
    @ApiOperation(value = "根据用户名获取用户的信息",notes = "查询数据库中的记录",httpMethod = "POST",response = String.class)
        public String getUserInfo(String userName) {
          
          
            return "1234";
        }
    }
    

  • @ApiImplicitParam A request parameter
    @ApiImplicitParam(required = “是否必须参数”, name = “参数名称”, value = “参数具体描述”,dateType=“变量类型”,paramType=”请求方式”)
    
@ApiImplicitParam(name = "userName",value = "用户名",required = true,dataType = "String",paramType = "query")
    public String getUserInfo(String userName) {
    
    
        return "1234";
    }
}

  • @ApiImplicitParams multiple request parameters
    • The parameters are the same as @ApiImplicitParam, except that this annotation can add multiple parameters
    @ApiImplicitParams({
          
          
        @ApiImplicitParam(name = "nickName",value = "用户的昵称",paramType = "query",dataType = "String",required = true),
        @ApiImplicitParam(name = "id",value = "用户的ID",paramType = "query",dataType = "Integer",required = true)
    })
    public String getUserInfoByNickName(String nickName, Integer id) {
          
          
        return "1234";
    }
    

1.3 controller adds swagger annotation

import com.yang.mapper.UserMapper;
import com.yang.pojo.User;
import com.yang.utils.RsaDemo;
import com.yang.utils.SignatureDemo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.security.PublicKey;
import java.util.List;

/**
 * @author 缘友一世
 * date 2023/1/22-13:00
 */
@Api(tags = "提供用户的增删改查的功能")
@RestController
//@RestController为开发提供了方便☺,在提供json接口时需要的配置操作再也不需要自己配置了
//@RestController注解相当于@ResponseBody和@Controller的结合
public class UserController {
    
    
    @Autowired
    UserMapper userMapper;
    @ApiOperation(value = "查询用户")
    @RequestMapping(value = "/findAll", method = RequestMethod.GET)
    public List<User> queryUserList() {
    
    
        List<User> userList = userMapper.queryUserList();
        for(User user:userList ) {
    
    
            System.out.println(user);
        }
        return userList;
    }
    @ApiOperation(value = "根据id查询用户")
    @RequestMapping(value = "/queryUserById",method = RequestMethod.GET)
    @ApiImplicitParams({
    
    
            //@ApiImplicitParam(name = "userName",value = "用户的昵称",paramType = "query",dataType = "String",required = true),
            @ApiImplicitParam(name = "id",value = "用户的id",paramType = "query",dataType = "int",required = true)
    })
    public User queryUserById(@RequestParam("id") int Id) {
    
    
        return userMapper.queryUserById(Id);
    }

    @ApiOperation(value = "添加用户")
    @RequestMapping(value = "/addUser", method = RequestMethod.POST)
    public String addUser() {
    
    
        userMapper.addUser(new User(6, "三毛", "123456"));
        return "finish addUser";
    }
    @ApiOperation(value = "更新用户")
    @RequestMapping(value = "/updateUser", method = RequestMethod.PUT)
    public String updateUser() {
    
    
        userMapper.updateUser(new User(6, "阿毛", "5211314"));
        return "finish UpdateUser";
    }
    @ApiOperation(value = "删除用户")
    @RequestMapping(value = "/addUser", method = RequestMethod.DELETE)
    public String deleteUer() {
    
    
        userMapper.deleteUser(6);
        return "finish DeleteUser";
    }

    @ApiOperation(value = "购物")
    @RequestMapping(value = "/buy", method = RequestMethod.GET)
    public String buy(String price, String num, String signature) {
    
    
        try {
    
    
            // 获取公钥
            PublicKey publicKey = RsaDemo.loadPublicKeyFromFile("RSA", "a.pub");
            // 第一个参数:原文
            // 第二个参数:算法
            // 第三个参数:公钥
            // 第四个参数:签名
            boolean result = SignatureDemo.verifySignature(price + num, "SHA256withRSA", publicKey, signature);
            System.out.println(result);
            if (result) {
    
    
                return "购物成功";
            }
        } catch (Exception e) {
    
    
            e.printStackTrace();
        }

        return "购物失败";
    }
}

Two project construction

  • The process of creating a project will not be described in detail!

2.1 Create a database

CREATE DATABASE USER;
USE USER;
CREATE TABLE USER(
  id INT PRIMARY KEY AUTO_INCREMENT,
  username VARCHAR(20),
  password VARCHAR(50),
)
  • Then just insert a piece of data yourself!

2.2 Introducing project dependencies

<dependencies>
  <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-jdbc</artifactId>
  </dependency>
  <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
  </dependency>

  <dependency>
      <groupId>com.mysql</groupId>
      <artifactId>mysql-connector-j</artifactId>
      <scope>runtime</scope>
  </dependency>
  <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-test</artifactId>
      <scope>test</scope>
  </dependency>

  <dependency>
      <groupId>org.mybatis.spring.boot</groupId>
      <artifactId>mybatis-spring-boot-starter</artifactId>
      <version>3.0.1</version>
  </dependency>

  <dependency>
      <groupId>org.projectlombok</groupId>
      <artifactId>lombok</artifactId>
  </dependency>

  <!--swagger2-->
  <dependency>
      <groupId>io.springfox</groupId>
      <artifactId>springfox-swagger2</artifactId>
      <version>2.9.2</version>
  </dependency>
  <dependency>
      <groupId>io.springfox</groupId>
      <artifactId>springfox-swagger-ui</artifactId>
      <version>2.9.2</version>
  </dependency>

  <dependency>
      <groupId>commons-io</groupId>
      <artifactId>commons-io</artifactId>
      <version>2.11.0</version>
  </dependency>
  <dependency>
      <groupId>commons-codec</groupId>
      <artifactId>commons-codec</artifactId>
      <version>1.15</version>
  </dependency>
</dependencies>

2.3 Configure database connection

spring:
  mvc:
    pathmatch:
      matching-strategy: ant_path_matcher
  datasource:
    username: root
    password: yqk.20021027
    url: jdbc:mysql://localhost:3306/user?useSSL=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC
    driver-class-name: com.mysql.cj.jdbc.Driver
#整合mybatis
mybatis:
  type-aliases-package: com.yang.pojo
  mapper-locations: classpath:mybatis/mapper/*.xml

2.4 Configure swagger configuration information

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

import java.util.ArrayList;

@Configuration //配置类
@EnableSwagger2// 开启Swagger2的自动配置
public class SwaggerConfig {
    
    
    //配置docket以配置Swagger具体参数
    @Bean
    public Docket docket() {
    
    
        return new Docket(DocumentationType.SWAGGER_2)
                .enable(true)
                .apiInfo(apiInfo())
                .select()
                .apis(RequestHandlerSelectors.basePackage("com.yang.controller"))
                .build();
    }

    //配置swagger文档信息apiInfo
    private ApiInfo apiInfo() {
    
    
        //作者信息
        Contact contact = new Contact("缘友一世", "https://www.csdn.net/", "[email protected]");
        return new ApiInfo(
                "Spring Boot集成Swagger和加密解密",//标题
                "学习Swagger",//描述
                "1.0",//版本
                "http://localhost",//组织连接
                contact,//联系人信息
                "Apache 2.0",//许可
                "http://www.apache.org/licenses/LICENSE-2.0",//许可连接
                new ArrayList());//拓展
    }


}

2.5 Writing Entity Classes

  • According to the results of the database table, write the entity class
  • You can use the lombok tool to quickly generate get, set methods and constructors with and without parameters
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.apache.ibatis.type.Alias;

/**
 * @author 缘友一世
 * date 2023/1/22-12:55
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
@Alias("User")
public class User {
    
    
    private int id;
    private String username;
    private String password;
}

2.6 Write business interface and query implementation

insert image description here

  1. Write the controller interface
    import com.yang.mapper.UserMapper;
    import com.yang.pojo.User;
    import com.yang.utils.RsaDemo;
    import com.yang.utils.SignatureDemo;
    import io.swagger.annotations.Api;
    import io.swagger.annotations.ApiImplicitParam;
    import io.swagger.annotations.ApiImplicitParams;
    import io.swagger.annotations.ApiOperation;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.*;
    
    import java.security.PublicKey;
    import java.util.List;
    
    /**
     * @author 缘友一世
     * date 2023/1/22-13:00
     */
    @Api(tags = "提供用户的增删改查的功能")
    @RestController
    //@RestController为开发提供了方便☺,在提供json接口时需要的配置操作再也不需要自己配置了
    //@RestController注解相当于@ResponseBody和@Controller的结合
    public class UserController {
          
          
        @Autowired
        UserMapper userMapper;
        @ApiOperation(value = "查询用户")
        @RequestMapping(value = "/findAll", method = RequestMethod.GET)
        public List<User> queryUserList() {
          
          
            List<User> userList = userMapper.queryUserList();
            for(User user:userList ) {
          
          
                System.out.println(user);
            }
            return userList;
        }
        @ApiOperation(value = "根据id查询用户")
        @RequestMapping(value = "/queryUserById",method = RequestMethod.GET)
        @ApiImplicitParams({
          
          
                //@ApiImplicitParam(name = "userName",value = "用户的昵称",paramType = "query",dataType = "String",required = true),
                @ApiImplicitParam(name = "id",value = "用户的id",paramType = "query",dataType = "int",required = true)
        })
        public User queryUserById(@RequestParam("id") int Id) {
          
          
            return userMapper.queryUserById(Id);
        }
    
        @ApiOperation(value = "添加用户")
        @RequestMapping(value = "/addUser", method = RequestMethod.POST)
        public String addUser() {
          
          
            userMapper.addUser(new User(6, "三毛", "123456"));
            return "finish addUser";
        }
        @ApiOperation(value = "更新用户")
        @RequestMapping(value = "/updateUser", method = RequestMethod.PUT)
        public String updateUser() {
          
          
            userMapper.updateUser(new User(6, "阿毛", "5211314"));
            return "finish UpdateUser";
        }
        @ApiOperation(value = "删除用户")
        @RequestMapping(value = "/addUser", method = RequestMethod.DELETE)
        public String deleteUer() {
          
          
            userMapper.deleteUser(6);
            return "finish DeleteUser";
        }
    
    }
    
  2. Write mapper interface
    @Mapper//这个注释表名这是一个mybatis的mapper的类
    @Repository
    public interface UserMapper {
          
          
    
        List<User> queryUserList();
    
        User queryUserById(int id);
    
        int addUser(User user);
    
        int updateUser(User user);
    
        int deleteUser(int id);
    }
    
  3. Write the implementation of mapeer
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.yang.mapper.UserMapper">
    <select id="queryUserList" resultType="User">
        select * from user;
    </select>
    <select id="queryUserById" resultType="User" parameterType="int">
        select * from user where id = #{id};
    </select>

    <insert id="addUser" parameterType="User">
        insert into user(id,name,pwd) values (#{id},#{name},#{pwd});
    </insert>

    <update id="updateUser" parameterType="User">
        update user set name=#{name},pwd=#{pwd} where id=#{id};
    </update>

    <delete id="deleteUser" parameterType="int">
        delete from user where id=#{id};
    </delete>
</mapper>

2.7 Start the project

  • The access address of swagger:http://localhost:8080/swagger-ui.html
    insert image description here
    insert image description here
  • Click try it out to enter the name, Execute executes, and returns the effect as shown in the figure below
    insert image description here

Three digital signatures for project completion

  • Simulate the shopping scene. When the user clicks to shop, the signature information is generated on the front end and passed to the background server for verification. If the price, quantity, and signature are all correct, the shopping is successful. If the parameters are modified by others, the shopping fails
    insert image description here

3.1 Writing tool classes

  • Two codes RsaDemo.java and SignatureDemo.java
    • RsaDemo: Generate and save public and private key files
    • SignatureDemo: Generate digital signatures
      insert image description here

3.1.1 RsaDemo

package com.yang.utils;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.nio.charset.Charset;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.io.FileUtils;

import javax.crypto.Cipher;

public class RsaDemo {
    
    
    public static void main(String[] args) throws Exception {
    
    

        generateKeyToFile("RSA", "a.pub", "a.pri");
    }

    /**
     * 生成密钥对并保存在本地文件中
     *
     * @param algorithm : 算法
     * @param pubPath   : 公钥保存路径
     * @param priPath   : 私钥保存路径
     */
    public static void generateKeyToFile(String algorithm, String pubPath, String priPath) throws Exception {
    
    
        // 获取密钥对生成器
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(algorithm);
        // 获取密钥对
        KeyPair keyPair = keyPairGenerator.generateKeyPair();
        // 获取公钥
        PublicKey publicKey = keyPair.getPublic();
        // 获取私钥
        PrivateKey privateKey = keyPair.getPrivate();
        // 获取byte数组
        byte[] publicKeyEncoded = publicKey.getEncoded();
        byte[] privateKeyEncoded = privateKey.getEncoded();
        // 进行Base64编码
        String publicKeyString = Base64.encodeBase64String(publicKeyEncoded);
        String privateKeyString = Base64.encodeBase64String(privateKeyEncoded);
        // 保存文件
        FileUtils.writeStringToFile(new File(pubPath), publicKeyString,Charset.forName("UTF-8"));
        FileUtils.writeStringToFile(new File(priPath), privateKeyString,Charset.forName("UTF-8"));

    }

    /**
     * 从文件中加载公钥
     *
     * @param algorithm : 算法
     * @param filePath  : 文件路径
     * @return : 公钥
     */
    public static PublicKey loadPublicKeyFromFile(String algorithm, String filePath) throws Exception {
    
    
        // 将文件内容转为字符串
        String keyString = FileUtils.readFileToString(new File(filePath), Charset.forName("UTF-8"));

        return loadPublicKeyFromString(algorithm, keyString);

    }

    /**
     * 从字符串中加载公钥
     *
     * @param algorithm : 算法
     * @param keyString : 公钥字符串
     * @return : 公钥
     */
    public static PublicKey loadPublicKeyFromString(String algorithm, String keyString) throws Exception {
    
    
        // 进行Base64解码
        byte[] decode = Base64.decodeBase64(keyString);
        // 获取密钥工厂
        KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
        // 构建密钥规范
        X509EncodedKeySpec keyspec = new X509EncodedKeySpec(decode);
        // 获取公钥
        return keyFactory.generatePublic(keyspec);

    }

    /**
     * 从文件中加载私钥
     *
     * @param algorithm : 算法
     * @param filePath  : 文件路径
     * @return : 私钥
     */
    public static PrivateKey loadPrivateKeyFromFile(String algorithm, String filePath) throws Exception {
    
    
        // 将文件内容转为字符串
        String keyString = FileUtils.readFileToString(new File(filePath),Charset.forName("UTF-8"));
        return loadPrivateKeyFromString(algorithm, keyString);

    }

    /**
     * 从字符串中加载私钥
     *
     * @param algorithm : 算法
     * @param keyString : 私钥字符串
     * @return : 私钥
     */
    public static PrivateKey loadPrivateKeyFromString(String algorithm, String keyString) throws Exception {
    
    
        // 进行Base64解码
        byte[] decode = Base64.decodeBase64(keyString);
        // 获取密钥工厂
        KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
        // 构建密钥规范
        PKCS8EncodedKeySpec keyspec = new PKCS8EncodedKeySpec(decode);
        // 生成私钥
        return keyFactory.generatePrivate(keyspec);

    }

    /**
     * 使用密钥加密数据
     *
     * @param algorithm      : 算法
     * @param input          : 原文
     * @param key            : 密钥
     * @param maxEncryptSize : 最大加密长度(需要根据实际情况进行调整)
     * @return : 密文
     */
    public static String encrypt(String algorithm, String input, Key key, int maxEncryptSize) throws Exception {
    
    
        // 获取Cipher对象
        Cipher cipher = Cipher.getInstance(algorithm);
        // 初始化模式(加密)和密钥
        cipher.init(Cipher.ENCRYPT_MODE, key);
        // 将原文转为byte数组
        byte[] data = input.getBytes();
        // 总数据长度
        int total = data.length;
        // 输出流
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        decodeByte(maxEncryptSize, cipher, data, total, baos);
        // 对密文进行Base64编码
        return Base64.encodeBase64String(baos.toByteArray());

    }



    /**
     * 分段处理数据
     *
     * @param maxSize : 最大处理能力
     * @param cipher  : Cipher对象
     * @param data    : 要处理的byte数组
     * @param total   : 总数据长度
     * @param baos    : 输出流
     * @throws Exception
     */
    public static void decodeByte(int maxSize, Cipher cipher, byte[] data, int total, ByteArrayOutputStream baos) throws Exception {
    
    
        // 偏移量
        int offset = 0;
        // 缓冲区
        byte[] buffer;
        // 如果数据没有处理完, 就一直继续
        while (total - offset > 0) {
    
    
            // 如果剩余的数据 >= 最大处理能力, 就按照最大处理能力来加密数据
            if (total - offset >= maxSize) {
    
    
                // 加密数据
                buffer = cipher.doFinal(data, offset, maxSize);
                // 偏移量向右侧偏移最大数据能力个
                offset += maxSize;
            } else {
    
    
                // 如果剩余的数据 < 最大处理能力, 就按照剩余的个数来加密数据
                buffer = cipher.doFinal(data, offset, total - offset);
                // 偏移量设置为总数据长度, 这样可以跳出循环
                offset = total;
            }
            // 向输出流写入数据
            baos.write(buffer);
        }
    }

}

  • Run RsaDemo.java to generate public and private keys
    insert image description here

3.1.2 SignatureDemo

package com.yang.utils;

import org.apache.commons.codec.binary.Base64;

import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;

public class SignatureDemo {
    
    
    public static void main(String[] args) throws Exception {
    
    
        // 10:表示购物的价格
        // 10:表示购物的数量
        String a = "10" + "10";

        PublicKey publicKey = RsaDemo.loadPublicKeyFromFile("RSA", "a.pub");
        PrivateKey privateKey = RsaDemo.loadPrivateKeyFromFile("RSA", "a.pri");

        String signaturedData = getSignature(a, "sha256withrsa", privateKey);
        System.out.println(signaturedData);
    }

    /**
     * 生成签名
     *
     * @param input      : 原文
     * @param algorithm  : 算法
     * @param privateKey : 私钥
     * @return : 签名
     * @throws Exception
     */
    public static String getSignature(String input, String algorithm, PrivateKey privateKey) throws Exception {
    
    
        // 获取签名对象
        Signature signature = Signature.getInstance(algorithm);
        // 初始化签名
        signature.initSign(privateKey);
        // 传入原文
        signature.update(input.getBytes());
        // 开始签名
        byte[] sign = signature.sign();
        // 对签名数据进行Base64编码
        return Base64.encodeBase64String(sign);
    }

    /**
     * 校验签名
     *
     * @param input          : 原文
     * @param algorithm      : 算法
     * @param publicKey      : 公钥
     * @param signaturedData : 签名
     * @return : 数据是否被篡改
     * @throws Exception
     */
    public static boolean verifySignature(String input, String algorithm, PublicKey publicKey, String signaturedData) throws Exception {
    
    
        // 获取签名对象
        Signature signature = Signature.getInstance(algorithm);
        // 初始化签名
        signature.initVerify(publicKey);
        // 传入原文
        signature.update(input.getBytes());
        // 校验数据
        return signature.verify(Base64.decodeBase64(signaturedData));

    }

}

  • Run SignatureDemo.java to generate signature information
    iMWjY/L17jMT8nippbtnWjkztU1l9DOH6I31cBwpVRNR7wD3qYRKJGTS+eFNrC+ygFlGmOLqON14vGxBxp7KKAauSuWMmWlbfynKeMsDveIo8ttssYHT+InNf
    0WLgwOnvUnKVK/CZF3rOdYTWYAZAqinJ/SikniPUfE1ZRknwksEFfXqEMUOAWeuHRdeVE+JdhGxv9yT5kV6agBccwili3fPaCQR5nfalPLRccrKlEV5RDwOjO
    YzQk3q64NHXNP1qsK9CpRbVsQPQjNFgU+GwgwI1E8HQJpdDKsbZYgLcBoCFqaoiARDjSsFnlmjpB/uUmF9YJdPkIkTEr3fSiteO3mNeu/WeZXp749MZF3IjRj
    zJYg9bF2s/iuR42zszvlmmWkBLzv9FD8kmg2u8UxhcsarSHirjl7MHF20kbM6h9t51v8DR2cz8ci6ciphiMI6ZE7/rVTfnzq9SdZRaoM+rMKn08ZFHWYXO3MX
    XZmlDQtd0WSF5hVwAgyU9zXMAHi2
    

3.2 Add controller interface

@ApiOperation(value = "购物")
@RequestMapping(value = "/buy", method = RequestMethod.GET)
public String buy(String price, String num, String signature) {
    
    
    try {
    
    
        // 获取公钥
        PublicKey publicKey = RsaDemo.loadPublicKeyFromFile("RSA", "a.pub");
        // 第一个参数:原文
        // 第二个参数:算法
        // 第三个参数:公钥
        // 第四个参数:签名
        boolean result = SignatureDemo.verifySignature(price + num, "SHA256withRSA", publicKey, signature);
        System.out.println(result);
        if (result) {
    
    
            return "购物成功";
        }
    } catch (Exception e) {
    
    
        e.printStackTrace();
    }

    return "购物失败";
}

3.3 Running the program

  • The address accessed by swagger:http://localhost:8080/swagger-ui.html

    insert image description here
    insert image description here

  • If the program is tampered with when requesting the server, such as changing the price to 100 yuan, the shopping will fail
    insert image description here

Guess you like

Origin blog.csdn.net/yang2330648064/article/details/130540864