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
中原來的attributeRepository
ben,替換為自定義的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>
修改地方:
- CAS Single Sign Out Filter【單點登出filter】:使用者退出cas的filter,需要將
casServerUrlPrefix
的value修改為cas服務端的地址。 - CAS Authentication Filter【單點登陸filter】:使用者登陸認證到cas的filter,需要將
casServerUrlPrefix
設定為cas服務端啟動地址,serverName設定為cas客戶端的啟動地址。 - 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
中設定的返回值:
對應到程式碼中:
三、自定義登陸介面
自定義登陸介面有兩種方式:
- 替換預設的頁面
- 建立主題目錄
方式一直接修改預設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多東西,只需要一個異常處理器就可以