1. 程式人生 > >CAS4.0.3服務的搭建實戰二【自定義登陸介面、登陸驗證、返回使用者資訊】

CAS4.0.3服務的搭建實戰二【自定義登陸介面、登陸驗證、返回使用者資訊】

一切技術框架都會有一個使用者自定義的入口檔案,cas中自定義配置檔案在deployerConfigContext.xml中。

一、自定義登陸驗證

  • Tips:本專案使用mysql資料庫,因此已經在pom中匯入mysql的驅動。
    開啟deployerConfigContext.xml,找到如下程式碼:
    <bean id="authenticationManager" class="org.jasig.cas.authentication.PolicyBasedAuthenticationManager">
        <
constructor-arg
>
<map> <!-- | IMPORTANT | Every handler requires a unique name. | If more than one instance of the same handler class is configured, you must explicitly | set its name to something other than its default name (typically the simple class name). -->
<entry key-ref="proxyAuthenticationHandler" value-ref="proxyPrincipalResolver" /> <entry key-ref="primaryAuthenticationHandler" value-ref="primaryPrincipalResolver" /> </map> </constructor-arg>

其中primaryAuthenticationHandler

為自定義登陸驗證,primaryPrincipalResolver為定義的返回屬性。
找到primaryAuthenticationHandler的定義位置,發現賬號密碼:casuser/Mellon是寫死在裡面的:

    <bean id="primaryAuthenticationHandler"
          class="org.jasig.cas.authentication.AcceptUsersAuthenticationHandler">
        <property name="users">
            <map>
                <entry key="casuser" value="Mellon"/>
            </map>
        </property>
    </bean>

進入AcceptUsersAuthenticationHandler這個類,發現只需要繼承改抽象類實現抽象方法authenticateUsernamePasswordInternal即可,如圖:
在這裡插入圖片描述
建立自己的UsersAuthenticationHandler類,實現抽象方法:

protected HandlerResult authenticateUsernamePasswordInternal(UsernamePasswordCredential credential) throws GeneralSecurityException, PreventedException {
        String username=credential.getUsername();
        String password=credential.getPassword();

        System.out.println("username=["+username+"]  password=["+password+"]");
        //自定義jdbc驗證
        DriverManagerDataSource dataSource=new DriverManagerDataSource();
        dataSource.setDriverClassName("com.mysql.jdbc.Driver");
        dataSource.setUrl("jdbc:mysql://localhost:3306/sso_user?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&useSSL=false&serverTimezone=UTC");
        dataSource.setUsername("root");
        dataSource.setPassword("123456");
        JdbcTemplate jdbcTemplate = new JdbcTemplate();
        jdbcTemplate.setDataSource(dataSource);

        String sql="SELECT * FROM user WHERE username = ?";
        System.out.println(sql);
        User info = (User) jdbcTemplate.queryForObject(sql, new Object[]{username}, new BeanPropertyRowMapper(User.class));
        System.out.println("database username : "+ info.getUsername());
        System.out.println("database password : "+ info.getPassword());
        if (info==null){
            throw new AccountException("使用者不存在");
        }else {
            System.out.println(info);
        }

        if (!info.getPassword().equals(password)){

            System.out.println("dateSourcePassword=["+info.getPassword()+"]");
            throw  new FailedLoginException("密碼錯誤");
        }else{
               return  createHandlerResult(credential,new SimplePrincipal(username),null);
        }
    }            

最後將該bean注入在deployerConfigContext.xml中,並註釋掉原來的proxyPrincipalResolver

<!--自己的登陸驗證類-->
    <bean id="proxyPrincipalResolver"
          class="org.jasig.cas.authentication.principal.BasicPrincipalResolver" />

當然這是最原始的方式,你也可以在spring-configuration/applicationContext.xml配置包掃描package-scan,以註解形式注入自定義的bean,或者資料來源等等。
開啟web.xml,可以看到:
在這裡插入圖片描述
滿足上述要求的配置檔案都會被spring載入進去

查詢AbstractUsernamePasswordAuthenticationHandler的子類發現有很多類可以繼承,如圖:
在這裡插入圖片描述
推薦去繼承第一個AbstractJdbcUsernamePasswordAuthenticationHandler,初始化時候將對應資料來源注入進來即可。

二、自定義返回使用者資訊

deployerConfigContext.xml找到primaryPrincipalResolver這個bean的定義:

<bean id="primaryPrincipalResolver"
          class="org.jasig.cas.authentication.principal.PersonDirectoryPrincipalResolver" >
        <property name="attributeRepository" ref="attributeRepository" />
    </bean>

    <!--
    Bean that defines the attributes that a service may return.  This example uses the Stub/Mock version.  A real implementation
    may go against a database or LDAP server.  The id should remain "attributeRepository" though.
    +-->
    <bean id="attributeRepository" class="org.jasig.services.persondir.support.StubPersonAttributeDao"
            p:backingMap-ref="attrRepoBackingMap" />
    
    <util:map id="attrRepoBackingMap">
        <entry key="uid" value="uid" />
        <entry key="eduPersonAffiliation" value="eduPersonAffiliation" /> 
        <entry key="groupMembership" value="groupMembership" />
    </util:map>

其中attributeRepository用來返回使用者私有資訊的bean,同樣的進入該類:
在這裡插入圖片描述
通過debug模式可以發現是通過getPerson方法返回的使用者私有資訊。因此可以通過建立自己的類去繼承StubPersonAttributeDao重寫getPerson方法,來返回自定義使用者資訊的目的:

public class UserStubPersonAttributeDao extends StubPersonAttributeDao {
    @Override
    public IPersonAttributes getPerson(String uid) {
        Map<String, List<Object>> attributes=new HashMap<String, List<Object>>();
        attributes.put("userId", Collections.singletonList((Object) uid));
        attributes.put("ServerTime", Collections.singletonList((Object) new Date()));
        attributes.put("defuatName", Collections.singletonList((Object) "siwash"));
        return new AttributeNamedPersonImpl(attributes);
    }
}

同時註釋掉deployerConfigContext.xml中原來的attributeRepositoryben,替換為自定義的bean:

  <bean id="attributeRepository" class="rpf.authentication.UserStubPersonAttributeDao"/>

最後進入:WEB-INF/view/jsp/protocol/2.0/casServiceValidationSuccess.jsp,做如下修改:

<cas:serviceResponse xmlns:cas='http://www.yale.edu/tp/cas'>
	<cas:authenticationSuccess>
		<cas:user>${fn:escapeXml(assertion.primaryAuthentication.principal.id)}</cas:user>
        <c:if test="${not empty pgtIou}">
        		<cas:proxyGrantingTicket>${pgtIou}</cas:proxyGrantingTicket>
        </c:if>
        <c:if test="${fn:length(assertion.chainedAuthentications) > 1}">
		  <cas:proxies>
            <c:forEach var="proxy" items="${assertion.chainedAuthentications}" varStatus="loopStatus" begin="0" end="${fn:length(assertion.chainedAuthentications)-2}" step="1">
			     <cas:proxy>${fn:escapeXml(proxy.principal.id)}</cas:proxy>
            </c:forEach>
		  </cas:proxies>
        </c:if>

		<c:if test="${fn:length(assertion.chainedAuthentications[fn:length(assertion.chainedAuthentications)-1].principal.attributes) > 0}">
			<cas:attributes>
				<c:forEach var="attr" items="${assertion.chainedAuthentications[fn:length(assertion.chainedAuthentications)-1].principal.attributes}">
					<cas:${fn:escapeXml(attr.key)}>${fn:escapeXml(attr.value)}</cas:${fn:escapeXml(attr.key)}>
				</c:forEach>
			</cas:attributes>
		</c:if>
	</cas:authenticationSuccess>
</cas:serviceResponse>

說明:

  • 2.0資料夾代表validation後,返回的報文協議用的是protocol 2.0。
  • 新增部分只是讓預設只顯示使用者id變為顯示使用者所有資訊。

cas簡易客戶端下載地址:https://github.com/cas-projects/cas-sample-java-webapp

客戶端配置
將下載的cas-sample-java-webapp匯入idea,開啟webapp下的web.xml:

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">

<!--
   <context-param>
       <param-name>renew</param-name>
       <param-value>true</param-value>
   </context-param>
-->

    <filter>
        <filter-name>CAS Single Sign Out Filter</filter-name>
        <filter-class>org.jasig.cas.client.session.SingleSignOutFilter</filter-class>
        <init-param>
            <param-name>casServerUrlPrefix</param-name>
            <param-value>https://sso.siwash.net:8443/siwash-auth</param-value>
        </init-param>
    </filter>

    <listener>
        <listener-class>org.jasig.cas.client.session.SingleSignOutHttpSessionListener</listener-class>
    </listener>

    <filter>
        <filter-name>CAS Authentication Filter</filter-name>
        <!--<filter-class>org.jasig.cas.client.authentication.Saml11AuthenticationFilter</filter-class>-->
        <filter-class>org.jasig.cas.client.authentication.AuthenticationFilter</filter-class>
        <init-param>
            <param-name>casServerLoginUrl</param-name>
            <param-value>https://sso.siwash.net:8443/siwash-auth</param-value>
        </init-param>
        <init-param>
            <param-name>serverName</param-name>
            <param-value>http://client.siwash.net:8082</param-value>
        </init-param>
    </filter>

    <filter>
        <filter-name>CAS Validation Filter</filter-name>
        <!--<filter-class>org.jasig.cas.client.validation.Saml11TicketValidationFilter</filter-class>-->
        <filter-class>org.jasig.cas.client.validation.Cas20ProxyReceivingTicketValidationFilter</filter-class>
        <init-param>
            <param-name>casServerUrlPrefix</param-name>
            <param-value>https://sso.siwash.net:8443/siwash-auth</param-value>
        </init-param>
        <init-param>
            <param-name>serverName</param-name>
            <param-value>http://client.siwash.net:8082</param-value>
        </init-param>

    </filter>

    <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 Single Sign Out Filter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <filter-mapping>
        <filter-name>CAS Validation Filter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <filter-mapping>
        <filter-name>CAS Authentication Filter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <filter-mapping>
        <filter-name>CAS HttpServletRequest Wrapper Filter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <welcome-file-list>
        <welcome-file>
            index.jsp
        </welcome-file>
    </welcome-file-list>
</web-app>

修改地方:

  1. CAS Single Sign Out Filter【單點登出filter】:使用者退出cas的filter,需要將casServerUrlPrefix的value修改為cas服務端的地址。
  2. CAS Authentication Filter【單點登陸filter】:使用者登陸認證到cas的filter,需要將casServerUrlPrefix設定為cas服務端啟動地址,serverName設定為cas客戶端的啟動地址。
  3. CAS Validation Filter【校驗filter】:使用者登陸成功或者已經登陸後會在瀏覽器cookie中儲存一個ticket,客戶端首先會向cas服務中心傳送一個類似的請求:
https://sso.siwash.net:8443/cas/serviceValidate?ticket=xxxx&service=客戶端地址

cas認證後發現無效或客戶端讀取不到ticket則會被重定向到登陸介面進行登陸。因此這部分也需要同CAS Authentication Filter置為cas服務端啟動地址,serverName設定為cas客戶端的啟動地址。
同時根據該filter指定的類名:<filter-class>org.jasig.cas.client.validation.Cas20ProxyReceivingTicketValidationFilter</filter-class>,也可以看出確實是用打protocol 2.0的報文協議。

我為什麼說是報文協議?

首先進入Cas20ProxyReceivingTicketValidationFilter中找到doFilter方法,定位到如下程式碼:
在這裡插入圖片描述
打上斷點執行後,進入validate方法,執行到如下位置:
在這裡插入圖片描述
serverResponse的值copy出來,格式化一下就是:

<cas:serviceResponse xmlns:cas='http://www.yale.edu/tp/cas'>
	<cas:authenticationSuccess>
		<cas:user>mrfox</cas:user>	
			<cas:attributes>				
					<cas:defuatName>siwash</cas:defuatName>			
					<cas:ServerTime>Fri Nov 23 16:47:22 CST 2018</cas:ServerTime>				
					<cas:userId>mrfox</cas:userId>		
			</cas:attributes>
	</cas:authenticationSuccess>
</cas:serviceResponse>

結合前面casServiceValidationSuccess.jsp中的修改來看,確實是利用jsp的語法生成xml節點作為返回資料的報文。

成功登陸後,客戶端獲取到的使用者屬性,也就是在UserStubPersonAttributeDao 中設定的返回值:
在這裡插入圖片描述
對應到程式碼中:
在這裡插入圖片描述

三、自定義登陸介面

自定義登陸介面有兩種方式:

  1. 替換預設的頁面
  2. 建立主題目錄
    方式一直接修改預設webapp\WEB-INF\view\jsp\default下的casLoginView.jsp檔案
    方式二稍微麻煩點:首先開啟WEB-INF下的cas.properties,修改cas.viewResolver.basename為自己的主題檢視
    在這裡插入圖片描述
    在resources下複製一份default_views.properties改名為自己的主題.properties:
    在這裡插入圖片描述
    然後進入WEB-INF下的view/jsp/default,將default檔案拷貝一份,並取個好聽的名字如下:
    在這裡插入圖片描述
    接下來,進入剛才建立的主題配置檔案,將所有的jsp路徑,改成你自己的:
    在這裡插入圖片描述
    最後再到自己的主題view下修改一個叫casLoginView.jsp的檔案,你也可以在自己的主題配置檔案中把casLoginView.url修改成你自己的:
    casLoginView.(class)=org.springframework.web.servlet.view.JstlView
    casLoginView.url=/WEB-INF/view/jsp/rpfView/login.jsp

具體修改內容如下:

<div class="container">
		<div class="row">
			<div class="col-md-offset-3 col-md-6">
				<form:form method="post
            
           

相關推薦

CAS4.0.3服務搭建實戰定義登陸介面登陸驗證返回使用者資訊

一切技術框架都會有一個使用者自定義的入口檔案,cas中自定義配置檔案在deployerConfigContext.xml中。 一、自定義登陸驗證 Tips:本專案使用mysql資料庫,因此已經在pom中匯入mysql的驅動。 開啟deployerConfigCo

CAS4.0.3服務搭建實戰編寫shiro-cas客戶端

shiro與cas可以實現無縫的整合,只需要加入幾個依賴的jar包,修改部分shiro的配置檔案,定義一個自己的casRealm 專案結構 一、在pom中加入cas相關依賴 <dependency> <groupId>org

CAS4.0.3服務搭建實戰基於普通web專案

一、從官網下載對應的war包 1.地址一:https://github.com/apereo/cas/releases/tag/v4.0.3 2.地址二:http://central.maven.org/maven2/org/jasig/cas/cas-server-webapp/4.0

Zabbix 3.0入門到企業實戰(zabbix介紹與安裝)

分布 1.2 網絡狀態 需要 服務端 mysql 軟件 組織 lar Zabbix的簡介 1.1 什麽是zabbix? Zabbix是一個基於Web界面的分布式系統監控的企業級開源軟件。可以監視各種系統與設備的參數,保障服務器及設備的安全運營。Zabbix是一個

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

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

服務springboot視訊最新SpringBoot2.0.3版本技術視訊教程免費學習

超火爆的springboot微服務技術怎麼學,看這裡,springboot超詳細的教程↓↓↓↓↓↓https://ke.qq.com/course/179440?tuin=9b386640 01.springboot介紹02.微服務介紹03.springboot第一個例子04.Springboot中的常用註解

Nuget私有服務搭建實戰

web項目 每次 問題 ref 版本 -c .com www. pack 最近更新了Nuget私有服務器的版本,之前是2.8.5,現在是2.11.3。 Nuget服務器的搭建,這裏有篇很詳細的文章,跟著弄就好了: https://docs.microsoft.com/e

SpringCloud微服務搭建實戰

SpringCloud微服務架構搭建 什麼是微服務?     '微',顧名思義,就是小的意思。意指將一個模組按其業務功能來拆分為多個模組,每個模組之間相互獨立,各司其職,類似於單一職責原則。每個模組就是一個服務,它們之間不相互依賴,可以獨立成功啟動、部署及測試。服務之

函式計算搭建 Serverless Web 應用()- 定義域名

摘要: 繫結自定義域名可以允許使用者通過自定義域名訪問 FC 的函式,配合 HTTP 觸發器使用,為使用函式計算搭建 Web 應用提供便利。 簡介阿里雲 函式計算(Function Compute) 是事件驅動的全託管計算服務,是阿里雲的 Serverless 計算平臺。基於函式計算構建應用,您無需管理伺服

定義檢視控制元件實戰篇--支援滑動和動畫的開關按鈕(SwitcheButton)

菜鳥日記: 之前嘗試去了解繼承View實現自定義檢視控制元件,學習了通過程式碼確實可以繪製一些:字元,幾何圖形。但是正真開發中我們可能做不到精確繪製圖形。想想工作量就很頭大。所以通過美術圖片來實現控制元件的內容是很明智便捷的達到目的的好辦法。現在我們就來看看用點陣圖資源來實

Spring Boot實現OAuth 2.0)-- 定義許可權驗證

自定義攔截器進行許可權驗證 涉及到的姿勢: 自定義註解 攔截器 Spring Boot新增攔截器 文章目錄: 自定義註解 @Target(ElementType.METHOD)//作用在方法 @Retention(RetentionP

springCloud微服務系列——OAuth2+JWT模式下的資源伺服器獲得定義資訊

       回過頭來說一下資源伺服器的問題點吧,這裡OAuth2+JWT用的是spring security,具體怎麼用spring security搭建資源伺服器我就不說了。這裡要討論的問題是這樣的,我們希望在spring mvc中,直接通過如下的形式獲得登入使用者資訊@

ToastCustom定義顯示風格的Toast

結構圖 iyu chan .cn 崩潰 頂部 組織 繼承 guid 版權聲明:本文為博主原創文章,未經博主允許不得轉載。 前言 基於系統Toast的自定義顯示風格的Toast。 效果圖 代碼分析 ToastCustom類基於系統Toast,不是繼承Toas

Hadoop實戰-Flume之定義Sink(十九)

current ioe back urn oop print out java try import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream;

NancyFx 2.0的開源框架的使用-CustomModule(定義模塊)

nuget eat ews pub 技術分享 continue for eth color NancyFx框架的自定義模塊 新建一個空的Web項目 然後通過NuGet庫安裝下面的包 Nancy Nancy.Hosting.Aspnet 然後添

TabTopAutoLayout定義頂部選項卡區域(帶下劃線)(動態選項卡數據且可滑動)

註意事項 ecif margin 代碼分析 獨立 xml文件 回收 support mtab 版權聲明:本文為博主原創文章,未經博主允許不得轉載。 前言 自定義頂部選項卡布局LinearLayout類,實現帶下劃線且可滑動效果。【實際情況中建議使用RecyclerVie

Zabbix():定義腳本遠程命令報警升級測試實例

zabbix1.自定義腳本Zabbix中有統一的報警腳本存放路徑,即:/usr/lib/zabbix/alertscripts。[root@zrs1 ~]# cd /usr/lib/zabbix/alertscripts/ [root@zrs1 alertscripts]# vim mailalert.sh

JSP第六篇定義標簽之傳統標簽

abstract error 重寫 ren flush zhong pwrite out b2c 為什麽要使用自定義標簽? JSTL標簽庫只提供了簡單的輸出等功能,沒有實現任何的HTML代碼封裝,並且某些復雜類型轉換,或者邏輯處理的時候,JSTL標簽庫完成不了,需要自定義標

Java排序方法--List,數組,定義繼承Comparable和Comparator

pri locale student ide abcdefg 接口 com main object (一)list和數組 ①List默認排序代碼: public static void main(String[] args) { List<String>

SpringMVC(十定義異常處理器 HandlerExceptionResolver(接口)

pin org ota admin pack property framework ase exception 自定義異常處理器和系統異常處理器的提升版可以實現相同的功能,但是使用的方法不同,自定義異常處理器可以不用在配置文件中配置name多東西,只需要一個異常處理器就可以