配置CAS應用客戶端
本文介紹JavaEE,Django, Php的CAS客戶端配置方法。
CAS客戶端可以在這裡找到,其中有些是官方維護,有些是社群維護。你也可以根據CAS協議編寫一個客戶端。關於CAS登陸驗證流程請參閱: 這裡 。當然最好是採用別人已經封裝好的客戶端(元件),避免重複發明輪子。
JavaEE
先定義一些環境變數:
CATALINA_HOME: Tomcat安裝目錄(以tomcat 7.0.42為例)
CAS_CLIENT_HOME cas客戶端發行包解壓後的目錄(以cas-client-3.2.1為例)
我們以tomcat自帶的例子來進行說明。
開啟%CATALINA_HOME%/webapps/examples1/WEB-INF/web.xml,在所有過濾器之前新增如下的過濾器:
<!-- 修復亂碼的問題 --> <filter> <filter-name>CharacterEncodingFilter</filter-name> <filter-class>edu.vt.middleware.servlet.filter.CharacterEncodingFilter</filter-class> <init-param> <param-name>requestCharsetName</param-name> <param-value>UTF-8</param-value> </init-param> <init-param> <param-name>responseCharsetName</param-name> <param-value>UTF-8</param-value> </init-param> </filter> <filter-mapping> <filter-name>CharacterEncodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!-- 該過濾器用於實現單點登出功能,可選配置。 --> <filter> <filter-name>CasSingleSignOutFilter</filter-name> <filter-class>org.jasig.cas.client.session.SingleSignOutFilter</filter-class> </filter> <filter-mapping> <filter-name>CasSingleSignOutFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!-- 該過濾器負責使用者的認證工作,必須啟用它 --> <filter> <filter-name>CasAuthenticationFilter</filter-name> <filter-class>org.jasig.cas.client.authentication.AuthenticationFilter</filter-class> <init-param> <param-name>casServerLoginUrl</param-name> <param-value>https://localhost:8444/cas-server/login</param-value> <!-- CAS-SERVER的url--> </init-param> <init-param> <param-name>serverName</param-name> <param-value>http://localhost:8080</param-value> <!-- 本客戶端的IP和埠 --> </init-param> </filter> <filter-mapping> <filter-name>CasAuthenticationFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!-- 該過濾器負責對Ticket的校驗工作,必須啟用它 --> <filter> <filter-name>CasValidationFilter</filter-name> <filter-class>org.jasig.cas.client.validation.Cas20ProxyReceivingTicketValidationFilter</filter-class> <init-param> <param-name>casServerUrlPrefix</param-name> <param-value>https://localhost:8444/cas-server</param-value> </init-param> <init-param> <param-name>serverName</param-name> <param-value>http://localhost:8080</param-value> </init-param> <init-param> <param-name>redirectAfterValidation</param-name> <param-value>true</param-value> </init-param> </filter> <filter-mapping> <filter-name>CasValidationFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!-- 該過濾器負責實現HttpServletRequest請求的包裹, 比如允許開發者通過HttpServletRequest的getRemoteUser()方法獲得SSO登入使用者的登入名 --> <filter> <filter-name>CASHttpServletRequestWrapperFilter</filter-name> <filter-class>org.jasig.cas.client.util.HttpServletRequestWrapperFilter</filter-class> </filter> <filter-mapping> <filter-name>CASHttpServletRequestWrapperFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!-- 將通過驗證後得到的Assertion 放入threadlocal --> <filter> <filter-name>CASAssertionThreadLocalFilter</filter-name> <filter-class>org.jasig.cas.client.util.AssertionThreadLocalFilter</filter-class> </filter> <filter-mapping> <filter-name>CASAssertionThreadLocalFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
以及在所有監聽器之前新增:
<!-- 用於單點退出,該過濾器用於實現單點登出功能,通知其他應用單點登出--> <listener> <listener-class>org.jasig.cas.client.session.SingleSignOutHttpSessionListener</listener-class> </listener>
其中casServerLoginUrl和casServerUrlPrefix要根據你的實際情況替換成合適的值,serverName是CAS客戶端的URL。另外,你應該根據業務的需要對受保護的資源實施登陸認證要求,這裡為了演示的方便,對所有資源的訪問請求都要求身份驗證.
將$CAS_CLIENT_HOME/modules/cas-client-core-3.2.1.jar
, $CAS_CLIENT_HOME/modules/cas-client-integration-atlassian-3.2.1.jar
複製到$CATALINA_HOME/webapps/examples/WEB-INF/lib
目錄中
把搭建CAS伺服器時產生的證書檔案(見這裡)匯入執行CAS客戶端的JVM證書庫
此外還要下載一個vt-servlet-filters-2.0.2.jar, common-logging-1.1.1.jar放到$CATALINA_HOME/webapps/examples/WEB-INF/lib
啟動tomcat, 訪問http://localhost:8080/examples。 第一次訪問時,瀏覽器會被重定向到CAS認證伺服器的登陸頁面,輸入使用者名稱和密碼並登陸成功後,瀏覽器會跳回http://localhost:8080/examples。後續訪問不需要重新登陸,直到CAS客戶端的session過期或使用者執行登出操作。
PHP
先定義一些環境變數
PHP_HOME: PHP安裝目錄(以php 5.5.1為例)
NGINX_HOME: nginx 安裝目錄(以nginx 1.4。1為例)
PHPCAS_HOME phpCAS客戶端安裝包解壓後的目錄(以phpCAS-1.3.2為例)。
注意: phpcas-1.3.2.tgz的目錄結構是這樣的:
· |-- CAS-1.3.2/ | |-- CAS | |-- docs | |-- CAS.php | |-- LICENSE | |-- NOTICE | `-- README.md `-- package.xml
需要將CAS-1.3.2/目錄下的所有內容拷貝到上一層目錄,即
· |-- CAS |-- docs |-- CAS.php |-- LICENSE |-- NOTICE |-- README.md `-- package.xml
安裝phpCAS客戶端
安裝phpCAS客戶端前,請先確保php.ini中配置了curl, openssl和zlib三個擴充套件。
這裡需要用到php官方提供的go-pear安裝指令碼。對於Linux的PHP,該指令碼在編譯安裝完成後位於$PHP_HOME/bin
目錄下;對於window的PHP,該指令碼可能沒在官方的發行包中,故需要先將 go-pear網頁的輸出另存為·go-pear.phar·檔案,然後在命令終端執行
php go-pear.phar
此時會顯示一些關於pear指令碼的安裝配置資訊,直接按回車完成。安裝完成後,會生成pear.bat
指令碼,把pear.bat
複製到%PHP_HOME%
目錄下。
安裝phpCAS
$PHP_HOME/bin/pear.sh install $PHPCAS_HOME/package.xml
Windows中則是:
%PHP_HOME%pear.bat install %PHPCAS_HOME%/package.xml
pear安裝指令碼會把phpCAS分成兩部分(執行庫和文件庫)進行安裝。在Linux中,預設會把phpCAS的執行庫安裝到$PHP_HOME/lib/php目錄中,把文件庫安裝到$PHP_HOME/lib/php/doc下;而Windows則把執行庫安裝到%PHP_HOME%/pear/下,把文件庫安裝到%PHP_HOME%/docs中.
配置phpCAS客戶端
phpcas自帶了一個演示例子(example_simple.php)下面我們以這個為例進行說明。
首先複製兩個樣板檔案到nginx的釋出目錄:
cp $PHPCAS_HOME/docs/examples/config.example.php $NGINX_HOME/html/config.php cp $PHPCAS_HOME/docs/examples/example_simple.php $NGINX_HOME/html/example_simple.php
根據實際情況,需要修改config.php
中的$phpcas_path
, $cas_host
, $cas_context
, $cas_port
, $cas_server_ca_cert_path
這幾個變數,其中
$phpcas_path 指向phpcas執行庫的根目錄(Linux中填入 $PHP_HOME/lib/php , windows中填入%PHP_HOME%/pear, 注意要把PHP_HOME替換為實際的路徑, 並且Windows中的路徑分割符要用雙反斜槓“\“)
$cas_host CAS認證伺服器的域名
$cas_port CAS認證伺服器的https埠
$cas_context CAS認證伺服器的上下文路徑(假如CAS認證伺服器的頁面登陸地址是https://localhost:8444/cas-server/login,那麼$cas_context就是cas-server)
$cas_server_ca_cert_path 指向CAS認證伺服器的安全證書(如果nginx應用伺服器和CAS認證伺服器不是部署在同一臺機,那麼要把該證書拷貝到nginx應用伺服器的機器上)
example_simple.php
給出phpCAS的基本使用方法,但example_simple.php沒有提供單點登出的配置方法。要支援單點登出,需要在phpCAS::setNoCasServerValidation();和phpCAS::forceAuthentication();這兩條語句之間加上:
phpCAS::handleLogoutRequests(false,true);
其中handleLogoutRequests的第一個引數表示當example_simple.php接收到CAS登出請求時,是否檢查該請求的客戶端。這主要是為了防止有其他人冒充CAS認證伺服器傳送登出請求。如果第一個引數為false,即表示example_simple.php不檢查客戶端,那麼第二個引數會被忽略。如果第一個引數為true,那麼第二個引數應該以陣列的形式列出哪些IP(或域名)的客戶端所傳送的登出請求會被處理。比如CAS的認證伺服器IP為192.168.121.130,那麼上述的程式碼可能改成:
phpCAS::handleLogoutRequest(true, ['192.168.121.130']);
測試
啟動nginx , 訪問http://localhost/example_simple.php。第一次訪問時,瀏覽器會被重定向到CAS認證伺服器的登陸頁面, 輸入使用者名稱和密碼併成功登陸後,瀏覽器跳回example_simple.php。後續訪問不需要重新登陸,直到CAS客戶端的session過期或使用者執行登出操作。
Django
環境
OS Windows 7(64位)
python 2.7.3(32位)
django 1.5.1
django_cas 2.1.1
假設上述環境已就緒,下面在一個臨時建立的django工程(E:\workspace\python_workspace\hello
, 記為%PROJ_DIR%)中說明如何使用django_cas。
配置
在開始之前,先修改django_cas的一個檔案。進入%PYTHON_HOME%/lib/site-packages/django_cas-2.1.1-py2.7.egg/django_cas
,開啟views.py
,將from django.http import
後面的get_host
刪去,並把檔案中所有的get_host(request)
替換為request.get_host()
開啟%PROJ_DIR%的專案配置檔案settings.py
.
在INSTALL_APPS配置項中追加'django_cas',
,如下圖所示:
INSTALLED_APPS = (
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.sites',
'django.contrib.messages',
'django.contrib.staticfiles',
# Uncomment the next line to enable the admin:
'django.contrib.admin',
# Uncomment the next line to enable admin documentation:
'django.contrib.admindocs',
'books',
'django_cas',
)
在MIDDLEWARE_CLASSES配置項的'django.contrib.auth.middleware.AuthenticationMiddleware'
後面新增'django_cas.middleware.CASMiddleware'
, ,如下面所示
MIDDLEWARE_CLASSES = (
'django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django_cas.middleware.CASMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
# Uncomment the next line for simple clickjacking protection:
'django.middleware.clickjacking.XFrameOptionsMiddleware',
)
在AUTHENTICATION_BACKENDS配置項的最後新增 'django_cas.backends.CASBackend'
, , 如下面所示
AUTHENTICATION_BACKENDS = (
'django.contrib.auth.backends.ModelBackend',
'django_cas.backends.CASBackend',
)
新增CAS_SERVER_URL配置項,該配置項的內容為CAS認證伺服器的預設地址,如下面所示
CAS_SERVER_URL='https://localhost:8443/cas-server/'
除此之外,還可以定義一些可選的配置項:
CAS_ADMIN_PREFIX: The URL prefix of the Django administration site. If undefined, the CAS middleware will check the view being rendered to see if it lives in django.contrib.admin.views`.
CAS_EXTRA_LOGIN_PARAMS: Extra URL parameters to add to the login URL when redirecting the user.
CAS_IGNORE_REFERER: If
True
, logging out of the application will always send the user to the URL specified by CAS_REDIRECT_URL.CAS_LOGOUT_COMPLETELY: If
False
, logging out of the application won't log the user out of CAS as well.CAS_REDIRECT_URL: Where to send a user after logging in or out if there is no referrer and no next page set. Default is
/
.CAS_RETRY_LOGIN: If
True
and an unknown or invalid ticket is received, the user is redirected back to the login page.CAS_VERSION: The CAS protocol version to use.
'1'
and'2'
are supported, with'2'
being the default.
定義登陸URL和登出URL所對應的檢視函式,比如
(r'^accounts/login/$', 'django_cas.views.login'),
(r'^accounts/logout/$', 'django_cas.views.logout'),
Play 1.2.x
Play 1.2.x提供了CAS客戶端模組支援. 首先開啟Play工程的依賴配置檔案conf/dependencies.yml, 新增模組引用宣告:
- play -> cas 1.3
在conf/routes中新增:
* / module:cas
然後執行play dependencies
,Play會把該模組下載並解壓到 /modules/cas-1.3. cas-1.3在conf/application.conf預設提供了一組配置示例,我們只需按照實際需要進行修改即可。下面是一個簡單配置的例子:
############################################################# # CAS CONFIGURATION ############################################################# cas.validateUrl=https://localhost:8443/cas/serviceValidate cas.loginUrl=https://localhost:8443/cas/login cas.logoutUrl=https://localhost:8443/cas/logout # 如果不使用代理模式,需要設定為空白 cas.proxyUrl= cas.gateway=false # play-cas模組可以為CAS伺服器提供mock支援. mock支援特性只能工作在DEV模式下 cas.mockserver=false # 如果使用mock支援,需要修改處理http請求的執行緒數 # play.pool=2 application.url.ssl=https://localhost:443 # 登陸成功後跳轉的首頁 application.url=http://localhost:9000
然後對需要身份認證的操作新增@With(controllers.modules.cas.SecureCAS.class)
註解,比如
@With(controllers.modules.cas.SecureCAS.class)
public class Application extends Controller {
public static void index() {
render();
}
public static void test(){
render();
}
}
這樣所有Application內的action請求都要先經過身份認證。
如果需要登陸後做進一步的許可權控制,可以在Controller或Action上新增@play.modules.cas.annotation.Check
註解,同時繼承controllers.modules.cas.Security
類並提供public static boolean check(String profile)
的實現,比如
@With(controllers.modules.cas.SecureCAS.class)
public class Application extends Controller {
@play.modules.cas.annotation.Check("role1")
public static void index() {
render();
}
public static void test(){
render();
}
}
public class MySecurity extends Security{
public static boolean check(String profile){
if ("role1".equals(profile)){
return isPermit(); // do whatever you want
}else{
return false;
}
}
}
對於通過身份驗證但沒有通過Security.check的請求,play-cas模組預設返回403響應,當然你也可以在Security子類提供自定義的onCheckFailed方法,返回一段描述性的文字。
更多高階用法,請參考這裡或play-cas的原始碼