1. 程式人生 > >java 整合 cas系統 服務端和客戶端配置

java 整合 cas系統 服務端和客戶端配置

http://blog.csdn.net/yunye114105/article/details/7997041

參考:

http://blog.csdn.net/diyagea/article/details/50638737

(配置SSL協議)http://www.cnblogs.com/notDog/p/5264666.html

背景

有幾個相對獨立的java的web應用系統, 各自有自己的登陸驗證功能,使用者在使用不同的系統的時候,需要登陸不同的系統。現在需要提供一個統一的登陸/登出介面, 而不修改各個系統原來的登陸驗證機制。於是採用單點登入系統CAS。

 

使用步驟

要使用單點登入,需要部署CAS系統, CAS服務端可以直接部署在tomcat下執行, 對於CAS服務端來說,所有要整合單點登入的web應用都是它的一個客戶端, CAS有客戶端jar包, 客戶端web應用需要引入CAS客戶端的jar包,這樣CAS系統的服務端和客戶端web應用程式端才能通訊。

 

客戶端web應用程式的通過配置web.xml,新增CAS需要的各種過濾器,來實現和CAS伺服器通訊, 使用者資訊驗證工作在CAS服務端統一完成, 驗證通過後,客戶端web應用程式只需要補全自己的Session資訊即可。

 

各個客戶端web應用程式需要使用一個公用的使用者表。

 

第一步 部署CAS系統服務端

1.從官網http://developer.jasig.org/cas/下載CAS Server, 將cas-server-webapp-3.4.12.war解壓, 可以看到是一個標準的java的web應用, 可以直接部署到tomcat的webapps目錄下的,我這裡假設部署的路徑是{tomcat_home}/webapps/cas。

2. CAS預設需要tomcat配置SSL協議,使用https協議通訊的。 由於專案是企事業單位內部的系統,不需要這麼高的安全級別, 可以簡化操作,不走SSL協議。修改下配置檔案\WEB-INF\spring-configuration\ticketGrantingTicketCookieGenerator.xml, 如下, 將預設的true改成false即可。

[html] view plain copy

 

  1. <bean id="ticketGrantingTicketCookieGenerator" class="org.jasig.cas.web.support.CookieRetrievingCookieGenerator"  
  2.         p:cookieSecure="false"  
  3.         p:cookieMaxAge="-1"  
  4.         p:cookieName="CASTGC"  
  5.         p:cookiePath="/cas" />  

3.配置登入的驗證邏輯, 修改配置檔案cas\WEB-INF\deployerConfigContext.xml。在authenticationHandlers中配置驗證方式,我這裡配置資料庫查詢語句來實現使用者名稱和密碼的驗證。

[html] view plain copy

 

  1. <property name="authenticationHandlers">  
  2.             <list>  
  3.                 <!--  
  4.                     | This is the authentication handler that authenticates services by means of callback via SSL, thereby validating  
  5.                     | a server side SSL certificate.  
  6.                     +-->  
  7.                 <bean class="org.jasig.cas.authentication.handler.support.HttpBasedServiceCredentialsAuthenticationHandler"  
  8.                     p:httpClient-ref="httpClient" />  
  9.                 <!--  
  10.                     | This is the authentication handler declaration that every CAS deployer will need to change before deploying CAS   
  11.                     | into production.  The default SimpleTestUsernamePasswordAuthenticationHandler authenticates UsernamePasswordCredentials  
  12.                     | where the username equals the password.  You will need to replace this with an AuthenticationHandler that implements your  
  13.                     | local authentication strategy.  You might accomplish this by coding a new such handler and declaring  
  14.                     | edu.someschool.its.cas.MySpecialHandler here, or you might use one of the handlers provided in the adaptors modules.  
  15.                     +-->  
  16.                  <bean class="org.jasig.cas.adaptors.jdbc.SearchModeSearchDatabaseAuthenticationHandler">
                    <property name="dataSource" ref="ds"/>

                    <property name="tableUsers" value="user"/>
                    <property name="fieldUser" value="username"/>
                    <property name="fieldPassword" value="password"/>
                    </bean>
  17.                 <!-- <bean  
  18.                     class="org.jasig.cas.authentication.handler.support.SimpleTestUsernamePasswordAuthenticationHandler" /> -->  
  19.                 <bean class="org.jasig.cas.adaptors.jdbc.QueryDatabaseAuthenticationHandler">  
  20.                     <property name="sql" value="select password from userTable where userName=?" />  
  21.                     <property name="passwordEncoder" ref="passwordEncoder"/>  
  22.                     <property name="dataSource" ref="dataSource" />  
  23.                 </bean>  -->

         

 

  

  1.             </list>  
  2.         </property>  

密碼加密方法我這裡使用MD5, 配置passwordEncoder的bean

[html] view plain copy

 

  1. <bean id="passwordEncoder" class="org.jasig.cas.authentication.handler.DefaultPasswordEncoder" autowire="byName">  
  2.         <constructor-arg value="MD5"/>  
  3.     </bean>  

在配置一個名稱為dataSource的資料來源

[html] view plain copy

 

  1. <bean id="dataSource" class="org.logicalcobwebs.proxool.ProxoolDataSource">  
  2.         <property name="driver" value="com.microsoft.sqlserver.jdbc.SQLServerDriver"></property>  
  3.         <property name="driverUrl" value="jdbc:sqlserver://localhost:1433;databaseName=testDB;"></property>  
  4.         <property name="user" value="sa"></property>  
  5.         <property name="password" value="123456"></property>  
  6.         <property name="maximumConnectionCount" value="100"></property>  
  7.         <property name="minimumConnectionCount" value="1"></property>  
  8.     </bean>  

資料來源的配置根據自己的實際情況來配置, 需要的jar如果lib下面沒有,自己複製進去, 不然資料來源連不上報錯。

4. 現在服務端就配置好了, 如果需要定製登入/登出頁面的話(實際專案基本上都需要修改), 修改cas\WEB-INF\view\jsp\default\ui\下面的casLoginView.jsp和casLogoutView.jsp就可以了

 

 

第二步 客戶端web應用程式整合CAS

1. 從官網 http://developer.jasig.org/cas-clients/ 下載CAS Client, 將客戶端的jar,如cas-client-core-3.2.1.jar引入到web應用程式的classpath中

2 .配置web.xml檔案, 主要是新增過濾器攔截通訊, 下面的例項程式碼, 假設web應用程式的埠是8080

[html] view plain copy

 

  1. <!-- CAS 單點登入(SSO) 過濾器配置 (start) -->  
  2.       
  3.     <!-- 該過濾器用於實現單點登出功能。-->  
  4.     <filter>  
  5.         <filter-name>CAS Single Sign Out Filter</filter-name>  
  6.         <filter-class>org.jasig.cas.client.session.SingleSignOutFilter</filter-class>  
  7.     </filter>  
  8.     <filter-mapping>  
  9.         <filter-name>CAS Single Sign Out Filter</filter-name>  
  10.         <url-pattern>/*</url-pattern>  
  11.     </filter-mapping>  
  12.     <!-- CAS: 用於單點退出 -->  
  13.     <listener>  
  14.         <listener-class>org.jasig.cas.client.session.SingleSignOutHttpSessionListener</listener-class>  
  15.     </listener>  
  16.       
  17.     <!-- 該過濾器負責使用者的認證工作,必須啟用它 -->  
  18.     <filter>  
  19.         <filter-name>CASFilter</filter-name>  
  20.         <filter-class>org.jasig.cas.client.authentication.AuthenticationFilter</filter-class>  
  21.         <init-param>  
  22.             <param-name>casServerLoginUrl</param-name>  
  23.             <!-- 下面的URL是Cas伺服器的登入地址 -->  
  24.             <param-value>http://CAS服務端所在伺服器IP:8080/cas/login</param-value>  
  25.         </init-param>  
  26.         <init-param>  
  27.             <param-name>serverName</param-name>  
  28.             <!-- 下面的URL是具體某一個應用的訪問地址 -->  
  29.             <param-value>http://具體web應用程式所在伺服器IP:8080</param-value>  
  30.         </init-param>  
  31.     </filter>  
  32.     <filter-mapping>  
  33.         <filter-name>CASFilter</filter-name>  
  34.         <url-pattern>/*</url-pattern>  
  35.     </filter-mapping>  
  36.        
  37.     <!-- 該過濾器負責對Ticket的校驗工作,必須啟用它 -->  
  38.     <filter>  
  39.         <filter-name>CAS Validation Filter</filter-name>  
  40.         <filter-class>org.jasig.cas.client.validation.Cas20ProxyReceivingTicketValidationFilter</filter-class>  
  41.         <init-param>  
  42.             <param-name>casServerUrlPrefix</param-name>  
  43.             <!-- 下面的URL是Cas伺服器的認證地址 -->  
  44.             <param-value>http://CAS服務端所在伺服器IP:8080/cas</param-value>  
  45.         </init-param>  
  46.         <init-param>  
  47.             <param-name>serverName</param-name>  
  48.             <!-- 下面的URL是具體某一個應用的訪問地址 -->  
  49.             <param-value>http://具體web應用程式所在伺服器IP:8080</param-value>  
  50.         </init-param>  
  51.         <init-param>  
  52.           <param-name>renew</param-name>  
  53.           <param-value>false</param-value>  
  54.         </init-param>  
  55.         <init-param>  
  56.           <param-name>gateway</param-name>  
  57.           <param-value>false</param-value>  
  58.         </init-param>  
  59.     </filter>  
  60.     <filter-mapping>  
  61.         <filter-name>CAS Validation Filter</filter-name>  
  62.         <url-pattern>/*</url-pattern>  
  63.     </filter-mapping>  
  64.        
  65.     <!--  
  66.     該過濾器負責實現HttpServletRequest請求的包裹,  
  67.     比如允許開發者通過HttpServletRequest的getRemoteUser()方法獲得SSO登入使用者的登入名,可選配置。  
  68.     -->  
  69.     <filter>  
  70.         <filter-name>CAS HttpServletRequest Wrapper Filter</filter-name>  
  71.         <filter-class>org.jasig.cas.client.util.HttpServletRequestWrapperFilter</filter-class>  
  72.     </filter>  
  73.     <filter-mapping>  
  74.         <filter-name>CAS HttpServletRequest Wrapper Filter</filter-name>  
  75.         <url-pattern>/*</url-pattern>  
  76.     </filter-mapping>  
  77.        
  78.     <!--  
  79.     該過濾器使得開發者可以通過org.jasig.cas.client.util.AssertionHolder來獲取使用者的登入名。  
  80.     比如AssertionHolder.getAssertion().getPrincipal().getName()。  
  81.     -->  
  82.     <filter>  
  83.         <filter-name>CAS Assertion Thread Local Filter</filter-name>  
  84.         <filter-class>org.jasig.cas.client.util.AssertionThreadLocalFilter</filter-class>  
  85.     </filter>  
  86.     <filter-mapping>  
  87.         <filter-name>CAS Assertion Thread Local Filter</filter-name>  
  88.         <url-pattern>/*</url-pattern>  
  89.     </filter-mapping>  
  90.        
  91.     <!-- 自動根據單點登入的結果設定本系統的使用者資訊(具體某一個應用實現) -->  
  92.     <filter>  
  93.         <filter-name>CasForInvokeContextFilter</filter-name>  
  94.         <filter-class>com.cm.demo.filter.CasForInvokeContextFilter</filter-class>  
  95.         <init-param>  
  96.           <param-name>appId</param-name>  
  97.           <param-value>a5ea611bbff7474a81753697a1714fb0</param-value>  
  98.         </init-param>  
  99.     </filter>  
  100.     <filter-mapping>  
  101.         <filter-name>CasForInvokeContextFilter</filter-name>  
  102.         <url-pattern>/*</url-pattern>  
  103.     </filter-mapping>  
  104.     <!-- CAS 單點登入(SSO) 過濾器配置 (end) -->  

4. 注意上步配置檔案中,過濾器CasForInvokeContextFilter的實現是需要在具體的應用中實現的,他的目的是, CAS服務端登入驗證成功後,會將登入使用者的使用者名稱攜帶回來, 這時客戶端web應用程式需要根據使用者名稱從資料庫使用者表中查詢到使用者的Id等資訊, 並填充到Session中, 這樣,客戶端應用程式原來的驗證邏輯就不會出問題了, 因為我們一般都是通過驗證session中是否含有當前登入的使用者的ID來進行登入驗證的。

下面是CasForInvokeContextFilter的一個簡單實現。

[java] view plain copy

 

  1. /** 
  2.  * 該過濾器使用者從CAS認證伺服器中獲取登入使用者使用者名稱,並填充必要的Session. 
  3.  * @author jiarong_cheng 
  4.  * @created 2012-7-12 
  5.  */  
  6. public class CasForInvokeContextFilter implements Filter {  
  7.   
  8.     @Override  
  9.     public void destroy() {  
  10.     }  
  11.   
  12.     @Override  
  13.     public void doFilter(ServletRequest request, ServletResponse response,  
  14.             FilterChain chain) throws IOException, ServletException {  
  15.         HttpSession session = ((HttpServletRequest) request).getSession();  
  16.         //如果session中沒有使用者資訊,則填充使用者資訊  
  17.         if (session.getAttribute("j_userId") == null) {  
  18.             //從Cas伺服器獲取登入賬戶的使用者名稱  
  19.             Assertion assertion = AssertionHolder.getAssertion();  
  20.             String userName = assertion.getPrincipal().getName();  
  21.   
  22.             try {  
  23.                 //根據單點登入的賬戶的使用者名稱,從資料庫使用者表查詢使用者資訊, 填充到session中  
  24.                 User user = UserDao.getUserByName(userName);  
  25.                 session.setAttribute("username", userName);  
  26.                 session.setAttribute("userId", user.getId());  
  27.             } catch (Exception e) {  
  28.                 e.printStackTrace();  
  29.             }  
  30.         }  
  31.         chain.doFilter(request, response);  
  32.     }  
  33.   
  34.     @Override  
  35.     public void init(FilterConfig config) throws ServletException {  
  36.     }  
  37. }  


到此,就完成了, 當你訪問具體應用的網址, 如http://具體應用IP: 8080/ ,就會跳轉到CAS伺服器的登陸頁面: http://CAS伺服器IP: 8080/  進行登入驗證, 驗證通過後, 又會跳轉回應用的網址。

 

第三步 單點登出

這個比較簡單, 只要在系統的登出事件中, 將URL訪問地址指向CAS服務登出的servlet, 就可以了。

http://CAS伺服器IP:8080/cas/logout