1
This commit is contained in:
@@ -0,0 +1,160 @@
|
||||
package com.ruoyi.web.controller.public_;
|
||||
|
||||
import com.ruoyi.common.annotation.RateLimiter;
|
||||
import com.ruoyi.common.constant.CacheConstants;
|
||||
import com.ruoyi.common.core.controller.BaseController;
|
||||
import com.ruoyi.common.core.domain.AjaxResult;
|
||||
import com.ruoyi.common.enums.LimitType;
|
||||
import com.ruoyi.jarvis.service.IInstructionService;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 公开订单提交控制器
|
||||
* 用于接收外部提交的订单信息
|
||||
* 特点:
|
||||
* 1. 无需登录认证
|
||||
* 2. 带接口限流保护
|
||||
* 3. 详细的日志记录
|
||||
* 4. 只允许使用"单"指令提交订单
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/public/order")
|
||||
public class PublicOrderController extends BaseController {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(PublicOrderController.class);
|
||||
|
||||
private final IInstructionService instructionService;
|
||||
|
||||
public PublicOrderController(IInstructionService instructionService) {
|
||||
this.instructionService = instructionService;
|
||||
}
|
||||
|
||||
/**
|
||||
* 提交订单
|
||||
*
|
||||
* 限流策略:
|
||||
* - 每个IP每分钟最多3次请求
|
||||
* - 防止恶意刷单和攻击
|
||||
*
|
||||
* @param body 请求体,包含command字段
|
||||
* @param request HTTP请求对象,用于获取客户端信息
|
||||
* @return 执行结果
|
||||
*/
|
||||
@PostMapping("/submit")
|
||||
@RateLimiter(
|
||||
key = CacheConstants.RATE_LIMIT_KEY,
|
||||
time = 60,
|
||||
count = 3,
|
||||
limitType = LimitType.IP
|
||||
)
|
||||
public AjaxResult submit(@RequestBody Map<String, String> body, HttpServletRequest request) {
|
||||
// 获取客户端信息用于日志记录
|
||||
String clientIp = getClientIp(request);
|
||||
String userAgent = request.getHeader("User-Agent");
|
||||
|
||||
// 获取指令内容
|
||||
String cmd = body != null ? body.get("command") : null;
|
||||
|
||||
// 记录请求日志
|
||||
log.info("======================================");
|
||||
log.info("公开订单提交 - 开始");
|
||||
log.info("客户端IP: {}", clientIp);
|
||||
log.info("User-Agent: {}", userAgent);
|
||||
log.info("请求时间: {}", new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new java.util.Date()));
|
||||
|
||||
// 参数校验
|
||||
if (cmd == null || cmd.trim().isEmpty()) {
|
||||
log.warn("参数校验失败: 指令内容为空");
|
||||
log.info("公开订单提交 - 结束(失败)");
|
||||
log.info("======================================");
|
||||
return AjaxResult.error("请输入订单信息");
|
||||
}
|
||||
|
||||
String trimmedCmd = cmd.trim();
|
||||
log.info("指令内容长度: {} 字符", trimmedCmd.length());
|
||||
log.info("指令内容预览: {}", trimmedCmd.length() > 100 ? trimmedCmd.substring(0, 100) + "..." : trimmedCmd);
|
||||
|
||||
// 安全检查:只允许"单"开头的指令
|
||||
if (!trimmedCmd.startsWith("单:") && !trimmedCmd.startsWith("单:") && !trimmedCmd.startsWith("单")) {
|
||||
log.warn("安全检查失败: 指令不是以'单'开头");
|
||||
log.info("公开订单提交 - 结束(拒绝)");
|
||||
log.info("======================================");
|
||||
return AjaxResult.error("只允许提交订单信息,指令必须以'单:'开头");
|
||||
}
|
||||
|
||||
// 执行指令
|
||||
List<String> result;
|
||||
try {
|
||||
log.info("开始执行订单指令...");
|
||||
result = instructionService.execute(trimmedCmd);
|
||||
log.info("订单指令执行完成");
|
||||
|
||||
// 记录执行结果
|
||||
if (result != null && !result.isEmpty()) {
|
||||
log.info("执行结果条数: {}", result.size());
|
||||
for (int i = 0; i < result.size(); i++) {
|
||||
String item = result.get(i);
|
||||
if (item != null) {
|
||||
// 检查是否包含警告标记
|
||||
if (item.contains("[炸弹]")) {
|
||||
log.warn("执行结果[{}]包含警告: {}", i, item);
|
||||
} else if (item.contains("成功")) {
|
||||
log.info("执行结果[{}]: 成功", i);
|
||||
} else {
|
||||
log.info("执行结果[{}]长度: {} 字符", i, item.length());
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
log.warn("执行结果为空");
|
||||
}
|
||||
|
||||
log.info("公开订单提交 - 结束(成功)");
|
||||
log.info("======================================");
|
||||
return AjaxResult.success(result);
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("执行订单指令时发生异常", e);
|
||||
log.error("异常类型: {}", e.getClass().getName());
|
||||
log.error("异常消息: {}", e.getMessage());
|
||||
log.info("公开订单提交 - 结束(异常)");
|
||||
log.info("======================================");
|
||||
return AjaxResult.error("订单提交失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取客户端真实IP地址
|
||||
* 考虑代理和负载均衡的情况
|
||||
*/
|
||||
private String getClientIp(HttpServletRequest request) {
|
||||
String ip = request.getHeader("X-Forwarded-For");
|
||||
if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
|
||||
ip = request.getHeader("Proxy-Client-IP");
|
||||
}
|
||||
if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
|
||||
ip = request.getHeader("WL-Proxy-Client-IP");
|
||||
}
|
||||
if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
|
||||
ip = request.getHeader("HTTP_CLIENT_IP");
|
||||
}
|
||||
if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
|
||||
ip = request.getHeader("HTTP_X_FORWARDED_FOR");
|
||||
}
|
||||
if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
|
||||
ip = request.getRemoteAddr();
|
||||
}
|
||||
// 对于通过多个代理的情况,第一个IP为客户端真实IP
|
||||
if (ip != null && ip.contains(",")) {
|
||||
ip = ip.substring(0, ip.indexOf(",")).trim();
|
||||
}
|
||||
return ip;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user