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

切换Pac4j+Shiro+Keycloak后JSF Ajax请求失效问题排查

问题分析与解决方案

这不是Pac4j或Shiro的Bug,而是默认授权配置与JSF Ajax请求的适配问题,以下是具体原因和正确配置方案:

原因解析

Pac4j的SecurityFilter默认启用了两个授权器:

  • CsrfAuthorizer:检查请求是否携带名为pac4jCsrfToken的参数或请求头,用于防范CSRF攻击
  • IsAuthenticatedAuthorizer:验证用户是否已完成认证

而JSF(尤其是PrimeFaces)的Ajax请求使用自身的CSRF机制(比如JSF 2.2+的javax.faces.Token或PrimeFaces内置CSRF token),不会自动携带Pac4j要求的pac4jCsrfToken,因此触发CsrfAuthorizer校验失败,请求被拦截后无法触发后台Bean的方法。

正确配置方案(替代authorizers = none)

方案1:让Pac4j识别JSF的CSRF Token

修改shiro.ini中oidcSecurityFilter的授权器配置,将CsrfAuthorizer的参数名改为JSF使用的CSRF参数名。

  • 针对JSF 2.2+的javax.faces.Token:
oidcSecurityFilter.authorizers = csrfAuthorizer, isAuthenticatedAuthorizer

# 配置适配JSF的CSRF授权器
csrfAuthorizer = org.pac4j.core.authorization.authorizer.CsrfAuthorizer
csrfAuthorizer.parameterName = javax.faces.Token
  • 针对PrimeFaces的csrfToken:
csrfAuthorizer.parameterName = csrfToken

方案2:在JSF页面中添加Pac4j的CSRF Token

在包含Ajax请求的<h:form>内添加隐藏字段,携带Pac4j的CSRF Token,让Ajax请求自动带上该参数:

<h:form>
    <h:inputHidden name="pac4jCsrfToken" value="#{pac4jCsrfToken}" />
    <p:ajax event="load" listener="#{myBean.init()}" />
    <!-- 其他表单组件 -->
</h:form>

方案3:针对Ajax请求跳过CSRF校验(谨慎使用)

若不需要对JSF Ajax请求做Pac4j的CSRF校验,可自定义授权逻辑或配置CsrfAuthorizer仅针对非Ajax请求检查,但这种方式会降低安全性,建议优先使用前两种方案。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 08:23:25