Liferay5中CAS Client v3.2.1动态配置参数失效及优化方案咨询
在Liferay 5中动态配置CAS Client 3.2.1的参数(无需重写AuthenticationFilter)
问题背景
我有一个基于Liferay 5的项目,已将旧版CAS Client升级至v3.2.1,更新jar包并配置web.xml后功能正常。但希望通过属性文件(如portal-ext.properties)或系统属性动态填充serverName和casServerLoginUrl等Filter参数。尝试在web.xml中使用${cas.login.url}并在portal-ext.properties中配置对应属性,但参数值未被替换。查看CAS Client的AuthenticationFilter.getPropertyFromInitParams方法,发现它仅从FilterConfig、ServletContext、JNDI读取参数,不处理Liferay的属性占位符。不想通过复制并重写整个AuthenticationFilter类来解决,求更优雅的方案。
解决方案
方案1:通过Liferay启动动作将属性注入ServletContext
CAS Client支持从ServletContext读取参数,我们可以利用Liferay的StartupAction机制,把portal-ext.properties中的属性加载到ServletContext中,让CAS Client自动读取:
- 在portal-ext.properties中添加自定义CAS配置
# CAS配置属性 cas.server.login.url=https://your-cas-server/login cas.server.name=http://your-liferay-server:8080
- 编写StartupAction类注入属性到ServletContext
创建一个实现com.liferay.portal.kernel.events.Action的类,在Liferay启动时将属性设置到ServletContext:
import com.liferay.portal.kernel.events.Action; import com.liferay.portal.kernel.events.ActionException; import com.liferay.portal.util.PortalUtil; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.ServletContext; import org.apache.commons.lang.StringUtils; import java.util.Properties; public class CASPropertyLoaderAction implements Action { @Override public void run(HttpServletRequest request, HttpServletResponse response) throws ActionException { try { Properties portalProps = PortalUtil.getPortalProperties(); ServletContext servletContext = request.getServletContext(); // 加载casServerLoginUrl String casLoginUrl = portalProps.getProperty("cas.server.login.url"); if (StringUtils.isNotBlank(casLoginUrl)) { servletContext.setInitParameter("casServerLoginUrl", casLoginUrl); } // 加载serverName String serverName = portalProps.getProperty("cas.server.name"); if (StringUtils.isNotBlank(serverName)) { servletContext.setInitParameter("serverName", serverName); } } catch (Exception e) { throw new ActionException("Failed to load CAS properties into ServletContext", e); } } }
- 注册StartupAction到Liferay
在portal-ext.properties中添加启动事件配置:
# 注册CAS属性加载动作 portal.startup.events=com.yourcompany.events.CASPropertyLoaderAction
- 修改web.xml的Filter配置
移除Filter中对应的init-param(或保留但设为空值),CAS Client会自动从ServletContext读取参数:
<filter> <filter-name>SSO CAS Filter</filter-name> <filter-class>org.jasig.cas.client.authentication.AuthenticationFilter</filter-class> <!-- 移除或留空init-param,让CAS从ServletContext读取 --> </filter>
方案2:利用CAS Client的JNDI支持配置参数
CAS Client的参数读取逻辑原生支持JNDI,可以在应用服务器中配置JNDI属性,让CAS Client自动读取:
以Tomcat为例配置JNDI:
- 在Tomcat的conf/context.xml中添加全局环境变量
<GlobalNamingResources> <!-- CAS配置属性 --> <Environment name="cas/casServerLoginUrl" value="https://your-cas-server/login" type="java.lang.String"/> <Environment name="cas/serverName" value="http://your-liferay-server:8080" type="java.lang.String"/> </GlobalNamingResources>
- 在项目的META-INF/context.xml中添加资源链接
<Context> <ResourceLink name="cas/casServerLoginUrl" global="cas/casServerLoginUrl" type="java.lang.String"/> <ResourceLink name="cas/serverName" global="cas/serverName" type="java.lang.String"/> </Context>
- 修改web.xml的Filter配置
同样移除或留空对应的init-param,CAS Client会自动从JNDI读取参数。
方案3:轻量扩展AuthenticationFilter(无需复制整个类)
如果上述方案不适用,可以编写一个子类继承原AuthenticationFilter,仅重写参数读取逻辑,复用父类的其他功能:
- 编写自定义Filter类
import org.jasig.cas.client.authentication.AuthenticationFilter; import com.liferay.portal.util.PortalUtil; import javax.servlet.FilterConfig; import org.apache.commons.lang.StringUtils; import java.util.Properties; public class LiferayCASAuthFilter extends AuthenticationFilter { @Override protected String getPropertyFromInitParams(FilterConfig filterConfig, String propertyName, String defaultValue) { // 优先从portal-ext.properties读取 Properties portalProps = PortalUtil.getPortalProperties(); String portalValue = portalProps.getProperty(propertyName); if (StringUtils.isNotBlank(portalValue)) { return portalValue; } // 其次读取系统属性 String sysValue = System.getProperty(propertyName); if (StringUtils.isNotBlank(sysValue)) { return sysValue; } // 最后调用父类的默认读取逻辑 return super.getPropertyFromInitParams(filterConfig, propertyName, defaultValue); } }
- 修改web.xml的Filter类
将filter-class替换为自定义类:
<filter> <filter-name>SSO CAS Filter</filter-name> <filter-class>com.yourcompany.filter.LiferayCASAuthFilter</filter-class> <!-- 可选:保留init-param作为默认值 --> </filter>
总结
- 方案1和方案2无需修改CAS Client相关代码,完全利用现有机制,是最优雅的选择;
- 方案3仅重写必要方法,比复制整个类更简洁,适合需要灵活扩展参数来源的场景。
内容的提问来源于stack exchange,提问作者user2178964
相关产品推荐
相关产品推荐

