解决 keycloak java adapter cors 白名单 URL 不携带有效 Token 无法跨域访问的问题

问题描述:

浏览器跨域请求由 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 allowedOrigins = token.getAllowedOrigins();

            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", "*");

 

 

转载于:https://my.oschina.net/u/4058864/blog/2995509

你可能感兴趣的:(解决 keycloak java adapter cors 白名单 URL 不携带有效 Token 无法跨域访问的问题)