Переглянути джерело

fix 兑换码详情漏洞

zoujiajian 16 годин тому
батько
коміт
766db7409f

+ 3 - 1
netflix-dao/src/main/java/com/cyksj/model/views/ExchangeCodeDetailView.java

@@ -3,6 +3,7 @@ package com.cyksj.model.views;
 import com.ejlchina.searcher.bean.DbField;
 import com.ejlchina.searcher.bean.DbIgnore;
 import com.ejlchina.searcher.bean.SearchBean;
+import com.fasterxml.jackson.annotation.JsonIgnore;
 import lombok.Getter;
 import lombok.Setter;
 
@@ -19,7 +20,8 @@ import java.util.List;
 @Setter
 @SearchBean(tables = "exchange_code ec")
 public class ExchangeCodeDetailView {
-	@DbField("ec.code")
+    @JsonIgnore
+    @DbField("ec.code")
 	private String code;
 
 	@DbField("ec.sku_ids")

+ 23 - 8
netflix-web/src/main/java/com/cyksj/web/controller/user/UserController.java

@@ -3,7 +3,6 @@ package com.cyksj.web.controller.user;
 import cn.hutool.core.date.DateTime;
 import cn.hutool.core.date.DateUtil;
 import cn.hutool.core.util.StrUtil;
-import cn.hutool.core.util.URLUtil;
 import cn.hutool.extra.servlet.ServletUtil;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.cyksj.common.annotation.NoSubmit;
@@ -15,6 +14,7 @@ import com.cyksj.enums.GatewayResponse;
 import com.cyksj.mapper.*;
 import com.cyksj.mapper.manage.coupon.CouponUserMapper;
 import com.cyksj.mapper.manage.distribute.*;
+import com.cyksj.mapper.manage.exchange.ExchangeCodeMapper;
 import com.cyksj.mapper.mirrorshop.UserMirrorShopMapper;
 import com.cyksj.model.dto.UserWhoami;
 import com.cyksj.model.entity.*;
@@ -62,6 +62,8 @@ public class UserController {
 
     private final ExchangeCodeService exchangeCodeService;
 
+    private final ExchangeCodeMapper exchangeCodeMapper;
+
     private final CouponUserMapper couponUserMapper;
 
     private final OrderDonMapper orderDonMapper;
@@ -128,15 +130,28 @@ public class UserController {
      * 车票兑换码详情
      */
     @GetMapping("/get/ticket/code/detail")
-    public Result<ExchangeCodeDetailView> getTicketCodeDetail(String code) throws Exception {
-        code = URLUtil.decode(code);
-        ExchangeCodeDetailView exchangeCodeDetailView = beanSearcher.searchFirst(ExchangeCodeDetailView.class, MapUtils.flatBuilder(request.getParameterMap()).field(ExchangeCodeDetailView::getCode, code).build());
-        if (exchangeCodeDetailView == null) {
+    public Result<ExchangeCodeDetailView> getTicketCodeDetail(
+            @RequestParam(value = "code", required = false) String code) throws Exception {
+        // Spring already decodes query parameters. Never decode a second time.
+        // Accept legacy underscore/hyphen codes, but reject whitespace and encoded payloads.
+        if (code == null || !code.matches("[A-Za-z0-9_-]{1,256}")) {
+            throw BusinessRuntimeException.getInstance("错误兑换码");
+        }
+        // Do not pass request parameters to BeanSearcher: all filters are server-owned.
+        ExchangeCode record = exchangeCodeMapper.selectOne(Wrappers.lambdaQuery(ExchangeCode.class)
+                .eq(ExchangeCode::getCode, code).last("LIMIT 1"));
+        // Also reject case-insensitive matches from a *_ci database collation.
+        if (record == null || !code.equals(record.getCode())) {
             throw BusinessRuntimeException.getInstance("错误兑换码");
         }
-        List<Long> skuIds = Jsons.parseList(exchangeCodeDetailView.getSkuIds(), Long.class);
-        exchangeCodeDetailView.setSkuDetails(skuMapper.selectExchangeTitleSkus(skuIds));
-        return GatewayResponse.SUCCESS.newBuilder().toResult(exchangeCodeDetailView);
+        ExchangeCodeDetailView detail = new ExchangeCodeDetailView();
+        detail.setSkuIds(record.getSkuIds());
+        detail.setUseStatus(record.getUseStatus());
+        detail.setUseTime(record.getUseTime());
+        detail.setCodeType(record.getCodeType());
+        List<Long> skuIds = Jsons.parseList(record.getSkuIds(), Long.class);
+        detail.setSkuDetails(skuMapper.selectExchangeTitleSkus(skuIds));
+        return GatewayResponse.SUCCESS.newBuilder().toResult(detail);
     }
 
     /**