项目2:API Hunter 细节回顾 -2

一. 接口上线/下线功能

接口的上线和下线是由管理员负责进行的。

上线接口,即发布接口。首先需要判断接口是否存在,然后判断接口是否可调用。如果可以调用,就修改数据库中该接口的状态字段为 1,代表发布,默认状态为 0,代表下线。

下线接口,与发布类似。先判断接口是否存在,如果存在,就修改数据库中该接口的状态字段为 0,代表下线。

1. 接收的参数

这两个功能接收的参数只需要 id 即可。因为 id 为接口的主键,唯一且不重复。

2. 管理员权限

这两个功能仅能管理员使用,所以给接口打上注解 @AuthCheck(mustRole = "admin")。

该注解是自定义实现的权限校验切面注解。首先获取到登录用户的信息,然后判断用户是否具有管理员权限,如果没有就抛异常,有权限才继续执行后续操作。

3. 上线接口

    /**
     * 发布
     *
     * @param idRequest
     * @param request
     * @return
     */
    @PostMapping("/online")
    @AuthCheck(mustRole = "admin")
    public BaseResponse<Boolean> onlineInterfaceInfo(@RequestBody IdRequest idRequest,
                                                     HttpServletRequest request) {
        if (idRequest == null || idRequest.getId() <= 0) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        long id = idRequest.getId();
        // 判断是否存在
        InterfaceInfo oldInterfaceInfo = interfaceInfoService.getById(id);
        if (oldInterfaceInfo == null) {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR);
        }
        // 判断该接口是否可以调用
        com.khr.kapiclientsdk.model.User user = new com.khr.kapiclientsdk.model.User();
        user.setUsername("test");
        String username = kApiClient.getUsernameByPost(user);
        if (StringUtils.isBlank(username)) {
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "接口验证失败");
        }
        // 仅本人或管理员可修改
        InterfaceInfo interfaceInfo = new InterfaceInfo();
        interfaceInfo.setId(id);
        interfaceInfo.setStatus(InterfaceInfoStatusEnum.ONLINE.getValue());
        boolean result = interfaceInfoService.updateById(interfaceInfo);
        return ResultUtils.success(result);
    }

首先判断接口是否存在,不存在直接抛异常。然后判断接口是否可以调用,直接使用先前开发的 SDK 即可。最后修改数据库中的状态字段为上线,此处使用了枚举值来表示,

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 接口信息状态枚举

 */
public enum InterfaceInfoStatusEnum {

    OFFLINE("关闭", 0),
    ONLINE("上线", 1);

    private final String text;

    private final int value;

    InterfaceInfoStatusEnum(String text, int value) {
        this.text = text;
        this.value = value;
    }

    /**
     * 获取值列表
     *
     * @return
     */
    public static List<Integer> getValues() {
        return Arrays.stream(values()).map(item -> item.value).collect(Collectors.toList());
    }

    public int getValue() {
        return value;
    }

    public String getText() {
        return text;
    }
}

4. 下线接口

下线接口与上线几乎一致,只需要删除判断接口是否可调用逻辑,并将上线状态修改为下线状态即可。

    /**
     * 下线
     *
     * @param idRequest
     * @param request
     * @return
     */
    @PostMapping("/offline")
    @AuthCheck(mustRole = "admin")
    public BaseResponse<Boolean> offlineInterfaceInfo(@RequestBody IdRequest idRequest,
                                                      HttpServletRequest request) {
        if (idRequest == null || idRequest.getId() <= 0) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        long id = idRequest.getId();
        // 判断是否存在
        InterfaceInfo oldInterfaceInfo = interfaceInfoService.getById(id);
        if (oldInterfaceInfo == null) {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR);
        }
        // 仅本人或管理员可修改
        InterfaceInfo interfaceInfo = new InterfaceInfo();
        interfaceInfo.setId(id);
        interfaceInfo.setStatus(InterfaceInfoStatusEnum.OFFLINE.getValue());
        boolean result = interfaceInfoService.updateById(interfaceInfo);
        return ResultUtils.success(result);
    }

二. 申请签名

需要为每个新注册的用户自动分配一对 accessKey 和 secretKey,所以需要修改注册流程。

    /**
     * 盐值,混淆密码
     */
    private static final String SALT = "khr";
    
    @Override
    public long userRegister(String userAccount, String userPassword, String checkPassword) {
        // 1. 校验
        if (StringUtils.isAnyBlank(userAccount, userPassword, checkPassword)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "参数为空");
        }
        if (userAccount.length() < 4) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "用户账号过短");
        }
        if (userPassword.length() < 8 || checkPassword.length() < 8) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "用户密码过短");
        }
        // 密码和校验密码相同
        if (!userPassword.equals(checkPassword)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "两次输入的密码不一致");
        }
        synchronized (userAccount.intern()) {
            // 账户不能重复
            QueryWrapper<User> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("userAccount", userAccount);
            long count = userMapper.selectCount(queryWrapper);
            if (count > 0) {
                throw new BusinessException(ErrorCode.PARAMS_ERROR, "账号重复");
            }
            // 2. 加密
            String encryptPassword = DigestUtils.md5DigestAsHex((SALT + userPassword).getBytes());
            // 3. 分配 accessKey, secretKey
            String accessKey = DigestUtil.md5Hex(SALT + userAccount + RandomUtil.randomNumbers(5));
            String secretKey = DigestUtil.md5Hex(SALT + userAccount + RandomUtil.randomNumbers(8));
            // 4. 插入数据
            User user = new User();
            user.setUserAccount(userAccount);
            user.setUserPassword(encryptPassword);
            user.setAccessKey(accessKey);
            user.setSecretKey(secretKey);
            boolean saveResult = this.save(user);
            if (!saveResult) {
                throw new BusinessException(ErrorCode.SYSTEM_ERROR, "注册失败,数据库错误");
            }
            return user.getId();
        }
    }

aK 和 sK 的生成是将盐值、用户账户和 5/8 位随机数进行拼接,并采用 MD5 加密生成,保证其随机性。

三. 接口测试调用

首先给这个接口封装一个参数,创建一个名为 InterfaceInfoInvokeRequest 的类。

import lombok.Data;

import java.io.Serializable;

/**
 * 接口调用请求
 *
 */
@Data
public class InterfaceInfoInvokeRequest implements Serializable {

    /**
     * 主键
     */
    private Long id;

    /**
     * 用户请求参数
     */
    private String userRequestParams;

    private static final long serialVersionUID = 1L;
}

 测试调用的完整代码为:

    /**
     * 测试调用
     *
     * @param interfaceInfoInvokeRequest
     * @param request
     * @return
     */
    @PostMapping("/invoke")
    public BaseResponse<Object> invokeInterfaceInfo(@RequestBody InterfaceInfoInvokeRequest interfaceInfoInvokeRequest,
                                                     HttpServletRequest request) {
        if (interfaceInfoInvokeRequest == null || interfaceInfoInvokeRequest.getId() <= 0) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        long id = interfaceInfoInvokeRequest.getId();
        String userRequestParams = interfaceInfoInvokeRequest.getUserRequestParams();
        // 判断是否存在
        InterfaceInfo oldInterfaceInfo = interfaceInfoService.getById(id);
        if (oldInterfaceInfo == null) {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR);
        }
        if (oldInterfaceInfo.getStatus() == InterfaceInfoStatusEnum.OFFLINE.getValue()) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "接口已关闭");
        }
        // 获取当前登录用户的 aK 和 sK,这样相当于用户以自己的身份去调用
        // 即使用户恶意刷量,数据库中也能知道是谁刷的
        User loginUser = userService.getLoginUser(request);
        String accessKey = loginUser.getAccessKey();
        String secretKey = loginUser.getSecretKey();
        // 创建一个临时的 KApiClient 对象,并传入 aK 和 sK
        KApiClient tempClient = new KApiClient(accessKey, secretKey);
        Gson gson = new Gson();
        com.yupi.yuapiclientsdk.model.User user = gson.fromJson(userRequestParams, com.yupi.yuapiclientsdk.model.User.class);
        String usernameByPost = tempClient.getUsernameByPost(user);
        return ResultUtils.success(usernameByPost);
    }

后续会持续更新整理。 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

精美个人博客 付费搭建

博客演示地址&#xff1a;http://gavana.top/ 1、前端博客页 2、后端管理页 此项目原作者已开源&#xff0c;地址&#xff1a;Naccl/NBlog: &#x1f353; Spring Boot Vue 前后端分离博客系统 https://naccl.top (github.com) 可以自己搭建&#xff0c;我只是负责搭建起可直…

【Java13】包

“包”这个机制&#xff0c;类似于分组。主要作用是区分不同组内的同名类。例如&#xff0c;高三三班有一个“王五”&#xff0c;高二八班也有一个“王五”。高三三班和高三八班就是两个不同的包。 Java中的包&#xff08;package&#xff09;机制主要提供了类的多层命名空间&…

被全球数千企业应用的TOGAF®标准,不仅仅是IT框架

2022 年 4 月 25 日&#xff0c;The Open Group 发布了 TOGAF标准第10版。这不仅仅是 The Open Group 的重要里程碑&#xff0c;也是整个企业架构行业和所有从业者的重大利好。作为企业架构师的首选标准&#xff0c;TOGAF一直以来都受到人们的欢迎。对此&#xff0c;第10版必须…

Java异常详解及自定义异常

认识异常&#xff0c;掌握异常处理主要的5个关键字&#xff1a;throw、try、catch、final、throws并掌握自定义异常 目录 1、异常概念与体系结构 1、1异常的概念 1、2异常体系结构 1、3异常的分类 编译时异常&#xff1a; 运行时异常 &#xff1a; 2、异常处理 2、1防御式…

每日直播分享车载知识:硬件在环、UDS诊断、OTA升级、TBOX测试、CANoe、ECU刷写、CAN一致性测试:物理层、数据链路层等

每日直播时间&#xff1a;&#xff08;进腾讯会议方式&#xff1a;QazWsxEdc_2010&#xff09; 周一到周五&#xff1a;20&#xff1a;00-23&#xff1a;00&#xff08;讲一个小时&#xff0c;实操两个小时&#xff09; 周六与周日&#xff1a;9&#xff1a;00-17&#xff1a;0…

C# 中的Semaphore(信号量)详解与应用

文章目录 1. 信号量是什么&#xff1f;2. C# 中的 Semaphore 类3. 信号量的使用示例3.1 创建信号量3.2使用信号量同步线程 4. 总结 在并发编程中&#xff0c;同步是一种基本的需求。信号量&#xff08;Semaphore&#xff09;是一种常见的同步机制&#xff0c;它用于控制对共享资…

智能充电(新能源电动车,电单车)云管理系统的定制解决方案

一 系统简介 智能充电&#xff08;新能源电动车&#xff0c;电单车&#xff09;云管理系统 是一套能够实现对充电站/桩的实时通讯、状态监控、故障检测、运营分析、数据统计、策略设置的智能化多任务管理系统。 二 平台概览 智能充电云管理系统 https://chongdianzhuang.itg…

AI大模型+软件开发,计算机从业者转行的契机?

自从大模型吹响新一轮技术革命的号角后&#xff0c;整个行业各个层次都面临大模型带来的范式转换。我今年在 4 月份上海举办的全球机器学习技术大会上演讲时曾提出&#xff0c;大模型为计算产业带来了计算范式、开发范式、交互范式的三大范式改变。今天是软件研发技术大会&…

职业理念教育观

职业道德理念——教育观 教育是什么、干什么、为了什么&#xff0c;教育心该培养什么样的人、如何培养人等。 教育观 素质教育内涵 教学观 素质教育内涵 新课程改革的教学观

力扣-贪心算法4

406.根据身高重建队列 406. 根据身高重建队列 题目 假设有打乱顺序的一群人站成一个队列&#xff0c;数组 people 表示队列中一些人的属性&#xff08;不一定按顺序&#xff09;。每个 people[i] [hi, ki] 表示第 i 个人的身高为 hi &#xff0c;前面 正好 有 ki 个身高大于或…

微信商城自定义小程序源码系统,PHP+MySQL组合开发 带完整的源代码包以及搭建教程

系统概述 传统电商模式面临着诸多挑战&#xff0c;如用户体验不够个性化、运营成本较高等。而微信商城小程序凭借其轻量级、便捷性和与微信生态系统的紧密结合&#xff0c;为企业提供了新的发展机遇。小编给大家分享一款功能强大、易于定制和扩展的源码系统&#xff0c;帮助企…

C# 快速排序算法的详细讲解

目录 一、前言 二、例子 三、快速排序算法图片讲解 四、快速排序算法代码 五、纯净代码 一、前言 用比较好懂的方式讲一下快速排序算法。 二、例子 如果我有一堆钱&#xff0c;想数清楚&#xff0c;最快的方案是什么&#xff1f; 图1 一堆钱 答&#xff1a;先分类&…

数据库之MQL

1&#xff0c;查询所有 mysql> select * from grade;2&#xff0c; mysql> select id,firstname,lastname from grade;3&#xff0c; mysql> select firstname,lastname from grade where id > 4;4&#xff0c; mysql> select * from grade where sex f;5&…

『SD』比例切换插件 sd-webui-aspect-ratio-helper(附插件)

本文简介 ✨ 告别手动计算&#xff0c;SD绘图神器来啦&#xff01; &#x1f494; 是不是每次使用SD绘图时&#xff0c;都要自己手动去计算图片的宽高比&#xff0c;感觉好繁琐啊&#xff1f; &#x1f389; 今天就来给各位工友安利一个超实用的插件——sd-webui-aspect-ratio-…

【kubernetes集群如何更改所有节点IP】

kubernetes集群如何更改所有节点IP 情景描述更换IP前的准备工作更换IP后的工作--master更换IP后的工作--node节点重新部署之前那些服务 情景描述 我有三台服务器&#xff0c;想要将其组成了一个kubernetes集群&#xff0c;在部署之前&#xff0c;我就对其进行了固定IP的操作&a…

C++、QT企业管理系统

目录 一、项目介绍 二、项目展示 三、源码获取 一、项目介绍 人事端&#xff1a; 1、【产品中心】产品案列、新闻动态的发布&#xff1b; 2、【员工管理】新增、修改、删除、搜索功能&#xff1b;合同以图片的方式上传 3、【考勤总览】根据日期显示所有员工上班、下班时间…

springboot331+vue“有光”摄影分享网站系统+论文+源码+讲解

第3章 系统分析 3.1 可行性分析 3.1.1技术可行性 研发设计程序流程挑选面向对象设计、功能齐全、简单实用的Java编程设计核心理念。MySQL数据库存储数据。Idea工具作为编程软件&#xff0c;win10计算机操作系统作为应用系统&#xff0c;以及数据库可视化工具等技术职称。一般…

十款绚丽的前端 CSS 菜单导航动画

CSS汉堡菜单是一种非常流行的PC端和移动端web菜单风格&#xff0c;特别是移动端&#xff0c;这种风格的菜单应用更为广泛。这款菜单便非常适合在手机App上使用&#xff0c;它的特点是当顶部菜单弹出时&#xff0c;页面内容将会配合菜单出现适当的联动&#xff0c;让整个页面变得…

【软件分享】我们为分类而生—eCognition

分类是各位小伙伴入门遥感需要做的一项基础的工作&#xff0c;在进行遥感影像中的地物进行分类和提取时&#xff0c;如何提高分类精度&#xff0c;常常令人头疼。今天小编带来此前接触过的一个工具&#xff0c;他的名字是—eCognition&#xff0c;感觉比ENVI好用&#xff0c;在…

Java-01-源码篇-04集合-05-SortedMap NavigableMap TreeMap

目录 一&#xff0c;SortedMap 二&#xff0c;NavigableMap 三&#xff0c;TreeMap 3.1 TreeMap 继承结构 3.2 TreeMap 属性 3.3 TreeMap 构造器 3.4 TreeMap 内部类 3.4.1 Values 3.4.2 KeySet 3.4.3 EntrySet 3.4.5 相关集合迭代器 3.4.5.1 PrivateEntryIterato…