Ver código fonte

fix 缓存响应头

zoujiajian 1 dia atrás
pai
commit
5b22d09c70

+ 5 - 2
netflix-service/src/main/java/com/cyksj/service/order/impl/OrderDonServiceImpl.java

@@ -1678,9 +1678,12 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 
 	@Override
 	public OrderDetailView getDetail(Long orderId, Long userId) {
+        if (userId == null || userId <= 0 || orderId == null || orderId <= 0) {
+            throw BusinessRuntimeException.getInstance("订单不存在或无权查看");
+        }
 		OrderDon orderDon = this.getById(orderId);
-		if (orderDon == null) {
-			throw BusinessRuntimeException.getInstance("订单不存在");
+		if (orderDon == null || !userId.equals(orderDon.getUserId())) {
+			throw BusinessRuntimeException.getInstance("订单不存在或无权查看");
 		}
 		MapBuilder builder = MapUtils.builder()
 				.field(OrderDonView::getId, orderId)

+ 88 - 0
netflix-web/src/main/java/com/cyksj/security/ApiCacheProtectionFilter.java

@@ -0,0 +1,88 @@
+package com.cyksj.security;
+
+import org.springframework.core.Ordered;
+import org.springframework.core.annotation.Order;
+import org.springframework.stereotype.Component;
+import org.springframework.web.filter.OncePerRequestFilter;
+
+import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpServletResponseWrapper;
+import java.io.IOException;
+import java.util.regex.Pattern;
+
+/** Sensitive API responses must never become shared CDN cache entries. */
+@Component
+@Order(Ordered.HIGHEST_PRECEDENCE)
+public class ApiCacheProtectionFilter extends OncePerRequestFilter {
+    private static final Pattern MATRIX_PATH = Pattern.compile(";|%(?:25)*3b", Pattern.CASE_INSENSITIVE);
+
+    private static final Pattern SENSITIVE_PATH = Pattern.compile(
+            "^/(?:manage|manager|auth|yhShop|applets/(?:user|order|register)|applet/coupon)(?:$|[/;.%])");
+    private static final Pattern STATIC_SUFFIX = Pattern.compile(
+            "\\.(?:css|js|png|jpg|jpeg|gif|svg|ico|woff2?|ttf|map)$", Pattern.CASE_INSENSITIVE);
+
+    @Override
+    protected boolean shouldNotFilter(HttpServletRequest request) {
+        String uri = request.getRequestURI();
+        String context = request.getContextPath();
+        if (uri != null && context != null && !context.isEmpty() && uri.startsWith(context)) {
+            uri = uri.substring(context.length());
+        }
+        String servletPath = request.getServletPath();
+        return !(uri != null && SENSITIVE_PATH.matcher(uri).find())
+                && !(servletPath != null && SENSITIVE_PATH.matcher(servletPath).find());
+    }
+
+    @Override
+    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
+                                    FilterChain chain) throws ServletException, IOException {
+        HttpServletResponseWrapper protectedResponse = new HttpServletResponseWrapper(response) {
+            private String protectedValue(String name, String value) {
+                if ("Cache-Control".equalsIgnoreCase(name)) return "no-store, private, max-age=0";
+                if ("Pragma".equalsIgnoreCase(name)) return "no-cache";
+                if ("Expires".equalsIgnoreCase(name)) return "0";
+                return value;
+            }
+            @Override public void setHeader(String name, String value) {
+                super.setHeader(name, protectedValue(name, value));
+            }
+            @Override public void addHeader(String name, String value) {
+                if ("Cache-Control".equalsIgnoreCase(name) || "Pragma".equalsIgnoreCase(name)
+                        || "Expires".equalsIgnoreCase(name)) setHeader(name, value);
+                else super.addHeader(name, value);
+            }
+            @Override public void setDateHeader(String name, long date) {
+                if ("Expires".equalsIgnoreCase(name)) setHeader(name, "0");
+                else super.setDateHeader(name, date);
+            }
+            @Override public void addDateHeader(String name, long date) {
+                if ("Expires".equalsIgnoreCase(name)) setHeader(name, "0");
+                else super.addDateHeader(name, date);
+            }
+            @Override public void reset() {
+                super.reset();
+                noCache(this);
+            }
+        };
+        noCache(protectedResponse);
+        // Inspect the raw path, not query strings; never normalize an ambiguous path into an API call.
+        String uri = request.getRequestURI();
+        if (uri != null && (MATRIX_PATH.matcher(uri).find() || STATIC_SUFFIX.matcher(uri).find())) {
+            protectedResponse.setStatus(HttpServletResponse.SC_BAD_REQUEST);
+            protectedResponse.setContentType("application/json;charset=UTF-8");
+            protectedResponse.getWriter().write("{\"code\":100002,\"msg\":\"Invalid request path\",\"flag\":false}");
+            return;
+        }
+        chain.doFilter(request, protectedResponse);
+    }
+
+    private static void noCache(HttpServletResponse response) {
+        response.setHeader("Cache-Control", "no-store, private, max-age=0");
+        response.setHeader("Pragma", "no-cache");
+        response.setHeader("Expires", "0");
+        response.setHeader("X-Content-Type-Options", "nosniff");
+    }
+}

+ 5 - 3
netflix-web/src/main/java/com/cyksj/web/controller/payment/OrderController.java

@@ -538,7 +538,7 @@ public class OrderController {
      */
     @GetMapping("/get/{orderId}")
     public Result<OrderDetailView> detail(@PathVariable Long orderId, Boolean isNoLogin) {
-        Long userId = StpUserUtil.getUserIdAfterLogin();
+        Long userId = StpUserUtil.getLoginIdAsLong();
 
         OrderDetailView detail = orderDonService.getDetail(orderId, userId);
 
@@ -557,11 +557,12 @@ public class OrderController {
 
     @GetMapping("/get/order/status/{orderId}")
     public Result<OrderDonSearchView> getOrderStatusById(@PathVariable Long orderId) {
+        long userId = StpUserUtil.getLoginIdAsLong();
         if (orderId < 1) {
             throw BusinessRuntimeException.getInstance("订单不存在");
         }
         OrderDonSearchView orderDonView = beanSearcher.searchFirst(OrderDonSearchView.class, MapUtils.builder()
-                .put("orderId", String.format("where id = %s", orderId))
+                .put("orderId", String.format("where id = %s and user_id = %s", orderId, userId))
                 .build());
         if (orderDonView == null) {
             throw BusinessRuntimeException.getInstance("订单不存在");
@@ -599,11 +600,12 @@ public class OrderController {
      */
     @GetMapping("/get/upgrade/order/status/{orderId}")
     public Result<UpgradeOrderDonSearchView> getUpgradeOrderStatusById(@PathVariable Long orderId) {
+        long userId = StpUserUtil.getLoginIdAsLong();
         if (orderId < 1) {
             throw BusinessRuntimeException.getInstance("订单不存在");
         }
         UpgradeOrderDonSearchView orderDonView = beanSearcher.searchFirst(UpgradeOrderDonSearchView.class, MapUtils.builder()
-                .put("orderId", String.format("where id = %s", orderId))
+                .put("orderId", String.format("where id = %s and user_id = %s", orderId, userId))
                 .build());
         if (orderDonView == null) {
             throw BusinessRuntimeException.getInstance("订单不存在");