Js 跨域CORS报错 Response for preflight has invalid HTTP status code 405

调用接口遇到Response for preflight has invalid HTTP status code 405这样的错误,是使用PUT方式提交请求接口。Content-Type设置为application/json,JS代码如下:

$.ajax({
    type: "PUT",
    url: "http://172.16.200.84:8977/Messages?sessionId=ee876bfbtest",
    data:data,
    beforeSend: function (XMLHttpRequest) {
        XMLHttpRequest.setRequestHeader("Content-Type", "application/json");
    },
    success: function (data, textStatus) {
        alert(data);
    }
});
 

尝试解决

项目使用的是WebApi,按照网上的比较通用的方法是直接在项目的webconfig里配置如下节点:

<system.webServer>
<httpProtocol>
  <customHeaders>
    <add name="Access-Control-Allow-Origin" value="*" />
    <add name="Access-Control-Allow-Headers" value="Content-Type" />
    <add name="Access-Control-Allow-Methods" value="GET, POST, PUT, DELETE, OPTIONS" />
  </customHeaders>
</httpProtocol>
…

 

当然配置后依然没有成功,接下来再试一次还是失败。还是原来的错误。

6360516868798237507944054

继续努力

后来注意到失败的请求Method是OPTIONS,奇怪了,明明是PUT请求,怎么出现了Method为OPTIONS的请求呢?还要在Global.asax里加上如下处理:

protected void Application_BeginRequest()
{
  if (Request.Headers.AllKeys.Contains("Origin") && Request.HttpMethod == "OPTIONS")
  {
    Response.End();
  }
}
 

原因

再试一次,成功了。但是看记录,会有两个请求,一个是OPTIONS请求返回200成功,一个是自己的PUT请求,返回200成功。那么这个OPTIONS请求到底是什么?百度了一下得到了答案:

 

Preflighted Requests(预检请求)

Preflighted Requests是CORS中一种透明服务器验证机制。预检请求首先需要向另外一个域名的资源发送一个 HTTP OPTIONS 请求头,其目的就是为了判断实际发送的请求是否是安全的。

下面的2种情况需要进行预检:

1、简单请求,比如使用Content-Type 为 application/xml 或 text/xml 的 POST 请求;

2、中设置自定义头,比如 X-JSON、X-MENGXIANHUI 等。

原来如此,在js发起PUT请求的时候,头部设置了XMLHttpRequest.setRequestHeader("Content-Type", "application/json"),所以请求的时候会多出一个OPTIONS,如果去掉这个头,就不会多出这次请求了。

什么是CORS

CORS_principle

CORS 流程

prelight1

补充

当然为了安全起见,可以不配置Web.Config,而是自己定义一个ActionAllowOriginAttribute,继承于ActionFilterAttribute,然后对需要跨域访问的接口加上标签就行了,主要是在header加上如下内容:

response.AddHeader("Access-Control-Allow-Origin", "*");
response.AddHeader("Access-Control-Allow-Methods", "PUT,GET,POST,OPTIONS");
response.AddHeader("Access-Control-Allow-Headers", "X-Requested-With, Content-Type, X-File-Name");

转载于:https://www.cnblogs.com/SilenceTom/p/6697484.html

### 配置CORS中的白名单 资源共享(Cross-Origin Resource Sharing, CORS)是一种浏览器机制,它允许某些资源由位于不同名下的网页加载。为了增强安全性并控制哪些外部站点可以访问特定资源,在实际开发中通常会配置受信任的白名单。 #### Java 中配置 CORS 的方法 在 Java 应用程序中可以通过多种方式实现 CORS 白名单的配置。以下是几种常见的方法: 1. **基于过滤器的方式** 使用 `Filter` 类拦截请求并对响应头进行修改,从而设置允许的来源列表。 ```java import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletResponse; import java.io.IOException; public class CorsFilter implements Filter { @Override public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { HttpServletResponse response = (HttpServletResponse) res; response.setHeader("Access-Control-Allow-Origin", "https://example.com"); // 设置白名单 response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE"); response.setHeader("Access-Control-Max-Age", "3600"); response.setHeader("Access-Control-Allow-Headers", "Content-Type,X-Requested-With"); chain.doFilter(req, res); } @Override public void init(FilterConfig filterConfig) {} @Override public void destroy() {} } ``` 上述代码片段展示了如何通过自定义过滤器来设置 CORS 头部信息,并指定允许的来源地址[^1]。 2. **Spring Boot 中的全局配置** 如果项目使用的是 Spring Boot,则可以通过创建一个 WebMvcConfigurer 来集中管理 CORS 策略。 ```java import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.CorsRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Configuration public class WebConfig { @Bean public WebMvcConfigurer corsConfigurer() { return new WebMvcConfigurer() { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/api/**") // 对 /api 下的所有接口生效 .allowedOrigins("https://example.com", "https://anotherdomain.com") // 设置多个白名单 .allowedMethods("GET", "POST", "PUT", "DELETE") .maxAge(3600); // 缓存时间 } }; } } ``` 这种方式更加灵活且易于维护,适合大型应用程序。 3. **Keycloak Adapter 中的 CORS 配置** 当涉及到 Keycloak 认证时,可能需要调整其默认行为以支持更多的场景。例如,针对 Keycloak Java Adapter 可以重写部分逻辑处理未认证请求的情况。 修改 `AuthenticatedActionsHandler` 类的相关函数即可满足需求[^2]: ```java protected boolean isCorsPreflight(HttpServletRequest request){ String method = request.getMethod(); if (!"OPTIONS".equalsIgnoreCase(method)) { return false; } String accessControlRequestMethod = request.getHeader(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD); if (accessControlRequestMethod == null || !isAllowedMethod(accessControlRequestMethod)){ throw new CorsErrorResponseException(cors(), HttpMethod.OPTIONS.name(), OAuthErrorException.INVALID_REQUEST, "Invalid CORS preflight configuration for '" + request.getRequestURI() + "' with method '" + accessControlRequestMethod + "'"); } return true; } ``` 4. **环境变量或配置文件设定** 在一些微服务架构下,推荐将这些敏感数据存储到独立的 `.env` 文件或者类似的资源配置中心里统一管理。下面是一个简单的例子展示如何读取预设好的可信 URL 列表[^3]: ```properties env_type=1 origin_prod=https://xxxx.xxxxx12.cn,\ https://xxxx.xxxx123.cn,\ https://xxxx.xxxxx13245.cn,\ https://xxx.xxxxxxxxx1234.cn ``` 同样也可以利用 spring boot 提供的功能自动注入上述属性值至对应的 bean 定义当中去简化编码工作量。 --- #### 总结 无论采用哪种方式进行 CORS 白名单配置都需要充分考虑业务的实际需求以及潜在的安全隐患。合理规划 API 接口权限范围的同时也要注意保持良好的用户体验平衡两者之间的关系至关重要。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值