java單點登陸系統CAS的簡單使用

 
 

背景

有幾個相對獨立的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://www.jasig.org下載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  
  17.                     class="org.jasig.cas.authentication.handler.support.SimpleTestUsernamePasswordAuthenticationHandler" /> -->  
  18.                 <bean class="org.jasig.cas.adaptors.jdbc.QueryDatabaseAuthenticationHandler">  
  19.                     <property name="sql" value="select password from userTable where userName=?" />  
  20.                     <property name="passwordEncoder" ref="passwordEncoder"/>  
  21.                     <property name="dataSource" ref="dataSource" />  
  22.                 </bean>  
  23.             </list>  
  24.         </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. 從官網下載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
相關文章
相關標籤/搜索