AJAX cors 问题:预检响应中的 Access-Control-Allow-Headers 不允许请求标头字段 access-control-allow-credentials
Posted
技术标签:
【中文标题】AJAX cors 问题:预检响应中的 Access-Control-Allow-Headers 不允许请求标头字段 access-control-allow-credentials【英文标题】:AJAX cors issue : Request header field access-control-allow-credentials is not allowed by Access-Control-Allow-Headers in preflight response 【发布时间】:2021-06-06 02:04:35 【问题描述】:我正在从主机(http://abc.com.au) 向运行在主机 http://localhost:8081 上的 Spring Cloud API 网关发送一个 ajax 请求。
jquery AJAX 请求代码。
SimplifiedAdoptionBulkUpload.jsp
setCookie("username", 'abc', 30);
$.ajax(
type: "POST",
enctype: 'multipart/form-data',
url: "http://localhost:8081/api/v1/users/bulkUpload",
xhrFields:
withCredentials: true
,
data: newData,
processData: false,
contentType: false,
crossDomain: true,
cache: false,
timeout: 600000,
success: function (data)
.....
,
error: function (e)
$('#btnSubmit').prop("disabled", false);
$('#txtMessage').text('Error Occured');
,
beforeSend: function (xhr)
xhr.setRequestHeader('Authorization', 'Bearer ' + token);
xhr.setRequestHeader('Access-Control-Allow-Credentials', 'true');
xhr.setRequestHeader('Access-Control-Allow-Headers', "Origin,Cookie,X-Requested-With, Content-Type, Accept, Authorization");
$('body').addClass("loading");
);
spring 云网关 cors 配置。
@Configuration
public class PreFlightCorsConfiguration
private static final String ALLOWED_HEADERS = "Origin,Cookie,X-Requested-With, Content-Type, Accept, Authorization";
private static final String ALLOWED_METHODS = "*";
private static final String ALLOWED_ORIGIN = "http://abc.com.au";
private static final String ALLOWED_EXPOSE = "*";
private static final String MAX_AGE = "3600";
@Bean
public WebFilter corsFilter()
return (ServerWebExchange ctx, WebFilterChain chain) ->
ServerHttpRequest request = ctx.getRequest();
if (CorsUtils.isCorsRequest(request))
ServerHttpResponse response = ctx.getResponse();
HttpHeaders headers = response.getHeaders();
headers.set("Access-Control-Allow-Origin", ALLOWED_ORIGIN);
headers.add("Access-Control-Allow-Methods", ALLOWED_METHODS);
headers.add("Access-Control-Max-Age", MAX_AGE);
headers.add("Access-Control-Allow-Headers", ALLOWED_HEADERS);
headers.add("Access-Control-Expose-Headers", ALLOWED_EXPOSE);
headers.add("Access-Control-Allow-Credentials", "true");
if (request.getMethod() == HttpMethod.OPTIONS)
response.setStatusCode(HttpStatus.OK);
return Mono.empty();
return chain.filter(ctx);
;
我在 chrome 控制台中收到以下错误。
SimplifiedAdoptionBulkUpload:1 访问 XMLHttpRequest at 来自原点的“http://localhost:8081/api/v1/users/bulkUpload” “http://abc.com.au”已被 CORS 策略阻止:请求标头 字段 access-control-allow-credentials 不允许 预检响应中的 Access-Control-Allow-Headers。
更新:
我从 ajax 请求中删除了这一行。
xhr.setRequestHeader('Access-Control-Request-Headers', "Origin,Cookie,X-Requested-With, Content-Type, Accept, Authorization");
我在 jsp 和 servlet 过滤器中为 cookie 设置了两个 cookie(accces_token,refresh_token)。
public class AdminSecurityFilter implements Filter
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException
boolean error = false;
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
request.setCharacterEncoding("UTF-8");
if(authenticated)
String accessToken = getUserAccessToken(userStr,passStr);
if(!accessToken.isEmpty())
Cookie cookie = new Cookie("access_token", accessToken);
cookie.setPath("/");
//cookie.setHttpOnly(true);
//cookie.setDomain("localhost");
//TODO: When in production must do cookie.setSecure(true);
cookie.setMaxAge(3600);
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("Access-Control-Allow-Origin", "http://localhost:8081");
response.addCookie(cookie);
if(!refreshToken.isEmpty())
Cookie cookie = new Cookie("refresh_token", refreshToken);
cookie.setPath("/");
//cookie.setHttpOnly(true);
//cookie.setDomain("localhost");
//TODO: When in production must do cookie.setSecure(true);
cookie.setMaxAge(10000);
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("Access-Control-Allow-Origin", "http://localhost:8081");
response.addCookie(cookie);
在 jsp 文件中我也使用 jquery 设置值 cookie。
function setCookie(cname,cvalue,exdays)
var d = new Date();
d.setTime(d.getTime() + (exdays*24*60*60*1000));
var expires = "expires=" + d.toGMTString();
document.cookie = cname + "=" + cvalue + ";" + expires + ";path=/";
setCookie("username", 'Nirangaa', 30);
但这些 cookie 值(用户名、refresh_token、access_token)在 Spring Cloud Gateway 的标头中缺失。 为什么 AJAX 请求没有将附加在 post 请求中的 cookie 值发送到 apigteway 端。 @T.J。如果您能解释为什么会发生这种情况,Crowder 将不胜感激
@Component
public class AccessTokenCheckingGlobalFilterPre extends AbstractGatewayFilterFactory<AccessTokenCheckingGlobalFilterPre.Config>
public AccessTokenCheckingGlobalFilterPre()
super(AccessTokenCheckingGlobalFilterPre.Config.class);
@Override
public GatewayFilter apply(AccessTokenCheckingGlobalFilterPre.Config config)
return (exchange, chain) ->
Route route = exchange.getAttribute(ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR);
ServerHttpRequest request = null;
if (route != null)
request = exchange.getRequest();
**//[Host:"localhost:8081", Connection:"keep-alive", Content-Length:"7391", Accept:"*/*", Access-Control-Allow-Credentials:"true", Authorization:"Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOlsiamFjcGx1c19yZXNvdXJjZSJdLCJFeHBpcmVzSW4iOjM1OTksInVzZXJfbmFtZSI6Im5zYW5kYXJ1d2FAd2lsZXkuY29tIiwic2NvcGUiOlsiUkVBRCxXUklURSJdLCJleHAiOjE2MTUxOTQwNjIsInVzZXJOYW1lIjoibnNhbmRhcnV3YUB3aWxleS5jb20iLCJhdXRob3JpdGllcyI6WyJST0xFX0FkbWluaXN0cmF0b3IiLCJST0xFX3RlYWNoZXIiLCJST0xFX3NjaGFkbWluIiwiUk9MRV9zdHVkZW50Il0sImp0aSI6IjBkMjQ3ZjJkLTg0NjgtNDUwYS04NjI3LTAzOGI4ZmRlZjQ2MCIsImNsaWVudF9pZCI6ImphY3BsdXMifQ.GT0ayX01TO0fNY834n5_vXsqmt2P3s2C7hfMH-_FLvsNT-p9uIj5i0U66ZdouDUaL9xu1iy4wdfxLexfvilwnO10fTX5I0U7DHqHQetLUwCJOhET0hN-PyFcJRe7k3C3BUe8f7iuDd6Y4VbLCYTTpp4KSjWcS5fv-BTrvTvktwtkq5oFK2iCtPS6JwqPcFsvt2MYNi9UlGFeik_a-iyuTTa7xf7VgL2XFnGqcu3bOTUNxj4AhG91YL5har3OnFTbZnKFxVWykEz7MJFSXzmhmSS5rNYAbC5FBg65VFmzD0j9G4j1xPODxmLEEeE2Qj5FSe6VTnEZIiFHTLd27IuYyA", User-Agent:"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (Khtml, like Gecko) Chrome/75.0.3770.142 Safari/537.36", Origin:"http://abc.com.au", Content-Type:"multipart/form-data; boundary=----WebKitFormBoundaryV5bORQSNHAa3kxFR", Referer:"http://admin.jacplus.com.au/admin/SimplifiedAdoptionBulkUpload", Accept-Encoding:"gzip, deflate, br", Accept-Language:"en-US,en;q=0.9"]**
HttpHeaders headers = request.getHeaders();
List<String> authorizationHeader = headers.get(HttpHeaders.AUTHORIZATION);
String value = authorizationHeader.get(0);
MultiValueMap<String, HttpCookie> cookies = request.getCookies(); /// nulll
return chain.filter(exchange.mutate().request(request).build());
;
【问题讨论】:
【参考方案1】:Access-Control-Allow-XYZ
标头是 响应 标头,而不是请求标头。从您的$.ajax
电话中删除它们。您可能需要 Access-Control-Request-XYZ
标头,例如:
xhr.setRequestHeader('Access-Control-Request-Headers', "Origin,Cookie,X-Requested-With, Content-Type, Accept, Authorization");
// −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−^^^^^^^
这是一个有效的请求标头。 (不过,CORS spec 中没有列出 Access-Control-Request-Credentials
标头,因此应该删除添加 Access-Control-Allow-Credentials
标头的另一行。)
更一般地说,请求中的任何标头都必须由您的响应的 Access-Control-Allow-Headers
值允许,而您的响应中没有。但解决方法是将其从请求中删除,而不是将其添加到 Access-Control-Allow-Headers
值中。
另见:CORS specification
【讨论】:
我更新了问题。你能看看吗? @NirangaSandaruwan - 在您的编辑中,您说 “我从 ajax 请求中删除了这一行。xhr.setRequestHeader('Access-Control-Request-Headers', "Origin,Cookie,X-Requested-With, Content-Type, Accept, Authorization");
” 该行不在 ajax 请求中。 ajax 请求设置为Access-Control-Allow-Headers
,而不是Access-Control-Request-Headers
。您可能需要Access-Control-Request-Headers
。但后来你开始谈论饼干。问题是因为您的 CORS 设置错误而被 SOP 拒绝。我就是这么回答的。
我更正了 ajax 请求标头。您知道 cookie 值没有与 ajax 请求一起发送到 apigatewat 端的原因吗?我在 apigateway 端得到了这些标头。[Host:"localhost:8081", Connection:"keep-alive", Content-Length:"7391", Accept:"/", Access-Control- Allow-Credentials:"true", Authorization:"Bearer ey_FLvsNT-p", User-Agent:"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36", Origin:"abc.com.au", Content-Type:"multip", Referer:"http:///abc/", Accept-Encoding:"gzip, deflate, br", Accept-Language:"en-US,en ;q=0.9"]以上是关于AJAX cors 问题:预检响应中的 Access-Control-Allow-Headers 不允许请求标头字段 access-control-allow-credentials的主要内容,如果未能解决你的问题,请参考以下文章
来自 ASP NET Web API 的 CORS 阻止 Ajax POST 调用 - 对预检请求的响应未通过访问控制检查
预检请求没问题,然后,经过身份验证,响应不包含允许 cors 标头
Yii2 和 reactjs CORS 过滤器给出错误:预检响应具有无效的 HTTP 状态代码 401