为何HttpURLConnection未发送指定的Sec-Fetch-Site请求头?
问题原因与解决方案
核心原因
Sec-Fetch-Site 这类请求头是浏览器为跨站请求防护自动添加的专属头,后端通过HttpURLConnection发起的服务器内部请求,不会自动携带这类浏览器专属头,因此/prueba接口检测不到该头,返回Error。
解决方案
方案1:手动添加请求头
在/prueba2的HttpURLConnection代码中,手动添加Sec-Fetch-Site请求头,值设为same-origin:
@POST @Path("/prueba2") @Produces(MediaType.APPLICATION_JSON) public Response prueba2() { URL url; byte[] buffer = new byte[1024]; try { url = new URL("http://localhost:8080/login/rest/auth/prueba"); HttpURLConnection connection = (HttpURLConnection) url.openConnection(); connection.setRequestMethod("POST"); // 手动添加Sec-Fetch-Site请求头 connection.setRequestProperty("Sec-Fetch-Site", "same-origin"); int responseCode = connection.getResponseCode(); if (responseCode != HttpURLConnection.HTTP_OK) throw new IOException("Error: " + responseCode); try (InputStream inputStream = connection.getInputStream(); ByteArrayOutputStream output = new ByteArrayOutputStream()) { int bytesRead; while ((bytesRead = inputStream.read(buffer)) != -1) output.write(buffer, 0, bytesRead); } } catch (IOException e) { e.printStackTrace(); } // 补充原代码缺失的返回语句 return Response.ok().build(); }
方案2:调整/prueba接口的校验逻辑
服务器内部调用不属于浏览器发起的请求,无需依赖Sec-Fetch-Site头做校验,可修改接口逻辑区分浏览器请求与内部请求:
@POST @Path("/prueba") @Produces(MediaType.APPLICATION_JSON) public Response prueba(@Context HttpHeaders headers) { String message = "OK"; MultivaluedMap<String, String> rh = headers.getRequestHeaders(); // 仅对浏览器发起的请求校验Sec-Fetch-Site,内部请求跳过 String userAgent = rh.getFirst("User-Agent"); boolean isBrowserRequest = userAgent != null && (userAgent.contains("Mozilla") || userAgent.contains("Chrome") || userAgent.contains("Safari")); if (isBrowserRequest && (rh == null || rh.get("Sec-Fetch-Site") == null || !rh.get("Sec-Fetch-Site").get(0).equals("same-origin"))) message = "Error"; return Response.ok(message).build(); }
注意:原/prueba2接口代码末尾缺少返回语句,需补充类似return Response.ok().build();的逻辑,否则会出现编译错误。
内容的提问来源于stack exchange,提问作者Eduardo Roque
相关产品推荐
相关产品推荐

