问题描述:
浏览器跨域请求由 keycloak adapter 保护的后端服务,
后端服务设置为允许跨域,
非简单请求时,预检是通过的,
无论简单请求还是非简单请求,
如果请求不携带Token的话,
虽然后端服务成功执行了,
但是,响应header中不存在Access-Control-Allow-Origin,
导致,ajax脚本仍然无法获取后端返回的数据,
此时,浏览器控制台仍然会报:
No 'Access-Control-Allow-Origin' header is present on the requested resource
的错误。
从而导致,白名单中的 URL 无法被浏览器跨域访问了。
解决办法:
找到类:org.keycloak.adapters.AuthenticatedActionsHandler
方法:corsRequest
变动说明:追加红色字体部分,意思是,不携带Token的访问,也仍然返回 cors 头信息。
protected boolean corsRequest() {
if (!deployment.isCors()) return false;
KeycloakSecurityContext securityContext = facade.getSecurityContext();
String origin = facade.getRequest().getHeader(CorsHeaders.ORIGIN);
String exposeHeaders = deployment.getCorsExposedHeaders();
if (deployment.getPolicyEnforcer() != null) {
if (exposeHeaders != null) {
exposeHeaders += ",";
} else {
exposeHeaders = "";
}
exposeHeaders += "WWW-Authenticate";
}
String requestOrigin = UriUtils.getOrigin(facade.getRequest().getURI());
log.debugv("Origin: {0} uri: {1}", origin, facade.getRequest().getURI());
if (securityContext != null && origin != null && !origin.equals(requestOrigin)) {
AccessToken token = securityContext.getToken();
Set
if (log.isDebugEnabled()) {
for (String a : allowedOrigins) log.debug(" " + a);
}
if (allowedOrigins == null || (!allowedOrigins.contains("*") && !allowedOrigins.contains(origin))) {
if (allowedOrigins == null) {
log.debugv("allowedOrigins was null in token");
} else {
log.debugv("allowedOrigins did not contain origin");
}
facade.getResponse().sendError(403);
facade.getResponse().end();
return true;
}
log.debugv("returning origin: {0}", origin);
facade.getResponse().setStatus(200);
facade.getResponse().setHeader(CorsHeaders.ACCESS_CONTROL_ALLOW_ORIGIN, origin);
facade.getResponse().setHeader(CorsHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS, "true");
if (exposeHeaders != null) {
facade.getResponse().setHeader(CorsHeaders.ACCESS_CONTROL_EXPOSE_HEADERS, exposeHeaders);
}
} else {
facade.getResponse().setHeader(CorsHeaders.ACCESS_CONTROL_ALLOW_ORIGIN, origin);
facade.getResponse().setHeader(CorsHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS, "true");
if (exposeHeaders != null) {
facade.getResponse().setHeader(CorsHeaders.ACCESS_CONTROL_EXPOSE_HEADERS, exposeHeaders);
}
log.debugv("cors validation not needed as we're not a secure session or origin header was null: {0}", facade.getRequest().getURI());
}
return false;
}
补充说明:
如果不方便修改keycloak源码的话,
也可以直接修改业务代码,
直接在响应header中追加
response.addHeader("Access-Control-Allow-Origin", "*");