1. 程式人生 > >【試水CAS-4.0.3】第08節_CAS客戶端配置單點登出

【試水CAS-4.0.3】第08節_CAS客戶端配置單點登出

本文內容包括配置單點登出、登出後自動跳轉指定資源、CASServer禁用單點登出等

/**
 * @see ------------------------------------------------------------------------------------------------------------------------
 * @see CAS客戶端配置單點登出
 * @see 與單點登入相對應,通過CASServer登出所有的CASClient,登入的URL是/login,登出的URL是/logout
 * @see 這裡需要配置SingleSignOutFilter和SingleSignOutHttpSessionListener
 * @see SingleSignOutFilter用來使Session失效,SingleSignOutHttpSessionListener用於在Session過期時移除其對應的對映關係
 * @see 1.要為SingleSignOutFilter配置casServerUrlPrefix引數
 * @see 2.預設的登出後會跳轉到CASServer的登出頁,若想跳轉到其它資源,可在/logout的URL後面加上service=you want to jump url
 * @see   比如http://sso.jadyer.com:8080/cas-server-web/logout?service=http://blog.csdn.net/jadyer
 * @see   但預設servcie跳轉不會生效,需要CASServer配置/WEB-INF/cas.properties中的cas.logout.followServiceRedirects=true
 * @see   另外為org.jasig.cas.client.session.SingleSignOutFilter增加service引數是沒用的,因為登出後跳轉到指定資源屬於服務端行為
 * @see 3.禁用單點登出
 * @see   CASServer/WEB-INF/cas.properties中的slo.callbacks.disabled=true
 * @see   測試時點選登出後雖然頁面跳轉到了預設登出頁,但再次訪問CASClient資源發現並沒有登出,即單點登出禁用成功
 * @see 4.測試單點登出
 * @see   測試時先登出,然後在瀏覽器新標籤頁訪問CASClient資源,發現會自動重定向到單點登入頁
 * @see   或者登出後,點瀏覽器後退按鈕,發現會後退到之前的CASClient資源頁,但在這個頁面點選任何請求,都會自動重定向到單點登入頁
 * @see ------------------------------------------------------------------------------------------------------------------------
 * @create 2015-7-27 下午4:30:14
 * @author 玄玉<http://blog.csdn.net/jadyer>
 */
下面是客戶端的web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" 
	xmlns="http://java.sun.com/xml/ns/javaee" 
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
	http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>classpath:applicationContext.xml</param-value>
	</context-param>
	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>
	
	<servlet>
		<servlet-name>SpringMVC</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<param-value>classpath:applicationContext.xml</param-value>
		</init-param>
	</servlet>
	<servlet-mapping>
		<servlet-name>SpringMVC</servlet-name>
		<url-pattern>/</url-pattern>
	</servlet-mapping>
	
	<filter>
		<filter-name>CharacterEncodingFilter</filter-name>
		<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
		<init-param>
			<param-name>encoding</param-name>
			<param-value>UTF-8</param-value>
		</init-param>
		<init-param>
			<param-name>forceEncoding</param-name>
			<param-value>true</param-value>
		</init-param>
	</filter>
	<filter-mapping>
		<filter-name>CharacterEncodingFilter</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>

	<!-- SSO -->
	<listener>
		<listener-class>org.jasig.cas.client.session.SingleSignOutHttpSessionListener</listener-class>
	</listener>
	<filter>
		<filter-name>casSingleSignOutFilter</filter-name>
		<filter-class>org.springframework.web.filter.DelegatingFilterProxy</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.springframework.web.filter.DelegatingFilterProxy</filter-class>
	</filter>
	<filter-mapping>
		<filter-name>casAuthenticationFilter</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>
	<filter>
		<filter-name>casTicketValidationFilter</filter-name>
		<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
	</filter>
	<filter-mapping>
		<filter-name>casTicketValidationFilter</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>
	<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>
	<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>
</web-app>
下面是客戶端的//src//applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:mvc="http://www.springframework.org/schema/mvc"
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
						http://www.springframework.org/schema/beans/spring-beans-3.2.xsd 
						http://www.springframework.org/schema/mvc
						http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd">
	<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
		<property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE"/>
		<property name="ignoreResourceNotFound" value="false"/>
		<property name="locations">
			<list>
				<value>classpath:config.properties</value>
			</list>
		</property>
	</bean>
	<mvc:resources mapping="/index.jsp" location="/index.jsp"/>
	
	<!-- cas -->
	<bean name="casSingleSignOutFilter" class="org.jasig.cas.client.session.SingleSignOutFilter">
		<property name="casServerUrlPrefix" value="${casServerUrlPrefix}"/>
	</bean>
	<bean name="casAuthenticationFilter" class="org.jasig.cas.client.authentication.AuthenticationFilter">
		<property name="serverName" value="${casClientServerName}"/>
		<property name="casServerLoginUrl" value="${casServerLoginUrl}"/>
	</bean>
	<bean name="casTicketValidationFilter" class="org.jasig.cas.client.validation.Cas20ProxyReceivingTicketValidationFilter">
		<property name="serverName" value="${casClientServerName}"/>
		<property name="ticketValidator">
			<bean class="org.jasig.cas.client.validation.Cas20ServiceTicketValidator">
				<constructor-arg index="0" value="${casServerUrlPrefix}"/>
			</bean>
		</property>
	</bean>
</beans>
下面是//src//config.properties
#<<Central Authentication Service>>
#where to logout
casServerLogoutUrl=http://sso.jadyer.com:8080/cas-server-web/logout
#where to login
casServerLoginUrl=http://sso.jadyer.com:8080/cas-server-web/login
#login server root
casServerUrlPrefix=http://sso.jadyer.com:8080/cas-server-web
#who am i
casClientServerName=http://boss.jadyer.com:8080
下面是//WebRoot//index.jsp
<%@ page pageEncoding="UTF-8"%>
<%@ page import="java.util.Map"%>
<%@ page import="java.net.URLDecoder"%>
<%@ page import="com.jadyer.util.ConfigUtil"%>
<%@ page import="org.jasig.cas.client.util.AssertionHolder"%>
<%@ page import="org.jasig.cas.client.authentication.AttributePrincipal"%>

<script>
function ssoLogout(){
	if(confirm('確定要退出系統嗎?')){
		//top.location.href ='http://sso.jadyer.com:8080/cas-server-web/logout?service=http://blog.csdn.net/jadyer';
		//top.location.href ='http://sso.jadyer.com:8080/cas-server-web/logout?service=http://sso.jadyer.com:8080/cas-server-web/login';
		top.location.href ='<%=ConfigUtil.INSTANCE.getProperty("casServerLogoutUrl")%>';
	}
}
</script>

<body style="background-color:#CBE0C9;">
	<span style="color:red; font-size:32px; font-weight:bold;">客戶端登入成功</span>
	<br>
	<br>
	<a href="javascript:ssoLogout();">我要登出</a>
</body>

<hr size="2">

<%
	AttributePrincipal principal = (AttributePrincipal)request.getUserPrincipal();
	Map<String, Object> attributes = principal.getAttributes();
	out.print("principal.getName()=" + principal.getName() + "<br/>");
	out.print("request.getRemoteUser()=" + request.getRemoteUser() + "<br/>");
	out.print("登入使用者:" + attributes.get("userId") + "<br/>");
	out.print("登入時間:" + AssertionHolder.getAssertion().getAuthenticationDate() + "<br/>");
	out.print("-----------------------------------------------------------------------<br/>");
	for(Map.Entry<String,Object> entry : attributes.entrySet()){
		//服務端返回中文時需要encode,客戶端接收顯示中文時需要decode,否則會亂碼
		out.print(entry.getKey() + "=" + URLDecoder.decode(entry.getValue().toString(), "UTF-8") + "<br/>");
	}
	out.print("-----------------------------------------------------------------------<br/>");
	Map<String, Object> attributes22 = AssertionHolder.getAssertion().getAttributes();
	for(Map.Entry<String,Object> entry : attributes22.entrySet()){
		out.print(entry.getKey() + "=" + entry.getValue() + "<br/>");
	}
	out.print("-----------------------------------------------------------------------<br/>");
	Map<String, Object> attributes33 = AssertionHolder.getAssertion().getPrincipal().getAttributes();
	for(Map.Entry<String,Object> entry : attributes33.entrySet()){
		out.print(entry.getKey() + "=" + entry.getValue() + "<br/>");
	}
%>
最後是讀取配置檔案的工具類ConfigUtil.java
package com.jadyer.util;

import java.io.IOException;
import java.util.Properties;
import java.util.regex.Pattern;

/**
 * 配置檔案讀取工具類
 * @see -----------------------------------------------------------------------------------------------------------
 * @see 用法為ConfigUtil.INSTANCE.getProperty("KJJF.databaseURL")
 * @see 採用列舉的方式,也是Effective Java作者Josh Bloch提倡的方式,它不僅能避免多執行緒同步問題,而且還能防止反序列化重新建立新的物件
 * @see -----------------------------------------------------------------------------------------------------------
 * @version v2.1
 * @history v2.1-->增加<code>getPropertyBySysKey()</code>方法,用於獲取配置檔案的鍵值中含系統屬性時的值,詳見該方法註釋
 * @history v2.0-->採用列舉的方式實現單例
 * @history v1.0-->通過內部類實現單例
 * @update 2015-2-2 下午05:22:03
 * @create Jun 7, 2012 5:30:10 PM
 * @author 玄玉<http://blog.csdn.net/jadyer>
 */
public enum ConfigUtil {
	INSTANCE;
	
	private Properties config;
	
	private ConfigUtil(){
		config = new Properties();
		try {
			config.load(ConfigUtil.class.getResourceAsStream("/config.properties"));
			System.out.println("Load /config.properties SUCCESS...");
		} catch (IOException e) {
			System.out.println("Load /config.properties Error...");
			e.printStackTrace();
			throw new ExceptionInInitializerError("載入系統配置檔案失敗...");
		}
	}

	public String getProperty(String key){
		return config.getProperty(key);
	}
	
	public int getPropertyForInt(String key){
		return Integer.parseInt(config.getProperty(key));
	}
	
	/**
	 * 配置檔案的鍵值中含系統屬性時的獲取方式
	 * @see 若配置檔案的某個鍵值含類似於${user.dir}的寫法,如log=${user.dir}/app.log
	 * @see 則可以通過該方法使用系統屬性中user.dir的值,替換掉配置檔案鍵值中的${user.dir}
	 * @create 2015-2-2 下午05:22:03
	 * @author 玄玉<http://blog.csdn.net/jadyer>
	 */
	public String getPropertyBySysKey(String key){
		String value = config.getProperty(key);
		if(null!=value && Pattern.compile("\\$\\{\\w+(\\.\\w+)*\\}").matcher(value).find()){
			String sysKey = value.substring(value.indexOf("${")+2, value.indexOf("}"));
			value = value.replace("${"+sysKey+"}", System.getProperty(sysKey));
		}
		return value;
	}
}

相關推薦

CAS-4.0.308_CAS客戶配置登出

本文內容包括配置單點登出、登出後自動跳轉指定資源、CASServer禁用單點登出等 /** * @see ------------------------------------------------------------------------------

CAS-4.0.307_CAS客戶配置登入

完整版見https://jadyer.github.io/2015/07/26/sso-cas-client-login/ /** * @see CAS客戶端配置 * @see -------------------------------------------

CAS-4.0.306_CAS服務配置HTTPS

/** * @see CAS服務端配置HTTPS * @see ----------------------------------------------------------------------------------------------------

CAS-4.0.302_CAS服務登入頁個性化

/** * @see ------------------------------------------------------------------------------------------------------------------------

基於CAS登入SSO[4]: 加入兩個CAS客戶測試登入

基於CAS的單點登入SSO[4]: 加入兩個CAS客戶端測試單點登入 作者:家輝,日期:2017-08-22 CSDN部落格: http://blog.csdn.net/gobitan 摘要:本系列的前三篇文章分別搭建了基於CAS的單點登入伺服器,並讓伺

SpringCloudRibbon如何自定義客戶配置和全域性配置

起因 事情的起因是這樣的,公司內部要實現基於Zuul閘道器的灰度路由,在上線時進行灰度測試,故需要配置業務微服務向Eureka註冊的metadata元資料,和自定義Ribbon的負載規則達到只訪問灰度服務的目的。這樣就需要自定義Ribbon的IRule,實現灰度請求只會負載到帶有灰度標籤元資料的業務微服務上,

讀書筆記The Swift Programming Language (Swift 4.0.3)

code any 是個 重建 之一 eric esc 傳值 特定 素材:Language Guide 初次接觸 Swift,建議先看下 A Swift Tour,否則思維轉換會很費力,容易卡死或鉆牛角尖。 同樣是每一章只總結3個自己認為最重要的點。這樣挺好!強迫你去思考去取

Maven的overlay外掛的用法結合cas4.0.3

overlay外掛是使用者多個web專案的war包合併,被依賴的war包會根據pom中的配置以及主專案的現有檔案進行合併。用途:1.大型web專案的並行開發。在分散式的趨勢下,這個用途應該不多了。2.基於他人專案的修改,比如:cas本身用來做登陸許可權的中央認證,其中專案原始碼非常之

CAS登入(3):cas-4.0.0 客戶配置

新建web工程 新增依賴jar包 cas-client-core-3.2.1.jar commons-logging-1.2.jar Tips: Maven專案直接新增Pom: <dependency> <grou

Ubuntu-opencv3.4.0-Error對‘cv::Mat::updateContinuityFlag()’未定義的引用

/path/libTrackKcf.a(kcftracker.cpp.o):在函式‘ot::KCFTracker::KCFTracker(bool, bool, bool, bool)’中: kcftracker.cpp:(.text+0x673):對‘cv::Mat::up

CAS 4.0 配置開發手冊

tab mysql 獲得 secure enter max 否則 exceptio track 1 下載 地址http://downloads.jasig.org/ cas-server-4.0.0-release.tar.gz cas-client-3.3.3-

NHibernte 4.0.3版本中,使用Queryover().Where().OrderBy().Skip().Take()方法分頁獲取數據失敗

osi ber modal str 問題 res tor 獲取數據 max 問題代碼如下: var result=repository.QueryOver<modal>() .Where(p=>p.Code==Code)

CQ18高一暑假前挑戰賽3標程

暑假 spa unsigned bound signed i++ 暴力 ins () 【A:LCM】 #include<bits/stdc++.h> using namespace std; #define ll long long int main

5196. NOIP2017提高組模擬7.3B (Standard IO)

solution spa bsp NPU fill ron 統計 class qsort Description 給出一棵樹,求出最小的k,使得,且在樹中存在路徑P,使得k>=S且k<=E。(k為路徑P的邊的權值和) Input

人臉檢測——基於機器學習3AdaBoost算法

源代碼 夠快 等等 多個 利用 原理 設計 聯結 大量 簡介 主要工作 AdaBoost算法的人臉檢測算法包含的主要工作:(1)通過積分圖快速求得Haar特征;(2)利用AdaBoost算法從大量的特征中選擇出判別能力較強的少數特征用於人臉檢測分類;(3)提出一個

NOIP2018模擬賽2018.10.3track

題目 題解 –開始以為和那個什麼括號匹配一樣,結果要判重,(QAQ) 結果其實是kmp字串匹配 設f[i][j][k]:第i秒時,高度為j,成功匹配第k個的方案數 狀態轉移方程式 if(s[k]==‘U’){ f[i+1][j+1][k+1]=(f[i+1][j+1

NOIP2018模擬賽2018.10.3到不了

題目 題解 –大佬都用lct,像我這種弱雞就只有用一種神奇的做法了 首先離線 直接把最後的森林處理出來(並查集) 再跟著修改順序,在這些樹上跳lca 但是這不一定是最後的答案(因為樹不一定就是最後的樣子了) 所以我們還要用當前的真實根來判斷一下: 如果真實根和這兩個

MongoDB走過的坑(4.0.3版本)

資料儲存一般使用本地或者儲存在資料庫,MongoDB是一個非關係型資料庫,今天小結下走過的一些坑。 1、網上的很多教程對自己無效 解決方法:這種情況一般都是和版本有關係,資料庫在不斷的更新發展,很多東西可能發生變化,建議找教程的時候按照特定的版本進行查詢,否則很容易就入坑了 2、以前安裝過的MongoD

4.0.3的mongodb 安裝和java使用

一 整合 由於本人的碼雲太多太亂了,於是決定一個一個的整合到一個springboot專案裡面。 附上自己的github專案地址 https://github.com/247292980/spring-boot 附上彙總博文地址 https://www.cnblogs.com/ydymz/p/939165

macOS(Mojave10.14.1)安裝MongoDB 4.0.3

安裝 通過homebrew 安裝,安裝命令:  brew install mongodb      配置 建立資料夾/usr/local/MongoDB/data 存放資料庫資料 建立資料夾/usr/local/MongoDB/log/mongodb.log 存放日