Keycloak angular 不存在 'Access-Control-Allow-Origin' header

Keycloak angular No 'Access-Control-Allow-Origin' header is present

我已经将 keycloak 与 angular 应用程序集成在一起。基本上,前端和后端都在不同的 server.Backend 应用程序在 apache 运行 上 tomcat 8. 前端应用程序在 JBoss 欢迎内容文件夹上 运行。

Angular 配置

angular.element(document).ready(function ($http) {
    var keycloakAuth = new Keycloak('keycloak.json');
    auth.loggedIn = false;
    keycloakAuth.init({ onLoad: 'login-required' }).success(function () {
        keycloakAuth.loadUserInfo().success(function (userInfo) {
            console.log(userInfo);  
        });
        auth.loggedIn = true;
        auth.authz = keycloakAuth;
        auth.logoutUrl = keycloakAuth.authServerUrl + "/realms/app1/protocol/openid-connect/logout?redirect_uri=http://35.154.214.8/hrms-keycloak/index.html";
        module.factory('Auth', function() {
            return auth;
        });
        angular.bootstrap(document, ["themesApp"]);
    }).error(function () {
            window.location.reload();
        });

});
module.factory('authInterceptor', function($q, Auth) {
    return {
        request: function (config) {
            var deferred = $q.defer();
            if (Auth.authz.token) {
                Auth.authz.updateToken(5).success(function() {
                    config.headers = config.headers || {};
                    config.headers.Authorization = 'Bearer ' + Auth.authz.token;
                    deferred.resolve(config);
                }).error(function() {
                        deferred.reject('Failed to refresh token');
                    });
            }
            return deferred.promise;
        }
    };
});
module.config(["$httpProvider", function ($httpProvider)  {
    $httpProvider.interceptors.push('authInterceptor');
}]);

请求Header

Accept:*/*
Accept-Encoding:gzip, deflate
Accept-Language:en-US,en;q=0.8
Access-Control-Request-Headers:authorization
Access-Control-Request-Method:GET
Connection:keep-alive
Host:35.154.214.8:8080
Origin:http://35.154.214.8
Referer:http://35.154.214.8/accounts-keycloak/
User-Agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36

Web 控制台出错。

XMLHttpRequest cannot load http://35.154.214.8:8080/company/loadCurrencyList. Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://35.154.214.8' is therefore not allowed access.

后端的 Cors 过滤器

@Component
public class CORSFilter implements Filter {
    static Logger logger = LoggerFactory.getLogger(CORSFilter.class);

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse res,
            FilterChain chain) throws IOException, ServletException {
        HttpServletResponse response = (HttpServletResponse) res;
        response.setHeader("Access-Control-Allow-Origin", "*");
        response.setHeader("Access-Control-Allow-Methods", "*");
        response.setHeader("Access-Control-Max-Age", "3600");
        response.setHeader("Access-Control-Allow-Headers", "*");
        chain.doFilter(request, response);
    }

    public void destroy() {
    }
}

我与 KeyCloak 和 CORS 斗争了大约两周,这是我的解决方案(针对 keycloak 3.2.1):

都是关于配置KeyCloak服务器的。 似乎是,你的领域的 WebOrigin 需要是

*
只有一个来源“*”。

这就是我所需要的。

如果您将服务器输入为 WebOrigin,麻烦就来了。 当你在JavaScript中调用keycloak.init时,keycloak不会生成CORSheaders,所以你必须手动配置它们,并且一旦这样做,然后调用keycloak.getUserInfo成功初始化 - 你得到双 CORS headers,这是不允许的。

在 keycloak 邮件列表的某个深处指出,您需要在 keycloak.json 中设置 enable-cors=true,但在 keycloak.gitbooks.io 上没有任何相关内容。所以好像不是真的。

他们在描述 JavaScript 和 Node.Js 适配器时也没有提到 CORS,我不知道为什么,似乎一点也不重要。

这似乎也是,你不应该触摸 WildFly 配置来提供 CORS headers。

此外,OIDC 中的 CORS 是一个特殊的 KeyCloak 功能(而不是错误)。

希望这个回答对您有所帮助。

您给出了您自己的问题的答案,在 client-level(不是在 Realm-level!)添加 WebOrigin 作为 *,这对您有用,但在我自己的情况下它没有。实际上,删除 * 对我来说是个窍门,因为 KC 两次发送 CORS headers - 删除它,将其剥离一次...

感谢您的回答,我幸运地找到了问题的答案...

我们一致认为,KC 文档至少非常糟糕。

它是为傻瓜写的,但是......我们不是傻瓜,主题也不是......

它没有解释技术细节。例如,端点的响应是什么。在网上搜索(两周)确实有所帮助 - 但为什么没有在文档中列出?

一个例子。但是我有几个...

我们可以帮忙处理文档吗?

请务必注意,将您的网络来源设置为“*”会打开一个巨大的安全漏洞。它允许来自任何域的任何脚本在该用户的浏览器中代表该用户发出请求。

每当您发现自己以这种方式禁用安全功能时,您需要考虑为什么存在该安全功能。

参见 8.1.1 of the Keycloak docs

中的“Web 起源”

在使用 Angular 6、Spring Boot for REST Web Services 和 Keycloak 时遇到同样的问题。

密钥斗篷地址:KEYCLOAK
Angular6个应用地址:ANGULAR_APP
两个使用 Keycloak 和 Spring 自动配置保护的 REST WS:AA、BB

流为:Angular应用程序请求(GET)AA,AA 请求(GET)BB

使用 XMLHttpRequest 错误类似于: 无法加载 AA。对预检请求的响应未通过访问控制检查:请求的资源上不存在 'Access-Control-Allow-Origin' header。因此不允许访问来源 'ANGULAR_APP'。

使用来自 Angular 的 Observable 是: 加载 AA 失败:从 'BB' 重定向到 'KEYCLOAK' 已被 CORS 策略阻止:请求的资源上不存在 'Access-Control-Allow-Origin' header。因此不允许访问来源 'ANGULAR'。

尝试使用网络来源:* 没有解决方案

从来不知道为什么 Keycloak 会做导致问题的重定向

当我将服务 AA 中的安全性从 Keycloak + 自动配置切换到 Keycloak + Spring 安全性时,问题神奇地消失了:https://developers.redhat.com/blog/2017/05/25/easily-secure-your-spring-boot-applications-with-keycloak/

因此失去了很多天的睡眠。留下这个以防有人遇到类似的事情。

对我有用的解决方案是设置 Web 起源 URL(我的客户,而不是领域),例如:http://localhost:3000/http://localhost:3000(注意缺少/ 最后)。这样您就不会使用 * 向所有 URLS 开放它。

我遇到了同样的问题,在我的情况下,这是由于在 keycloak js 适配器创建中使用了一个选项对象引起的,其中 auth 服务器的 url 被错误地设置为 http 而不是 https:

const keycloak = Keycloak({
    url: 'http://my-keycloak-auth-server/auth',
    realm: 'myRealm',
    clientId: 'myClient'
});

但正确的是

const keycloak = Keycloak({
    url: 'https://my-keycloak-auth-server/auth',
    realm: 'myRealm',
    clientId: 'myClient'
});

我遇到了同样的问题,并且(至少)对于 Keycloak 服务器版本 8.0.1,您可以添加一个“+”作为 'Web Origins' 字段的输入,这似乎是最佳选择。

“+”效果应该与添加(见下面的屏幕截图)'http://localhost:4200' 作为 'Web Origins' 条目相同。

'Web Origins' 字段工具提示是这样说的:

“允许的 CORS 来源。要允许“有效重定向 URI”的所有来源,请添加“+”。要允许所有来源,请添加“*”。“(请参阅屏幕截图下)

我有同样的 CORS 错误。 KeyCloak 的新手。尝试将 web-origin 设置为“*”、“+”和特定的 urls。没有任何效果。直到我将客户端设置中的 'Access Type' 更改为 public。然后将 web-origin 设置为特定 url 和 + 的两个选项都起作用了。由于设置为*不安全,所以没有尝试。

当访问类型设置为机密时,它又开始出现 CORS 错误。我正在尝试使用 PKCE(代码流)进行授权流。

使用版本 10.0.2。

有效设置的屏幕截图:

我在初始化时添加了这一行...

this.keycloakAuth.init({ onLoad: 'login-required', 流量:'implicit' })

这是一个比较老的问题,但我还是回答了。它可能会帮助某人。在 keycloak 管理页面中,转到 clients->your client。您可以在下面看到一个名为 web origins 的字段。在此处输入 url,您的问题将得到解决。

虽然在 Angular 中没有,但在 keycloak-js 中遇到了类似的错误:我可以使用文档中的代码成功登录:

keycloak.init({
  onLoad: 'login-required',
}).then(function(authenticated) {
  alert(authenticated ? 'authenticated' : 'not authenticated');
}).catch(function() {
  alert('failed to initialize');
});

但是连续调用(keycloak.loadUserProfile() 在我的例子中,调用 account 端点)将以 CORS 错误结束。

后来我发现我以错误的方式操纵了我的代码,以至于连续的调用出现了 init 的竞争条件!事后看来很明显但是..

TLDR;如果您在 init 调用完成之前调用 keycloak 端点,响应将缺少 CORS headers 并且您将收到 CORS 错误!这只是意味着您未通过身份验证。

我从 keycloak 12 升级到 15 后遇到了类似的问题。 还升级 keycloak.js 文件后,在此处找到:https://your-keycloak-server/auth/js/keycloak.js 在我的 Web 应用程序中,它再次开始工作。