基於 CAS 4.1.8 實現 SPNEGO 認證,讓域內用戶訪問 Web 應用時無感知自動登錄(Kerberos/NTLM)。涉及 AD 域、DNS、SPN、Keytab、瀏覽器、Java 加密策略、CAS Webflow 等多環節,易踩坑,特記錄全流程。
example.com)。client,IE/Firefox 配置信任站點。server,IP 172.10.1.10,主機名 server.example.com。example.com,創建用戶 client/server,設置「密碼永不過期」,賬戶選項僅勾選「支持 Kerberos AES 256 位加密」。example.com,重啟驗證 whoami 顯示域用戶。setspn -s HTTP/server.example.com@EXAMPLE.COM server setspn -l server # 驗證
ktpass /princ HTTP/server.example.com@EXAMPLE.COM /mapuser server /pass ****** /out server.keytab /crypto all /ptype KRB5_NT_PRINCIPAL /mapop set將
server.keytab 複製到 CAS 服務器(如 C:/keytab/server.keytab)。https://server.example.com。about:config 設置 network.negotiate-auth.trusted-uris = https://server.example.com。local_policy.jar/US_export_policy.jar)替換 $JAVA_HOME/jre/lib/security/ 下文件,支持 AES-256。login-webflow.xml):
<action-state id="startAuthenticate"> <evaluate expression="negociateSpnego" /> <transition on="success" to="spnego" /> </action-state> <action-state id="spnego"> <evaluate expression="spnego" /> <transition on="success" to="sendTicketGrantingTicket" /> <transition on="error" to="viewLoginForm" /> </action-state> <!-- 修改 generateLoginTicket 後的 transition 目標為 startAuthenticate -->
cas-servlet.xml):
<bean id="negociateSpnego" class="org.jasig.cas.support.spnego.web.flow.SpnegoNegociateCredentialsAction" />
<bean id="spnego" class="org.jasig.cas.support.spnego.web.flow.SpnegoCredentialsAction"
p:centralAuthenticationService-ref="centralAuthenticationService" />
deployerConfigContext.xml):
<bean id="jcifsConfig" class="org.jasig.cas.support.spnego.authentication.handler.support.JCIFSConfig"
p:jcifsServicePrincipal="HTTP/server.example.com@EXAMPLE.COM"
p:kerberosDebug="false"
p:kerberosRealm="EXAMPLE.COM"
p:kerberosKdc="172.10.1.10"
p:loginConf="/login.conf" />
<bean id="spnegoAuthentication" class="jcifs.spnego.Authentication" />
<bean id="spnegoHandler" class="org.jasig.cas.support.spnego.authentication.handler.support.JCIFSSpnegoAuthenticationHandler"
p:authentication-ref="spnegoAuthentication"
p:principalWithDomainName="false"
p:NTLMallowed="true" />
<bean id="spnegoPrincipalResolver" class="org.jasig.cas.support.spnego.authentication.principal.SpnegoPrincipalResolver" />
<bean id="authenticationManager" class="org.jasig.cas.authentication.PolicyBasedAuthenticationManager">
<constructor-arg>
<map><entry key-ref="spnegoHandler" value-ref="spnegoPrincipalResolver"/></map>
</constructor-arg>
</bean>
login.conf 放類路徑):
jcifs.spnego.initiate {
com.sun.security.auth.module.Krb5LoginModule required
storeKey=true useKeyTab=true keyTab="C:/keytab/server.keytab";
};
jcifs.spnego.accept {
com.sun.security.auth.module.Krb5LoginModule required
storeKey=true useKeyTab=true keyTab="C:/keytab/server.keytab";
};
172.10.1.10 server.example.com。ktpass /crypto all 導出所有加密類型,JCE 無限制策略必須生效。HTTP/host@REALM。p:NTLMallowed="true" 允許不支持 Kerberos 的客戶端降級 NTLM。org.apereo.cas,Bean 類名可能調整,參考官方文檔。官方參考:CAS SPNEGO Authentication