Apache Zeppelin集成Keycloak后AJAX请求空指针及PKCE验证失败
解决方案:Apache Zeppelin 0.11.1 + Keycloak 集成的PKCE验证失败与AJAX空指针问题
针对你遇到的两个核心问题(PKCE验证失败、AJAX请求空指针),结合使用的依赖版本(pac4j 5.7.6、buji-pac4j 8.1.0、Shiro 1.10.0),给出以下具体排查和修复步骤:
一、解决PKCE验证失败(invalid_grant)问题
1. 检查Keycloak客户端配置
- 进入对应客户端的Settings页面,确认:
Access Type设置为confidential(Zeppelin作为服务端应用,需使用此类型配合PKCE);Proof Key for Code Exchange Code Challenge Method设置为S256(若开启此选项,pac4j必须使用相同算法生成挑战值)。
2. 修正pac4j OIDC客户端配置
在OidcClient初始化代码中明确开启PKCE并指定算法:
OidcClient oidcClient = new OidcClient(); // 开启PKCE支持 oidcClient.setUsePkce(true); // 匹配Keycloak配置的算法 oidcClient.setCodeChallengeMethod("S256"); // 其他配置(如client ID、secret、Keycloak issuer URL)...
3. 确保会话存储同步
buji-pac4j依赖Shiro会话存储PKCE的code_challenge和code_verifier,需确认:
- Zeppelin的Shiro会话配置正确,session ID在AJAX请求中正常携带(检查请求Cookie是否包含Shiro的session ID);
- 避免会话过期时间过短,导致回调时会话中已丢失PKCE参数。
二、解决DefaultAjaxRequestResolver空指针问题
1. 自定义AJAX请求解析器
DefaultAjaxRequestResolver在识别非标准AJAX请求时会返回null,导致空指针。针对Zeppelin的/api/前缀请求,自定义解析器避免返回null:
public class ZeppelinAjaxResolver extends DefaultAjaxRequestResolver { @Override public AjaxResponse buildAjaxResponse(WebContext context, String url) { // 对Zeppelin API路径强制返回非null响应 if (context.getRequestPath().startsWith("/api/")) { return new AjaxResponse(url, false); } AjaxResponse response = super.buildAjaxResponse(context, url); return response != null ? response : new AjaxResponse(url, false); } @Override public boolean isAjax(WebContext context) { // 兼容Zeppelin可能的自定义AJAX标识Header boolean standardAjax = super.isAjax(context); String zeppelinAjaxHeader = context.getRequestHeader("X-Zeppelin-Ajax"); return standardAjax || "true".equals(zeppelinAjaxHeader); } }
然后在pac4j全局配置中替换默认解析器:
Config config = new Config(oidcClient); config.setAjaxRequestResolver(new ZeppelinAjaxResolver());
2. 调整API路径的安全过滤规则
确保/api/路径的请求不会触发OIDC重定向(AJAX无法处理重定向),在SecurityFilter配置中添加:
SecurityFilter filter = new SecurityFilter(); filter.setConfig(config); filter.setClients("OidcClient"); // 允许AJAX请求直接处理,不跳转登录页 filter.setAllowAjaxRequests(true); // 针对/api/路径设置授权规则 filter.setMatchers(new PathMatcher().include("/api/**"));
三、版本兼容性与日志调试
1. 版本验证
当前依赖版本组合(pac4j 5.7.6 + buji-pac4j 8.1.0 + Shiro 1.10.0)是兼容的,可尝试升级pac4j到5.x最新版(如5.7.10),修复已知的PKCE或AJAX处理bug。
2. 开启调试日志
在Zeppelin的日志配置中添加:
log4j.logger.org.pac4j.core=DEBUG log4j.logger.org.pac4j.oidc=DEBUG log4j.logger.io.buji.pac4j=DEBUG
通过日志查看:
- PKCE参数(
code_challenge/code_verifier)是否在会话中正确存储; - AJAX请求的识别逻辑是否符合预期。
内容的提问来源于stack exchange,提问作者longvh
相关产品推荐
相关产品推荐

