單點登陸(SSO)的實現方式有很多種,這里所說的是用CAS實現,這也是Liferay中所采納的方式。至于什么是CAS,單點登陸實現的原理等,這里不做解釋,直接一步一步明說實現方式,好了,多一個字的費話也不說了。
第一步,創建證書
keytool -genkey -alias tomcat -keystore c:\mykeystore -dname "CN=xyb, OU=localhost, O=localhost, L=SH, ST=SH, C=CN" -keypass 123456 -storepass 123456
PS:
-genkey 創建一個證書
-alias 證書的別名
-keystore 指定生成此證書的路徑(可不寫,默認存在系統的Home目錄下.keystore文件中
-storepass 指定密鑰庫的密碼
-keypass 指定別名條目的密碼
-dname 指定證書擁有者信息(可不寫,但,系統會提示你依次輸入這些信息,特別要注意“CN”的值是你想做為CAS服務器的這臺機器的域名或機器名,但就是不能是IP)
-keyalg 指定密鑰的算法(可不寫)
-validity 指定創建的證書有效期多少天(可不寫,默認為90天)
第二步,導出證書
keytool -export -alias tomcat -keystore c:\mykeystore -file c:\mycerts.cer -storepass 123456
PS:
-export 將別名指定的證書導出到文件
-keystore 指定生成此證書的路徑(上一步中寫的什么這就寫什么,如果沒寫,這也不寫)
-file 指定導出到文件的文件名
第三步,把導出的證書導入到客戶端服務器
keytool -import -trustcacerts -alias tomcat -keystore "%JAVA_HOME%/JRE/LIB/SECURITY/CACERTS" -storepass 123456 -file c:\mycerts.cer
PS:
-import 將已簽名數字證書導入密鑰庫
-file 指定要導入到密鑰庫的文件名(也就是上一步導出的那個文件)
有一個提示:是否信任這個證書,輸入 Y,回車。
第四步,下載cas集成包。將下載后的文件改名為cas-web,放置在liferay的webapps目錄下,在conf/server.xml中找到下面這段,去掉原有的注釋并修改為:
<Connector port="8443" maxHttpHeaderSize="8192" maxThreads="150" minSpareThreads="25" maxSpareThreads="75" enableLookups="false" disableUploadTimeout="true" acceptCount="100" scheme="https" secure="true" clientAuth="false" sslProtocol="TLS" URIEncoding="UTF-8" keystorePass="123456" keyAlias="tomcat"/>
第五步,在Liferay的webapps\ROOT\WEB-INF\classes\portal-ext.properties下添加如下內容:
cas.auth.enabled=true
cas.login.url=https://xyb:8443/cas-web/login
cas.logout.url=https://xyb:8443/cas-web/logout
cas.server.name=客戶端IP:8080
cas.service.url=
#cas.service.url=http://localhost:8080/c/portal/login
cas.validate.url=https://xyb:8443/cas-web/proxyValidate
如果沒在Liferay下,只是普通的Web程序可用Filter來實現,打開Web-INF\Web.XML文件,增加如下代碼
最后一步,在客戶端獲取CAS認證通過的用戶名,并修改身份驗證程序為只通過用戶名來驗證。如是在Liferay下就不用做這一步了,Liferay中本身的驗證是ScreenName字段
1、在JSP或Servlet中的用法:
<%@ page import="edu.yale.its.tp.cas.client.filter.CASFilter" %>
<%@ page import="javax.servlet.http.HttpServletRequest" %>
<%@ page import="javax.servlet.http.HttpSession" %>
<%
HttpSession ses = request.getSession();

String screenName =
(String)ses.getAttribute(CASFilter.CAS_FILTER_USER);
System.out.println("screenName==:"+screenName);
%>
2、在Java中通過 Session 獲取登錄用戶名
// 以下兩者都可以
session.getAttribute(CASFilter.CAS_FILTER_USER);
session.getAttribute("edu.yale.its.tp.cas.client.filter.user");
3、在 JSTL 中獲取用戶名的方法
<c:out value="${sessionScope[CAS:'edu.yale.its.tp.cas.client.filter.user']}"/>
問題匯總:
嚴重: edu.yale.its.tp.cas.client.CASAuthenticationException: Unable to validate ProxyTicketValidator [[edu.yale.its.tp.cas.client.ProxyTicketValidator prox
yList=[null] [edu.yale.its.tp.cas.client.ServiceTicketValidator casValidateUrl=[https://192.168.1.111:8443/cas/proxyValidate] ticket=[ST-0-9h7Mx5HK3pfsdxRv
MD3y] service=[http%3A%2F%2F192.168.1.222%3A8080%2Fservlets-examples%2Fservlet%2FHelloWorldExample] renew=false]]]
這個CAS異常是從CAS Client里面拋出,是當我們不使用證書的CN去訪問域名的時候(比如上文是用IP訪問而且證書的CN是該IP對應的域名而非該IP),CASClient無法信任,也就是我上面特意提到的那個CN的問題。要特別注意。
還有一種情況就是客戶端證書沒有導入,同樣也報這個錯誤,最終可以歸為一句話,肯定是證書驗證沒有通過所致.
INFO [org.jasig.cas.authentication.AuthenticationManager
Impl] - <AuthenticationHandler: cn.com.tiansky.cas.authenticationHandlers.UPAuthenticationHandler successfully authenticated the user which provided the followi
ng credentials: [username: test]>
就種錯誤,可能是客戶端的那個配置文件里寫的不太對。也就是上面說的第五步,要多注意一下。
java.io.IOException: Cannot recover key
at org.apache.tomcat.util.net.jsse.JSSE14SocketFactory.init(JSSE14Socket
Factory.java:125)
at org.apache.tomcat.util.net.jsse.JSSESocketFactory.createSocket(JSSESo
cketFactory.java:88)
at org.apache.tomcat.util.net.PoolTcpEndpoint.initEndpoint(PoolTcpEndpoi
nt.java:292)
at org.apache.coyote.http11.Http11BaseProtocol.init(Http11BaseProtocol.j
ava:138)
at org.apache.catalina.connector.Connector.initialize(Connector.java:101
這種錯誤,可能是你生成的證書有問題,如果keypass和storepass的密碼不一致也會把這個錯(不知為什么非要設成一樣的)
眼鏡蛇