簡介
CAS專案官網 是一款開源的單點登入解決方案,可以直接再Tomcat,Jetty等WEB容器上執行,支援多種開發語言
下載
下載cas-server-XXX-release.zip(地址)
注意:官網提供的所有版本中,最新的版本(4.0以上)可能沒有release.zip包
修改tomcat
建立祕鑰
生成keypair
在 $JRE_HOME/bin/
目錄下建立命令列,輸入以下命令,其中CN
的值必須保持和主機名一致,假設密碼為 mypass
,再繼續填寫資訊,遇到主密碼直接回車
keytool -genkeypair -alias cas -keyalg RSA -storepass mypass
上述命令會在使用者目錄下生成一個.keystore檔案,後面會使用該檔案其他的幾個常用命令
# 檢視 keypair:
keytool -list -storepass mypass
# 刪除 keypair:keytool -delete -alias <別名> -storepass mypass
匯出證照
keytool -exportcert -alias cas -file cas.crt -storepass mypass
上述命令會在當前目錄生成一個cas.crt證照檔案,後面也會使用該檔案
向JVM匯入證照
keytool -importcert -alias cas -file cas.crt -keystore "%JAVA_HOME%jrelibsecuritycacerts" -storepass mypass -noprompt
上面的JAVA_HOME
需要換成實際的路徑
配置tomcat
修改配置檔案
不同版本的cas對jdk版本的要求不一樣,請查閱cas說明
修改tomcat目錄下的conf/server.xml,開啟SSL
<Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="off" />
配置HTTPS埠
<Connector port="8443"
protocol="org.apache.coyote.http11.Http11Protocol"
SSLEnabled="true"
maxThreads="150"
scheme="https"
secure="true"
clientAuth="false"
sslProtocol="TLS"
keystoreFile="apache-tomcat-7.0.73confsecurity.keystore"
keystorePass="mypass"/>
如果要確保訪問HTTPS服務只能用8443埠,則需要禁用其他埠號
訪問cas服務
重啟tomcat: 在 tomcat/bin/
下先執行 shutdown
,再執行 startup
。訪問cas的地址為 https://localhost:8443/cas/login
WEB整合CAS-CLIENT
在Spring服務的pom.xml
加入cas-client的依賴包
<!--cas client-->
<dependency>
<groupId>org.jasig.cas.client</groupId>
<artifactId>cas-client-core</artifactId>
<version>3.3.3</version>
</dependency>
在Spring的專案配置檔案web.xml
中加入cas的配置
<!-- ======================== 單點登入開始 ======================== -->
<listener>
<listener-class>org.jasig.cas.client.session.SingleSignOutHttpSessionListener</listener-class>
</listener>
<!-- 該過濾器用於實現單點登出功能,可選配置。 -->
<filter>
<filter-name>CAS Single Sign Out Filter</filter-name>
<filter-class>org.jasig.cas.client.session.SingleSignOutFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>CAS Single Sign Out Filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>CAS Filter</filter-name>
<filter-class>org.jasig.cas.client.authentication.AuthenticationFilter</filter-class>
<init-param>
<param-name>casServerLoginUrl</param-name>
<param-value>https://nkgy4l003835331:8443/cas/login</param-value>
<!-- 這裡只能使用主機名的url -->
</init-param>
<init-param>
<param-name>serverName</param-name>
<param-value>http://localhost:8080</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CAS Filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- 該過濾器負責對Ticket的校驗工作,必須啟用它 -->
<filter>
<filter-name>CAS Validation Filter</filter-name>
<filter-class>
org.jasig.cas.client.validation.Cas20ProxyReceivingTicketValidationFilter</filter-class>
<init-param>
<param-name>casServerUrlPrefix</param-name>
<param-value>https://nkgy4l003835331:8443/cas</param-value>
<!-- 這裡只能使用主機名的url -->
</init-param>
<init-param>
<param-name>serverName</param-name>
<param-value>http://localhost:8080</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CAS Validation Filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!--
該過濾器負責實現HttpServletRequest請求的包裹,
比如允許開發者通過HttpServletRequest的getRemoteUser()方法獲得SSO登入使用者的登入名,可選配置。
-->
<filter>
<filter-name>CAS HttpServletRequest Wrapper Filter</filter-name>
<filter-class>
org.jasig.cas.client.util.HttpServletRequestWrapperFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>CAS HttpServletRequest Wrapper Filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!--
該過濾器使得開發者可以通過org.jasig.cas.client.util.AssertionHolder來獲取使用者的登入名。
比如AssertionHolder.getAssertion().getPrincipal().getName()。
-->
<filter>
<filter-name>CAS Assertion Thread Local Filter</filter-name>
<filter-class>org.jasig.cas.client.util.AssertionThreadLocalFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>CAS Assertion Thread Local Filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- ======================== 單點登入結束 ======================== -->
同一個Tomcat下部署CAS-Server和Spring Web需要在tomcat的server.xml
中建立兩個Service
<!-- 用於HTTP應用 -->
<Service name="Catalina">
</Service>
<!-- 用於CAS的HTTPS應用 -->
<Service name="Catalina.cas">
</Service>
將HTTPS的移動到Catalina.cas中,並配置context的path路徑cas的包路徑
<Service name="Catalina.cas">
<Connector port="8443"
protocol="org.apache.coyote.http11.Http11Protocol" SSLEnabled="true"
maxThreads="150" scheme="https" secure="true"
clientAuth="false" sslProtocol="TLS"
keystoreFile="F:softwareapache-tomcat-7.0.73-windows-x64apache-tomcat-7.0.73confsecuritykeystore.jks"
keystorePass="changeit"/>
<Engine name="Catalina.cas" defaultHost="localhost">
<Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="false" deployOnStartup="false">
<Context path="/cas" docBase="cas" reloadable="false" />
配置HTTP的context
與上一步類似,context的path填WEB專案的地址
CAS連線資料庫
複製cas下載包中的 cas-server-support-jdbc-*.jar
到 tomcat/webapps/cas/WEB-INF/lib
中
複製資料庫驅動包(如 mysql-connector.jar
)到 tomcat/webapps/cas/WEB-INF/lib
中
- 修改cas配置檔案: 在
tomcat/webapps/cas/WEB-INF/cas.properties
中加入以下資料庫的配置
# == Basic database connection pool configuration ==
database.driverClass=com.mysql.jdbc.Driver
database.url=jdbc:mysql://127.0.0.1:3306/test
database.user=root
database.password=root
-
修改 tomcat/webapps/cas/WEB-INF/deployerConfigContext.xml 配置
- 註冊dataSource的bean
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource" p:driverClassName="${database.driverClass}" p:url="${database.url}" p:username="${database.user}" p:password="${database.password}"> </bean>
- 註冊密碼加密的bean,這裡的bean的實現類可以是自定義的加密類,只要實現encode方法就可以
// 以下使用cas自帶的加密類 <bean id="md5PasswordEncoder" class="org.jasig.cas.authentication.handler.DefaultPasswordEncoder"> <constructor-arg index="0"> <value>MD5</value> </constructor-arg> </bean>
- 註釋預設的校驗規則bean,預設判斷使用者名稱和密碼相等即可
<!-- <bean class="org.jasig.cas.authentication.handler.support.SimpleTestUsernamePasswordAuthenticationHandler" /> -->
- 在上述註釋後面新增新的校驗bean,注意sql的值要完全和設計的登陸表對應
<bean class="org.jasig.cas.adaptors.jdbc.QueryDatabaseAuthenticationHandler"> <property name="dataSource" ref="dataSource"></property> <property name="sql" value="select password from tb_user where account=?"></property> <property name="passwordEncoder" ref="md5PasswordEncoder"></property> </bean>
重啟tomcat重新登陸
CAS自定義登陸頁面
CAS的登陸頁jsp檔案在 tomcat/webapps/cas/WEB-INF/view/jsp/default/ui/casLoginView.jsp
修改注意事項
- 可以自由定義樣式和指令碼
- 要引入靜態資源,需要將被引入的檔案放在
tomcat/webapps/cas
目錄下的位置,可以參考tomcat/webapps/cas/css
,引用程式碼示例:
<link href="/css/login.css" rel="stylesheet" type="text/css">
保持以下內容完整,因為以下內容會將值傳給login請求
<form:form method="post" id="fm1" cssClass="fm-v clearfix" commandName="${commandName}" htmlEscape="true">
<input type="hidden" name="lt" value="${loginTicket}" />
<input type="hidden" name="execution" value="${flowExecutionKey}" />
<input type="hidden" name="_eventId" value="submit" />
<form:input id="username" .../>
<form:password id="password" .../>
原有的控制元件具有友好的功能,可以適當考慮保留和優化,如下面是登陸失敗提示憑證錯誤的控制元件
<form:errors path="*" id="msg" cssClass="errors" element="div" />
儲存檔案,重新整理瀏覽器即可
CAS加入註冊功能(擴充套件:其他任意功能)
在CAS Server上新增註冊功能
CAS本身不具有註冊功能,因為CAS要開放註冊業務給其他業務系統,CAS單一負責登陸校驗和會話管理
修改步驟
在 tomcat/webapps/cas/WEB-INF/view/jsp/default/ui/
中加入註冊頁的jsp檔案,如casRegisterView.jsp
,傳入引數為username
和password
在 tomcat/webapps/cas/WEB_INF/classes/default_views.properties
中新增註冊頁的view對映
-
新增註冊頁
casRegisterView.(class)=org.springframework.web.servlet.view.JstlView
casRegisterView.url=/WEB-INF/view/jsp/default/ui/casRegisterView.jsp
- 建立註冊控制類RegisterController.java,輸入以下程式碼
package x.y.z;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.AbstractController;
//必須繼承AbstractController控制器基礎類
public class RegisterController extends AbstractController
{
private DatabaseHandler dataHandler;//資料庫處理類(bean注入)
// 必須實現的方法
protected ModelAndView handleRequestInternal(HttpServletRequest request,
HttpServletResponse response) throws Exception
{
ModelAndView signinView=new ModelAndView();
String username=request.getParameter("username");
String password=request.getParameter("password");
if(username == null || username.equals("") || password == null || password.equals("")){
return new ModelAndView("casRegisterView");
}
boolean success = this.dataHandler.insertUser(username,password);
String viewName=getSignInView(request);
signinView.setViewName(viewName);
return signinView;
}
// 處理跳轉url
protected String getSignInView(HttpServletRequest request) {
String service = ServletRequestUtils.getStringParameter(request, "service", "");
return ("redirect:login" + (service.length() > 0 ? "?service=" + service : ""));
}
// 開放設定dataHandler,用於bean注入
public void setDataHandler(DatabaseHandler handler){
this.dataHandler = handler;
}
}
- 建立資料庫實現類DatabaseHandler.java,輸入以下程式碼
package x.y.z;
import org.springframework.jdbc.core.simple.SimpleJdbcTemplate;
import javax.sql.DataSource;
class DatabaseHandler{
// 資料庫操作模板類
private SimpleJdbcTemplate jdbcTemplate;
// 資料來源
private DataSource dataSource;
// 自定義方法,示例為插入一個新使用者
public boolean insertUser(String username,String password){
int r = 0;
try {
r = this.jdbcTemplate.update("insert into tb_user(account,password,time) values(?,?,?)",username,password,System.currentTimeMillis()/1000);
}catch (Exception e){
e.printStackTrace();
return false;
}
return r > 0;
}
//設定datasource注入
public final void setDataSource(final DataSource dataSource) {
this.jdbcTemplate = new SimpleJdbcTemplate(dataSource);
this.dataSource = dataSource;
}
}
-
將3-4的兩個java檔案打包成jar檔案,並最終放到
tomcat/webapps/cas/WEB-INF/lib
中- 第一步: 編譯java檔案
# 由於java檔案中引用了其他類,所以需要用 -cp 連結jar包 javac -cp "tomcat/webapps/cas/WEB-INF/lib/*" RegisterController.java.java javac -cp "tomcat/webapps/cas/WEB-INF/lib/*" DatabaseHandler.java.java
- 第二步: 打包成jar包
# 可以將兩個檔案打包在一起,也可以分開打包。例如打包在一起,名字取為my-register.jar # @注意: 由於3-4建立的java檔案包含package 值,所以用jar打包時必須將class檔案放在當前目錄下的package子目錄下,例如當前目錄下的 x/y/z/目錄下 jar cvf my-register.jar x/y/z/*.class
-
修改
tomcat/webapps/cas/WEB-INF/cas-servlet.xml
檔案配置- 註冊dataHandler的bean
<bean id="dataHandler" class="com.cas.luodong.web.DatabaseHandler"> <property name="dataSource" ref="dataSource"></property> </bean>
- 註冊registerController的bean
<bean id="registerController" class="com.cas.luodong.web.RegisterController" p:dataHandler-ref="dataHandler"/>
- 在 <bean id=”handlerMappingC” 的props中加入以下內容
<prop key="/register">registerController</prop> 修改 tomcat/webapps/cas/WEB-INF/web.xml 檔案配置
- 加入servlet-mapping項
<servlet-mapping> <servlet-name>cas</servlet-name> <url-pattern>/validate</url-pattern> </servlet-mapping>
重啟tomcat,訪問 cas/register
可以看到結果
FQA
java.lang.IllegalArgumentException: casServerUrlPrefix cannot be null
解決辦法: cas-client-core的版本3.4.1不支援RC5,改為3.3.3即可
java.security.cert.CertificateException: No name matching localhost found
解決辦法: jdk生成證照時填寫的CN值必須為當前主機的主機名
java.security.cert.CertificateException: No subject alternative names present
解決辦法: web.xml中的 casServerLoginUrl 和 casServerUrlPrefix 不能使用ip,必須使用CN值
CAS is Unavailable ; There was an error trying to complete your request. Please notify your support desk or try again.
解決辦法: 檢查ui下的jsp檔案是否有誤,確認標籤匹配正確