You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何解决Quarkus OIDC Cookie过期与Ajax请求CORS失败问题?

问题解决:Quarkus OIDC + Primefaces Ajax过期重定向CORS及401问题

环境与配置

基于Quarkus + Primefaces(服务端渲染)的Web应用,已集成Quarkus OIDC,核心配置如下:

quarkus.oidc.auth-server-url=${oidc_serverUrl}
quarkus.oidc.client-id=my-jsf-app
quarkus.oidc.application-type=web-app
quarkus.oidc.credentials.secret=${oidc_secret}
quarkus.http.auth.permission.authenticated.paths=/secure/*
quarkus.http.auth.permission.authenticated.policy=authenticated
quarkus.oidc.authentication.cookie-same-site=lax
quarkus.oidc.tls.verification=none
# 仅认证用户可发起登出
quarkus.oidc.logout.path=/secure/logout
# 登出后跳转至首页
quarkus.oidc.logout.post-logout-path=/secure/user/home.xhtml
quarkus.oidc.token-state-manager.split-tokens=true
quarkus.oidc.token-state-manager.strategy=id-refresh-tokens
quarkus.oidc.authentication.cookie-path=/secure/

问题现象

当浏览器端的q_session和q_session_rt Cookie过期后,首个Ajax请求会被重定向至OIDC端点进行重新认证,触发CORS报错:

Access to XMLHttpRequest at 'https://keycloak.myapp.com/auth/realms/my-app/protocol/openid-connect/auth?response_type=code&client_id=my-jsf-app&scope=openid&redirect_uri=https%3A%2F%2Fdev.myapp.com%2Fsecure%2Fuser%2FaccountWizard.xhtml&state=b8afe3c2-0302-4592-a2b4-ad67997fad32' (redirected from 'https://dev.myapp.com/secure/user/accountWizard.xhtml?jfwid=cc9f2') from origin 'https://dev.myapp.com' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.

Ajax请求失败后,所有常规GET/POST请求返回401错误,强制页面刷新也无法正常工作,用户需清除浏览器缓存才能恢复。

日志信息

Quarkus应用日志输出:

2023-06-10 21:49:22,257 DEBUG [io.qua.oid.run.CodeAuthenticationMechanism] (vert.x-eventloop-thread-1) State parameter can not be empty or multi-valued if the state cookie is present

解决方案

1. 拦截Ajax未授权响应,触发页面跳转

Primefaces的Ajax请求无法处理跨域重定向,需通过全局Ajax错误处理器拦截401状态码,手动清除无效Cookie并跳转到登录页面:

PrimeFaces.settings.ajax.error = function(xhr, status, error) {
    if (xhr.status === 401) {
        // 清除过期的认证Cookie
        document.cookie = "q_session=; path=/secure/; expires=Thu, 01 Jan 1970 00:00:00 UTC";
        document.cookie = "q_session_rt=; path=/secure/; expires=Thu, 01 Jan 1970 00:00:00 UTC";
        // 跳转到应用首页触发重新认证
        window.location.href = '/secure/user/home.xhtml';
    }
};

2. 调整Quarkus OIDC配置解决状态参数冲突

日志中的状态参数错误由无效Cookie残留导致,可调整Token状态管理配置:

  • 禁用拆分Token配置,避免状态Cookie与请求参数冲突:
quarkus.oidc.token-state-manager.split-tokens=false
  • 扩展认证Cookie路径,确保所有受保护路径都能携带Cookie:
quarkus.oidc.authentication.cookie-path=/

3. 验证Keycloak Web Origins配置

确认Keycloak客户端的Web Origins已添加完整的应用域名(如https://dev.myapp.com),不要添加路径后缀,确保CORS策略覆盖整个域名的请求。

4. 后端拦截Ajax重定向,返回401状态码

添加Quarkus响应过滤器,针对Ajax请求直接返回401而非重定向,让前端统一处理跳转逻辑:

import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerResponseContext;
import javax.ws.rs.container.ContainerResponseFilter;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.ext.Provider;

@Provider
public class AjaxAuthResponseFilter implements ContainerResponseFilter {
    @Override
    public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) {
        String ajaxHeader = requestContext.getHeaderString("X-Requested-With");
        if ("XMLHttpRequest".equals(ajaxHeader) && responseContext.getStatus() == 302) {
            responseContext.setStatus(401);
            responseContext.getHeaders().putSingle("Content-Type", MediaType.TEXT_PLAIN);
            responseContext.setEntity("Unauthorized");
        }
    }
}

内容的提问来源于stack exchange,提问作者zeppelinux

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 19:53:15