最近研究了一下SSO(Single Sign On:單點登陸)原理。
因而想借助CAS(基於SSO原理的實現框架)加深一下理解同時參考一下具體代碼實現,所以有了此係列文章。
先從CAS-CLIENT提及。web
假設你已經掌握瞭如何在你的web項目中引入CAS。咱們以AuthenticationFilter爲例,說一說它是如何從初始化的。spring
在web項目中的web.xml文件中咱們一般經過以下方式進行spring和cas的整合:tomcat
<bean id="authenticationFilter" class="org.jasig.cas.client.authentication.AuthenticationFilter"> <property name="casServlerLoginUrl">xxx</property> <property name="serverName">xxx</property> </bean>
<filter> <filter-name>casAuthenticationFilter</filter-name> <filter-class> org.springframework.web.filter.DelegatingFilterProxy </filter-class> <init-param> <param-name>targetBeanName</param-name> <param-value>authenticationFilter</param-value> </init-param> </filter> <filter-mapping> <filter-name>casAuthenticationFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
能夠看到引入了一個名爲DelegatingFilterProxy的Filter。那咱們來看一下該類的源碼:app
public class DelegatingFilterProxy extends GenericFilterBean { private String contextAttribute;//上下文屬性,尋找WebApplicationContext private WebApplicationContext webApplicationContext;//web上下文 private String targetBeanName;//被委託的Filter的名字,若是沒有指定,則使用DelegatingFilterProxy對應的Filter的name,即上面的<filter-name>標籤的內容。 private boolean targetFilterLifecycle;//是不是目標Filter的生命週期,默認爲false,即由Spring來管理Filter的生命週期,不然由Servlet來管理。 private Filter delegate;//被委託的過濾器 private final Object delegateMonitor;//監視器 ...
該類是實現了Filter接口並交由spring管理的servlet過濾器的代理類。
由於這個類也是實現了Filter接口,因此在tomcat容器初始化是會執行init(FilterConfig)方法。該方法來自其父類GenericFilterBean,來看代碼:框架
public final void init(FilterConfig filterConfig) throws ServletException { ... this.filterConfig = filterConfig; ... this.initFilterBean(); }
注意到this.initFilterBean(),該方法來自DelegatingFilterProxy,看源碼:學習
protected void initFilterBean() throws ServletException { ... WebApplicationContext wac = this.findWebApplicationContext();//獲取應用上下文 if (wac != null) { this.delegate = this.initDelegate(wac);//初始化委託 ...
protected Filter initDelegate(WebApplicationContext wac) throws ServletException { Filter delegate = (Filter)wac.getBean(this.getTargetBeanName(), Filter.class);//從應用上下文中獲取名爲targetBeanName的bean,也就是被委託的Filter if (this.isTargetFilterLifecycle()) { delegate.init(this.getFilterConfig());//調用Filter的初始化方法 } return delegate; }
AuthenticationFilter繼承了AbstractCasFilter。this
上面說到調用Filter本身的初始化方法。對於AuthenticationFilter,由於本身沒有重寫init(FilterConfig),則會調用從其父類AbstractCasFilter繼承來的init(FilterConfig)方法:url
public final void init(FilterConfig filterConfig) throws ServletException { if (!this.isIgnoreInitConfiguration()) { ... this.initInternal(filterConfig);//內部初始化 } this.init();//自定義初始化邏輯 }
注意:你會發現AuthenticationFilter和其父類都有initInternal(filterConfig)和init()方法,這裏進入的是AuthenticationFilter,因此回去調用AuthenticationFilter中對應的方法:代理
protected void initInternal(FilterConfig filterConfig) throws ServletException {//將filterConfig設置到WebXmlConfigurationStrategyImpl以及設置一些本身的屬性值 ... super.initInternal(filterConfig);//此時纔去調用其父類的initInternal(filterConfig) ... } public void init() { super.init();//此時纔去調用其父類的init() ... }
直觀的圖示(非專業,手動滑稽~):
本文從web項目和spring的整合入手,以cas中的AuthenticationFilter爲例(其餘類型的Filter相似)跟蹤代碼分析如何走到他本身的初始化邏輯。後續會有初始化以後對請求的攔截、cas服務端的處理等分析。
碼字整理不易,如何你以爲寫的還能看的話請賞一個贊或者推薦吧,若是寫的不對請直接評論糾正,畢竟我仍是一個在路上的小魯班呢~
歡迎關注個人公衆號,不按期更新學習筆記和視頻文檔學習資料哦~