cas 登陸和登出是基於spring web flow 的,如果不瞭解 spring web flow 是沒辦法修改的,所以在修改cas 的登陸時最好先了解一下 spring web flow。
下邊說一下簡單的修改:
1、先將target下的 webflow 文件夾拷貝到 WEB-INF下
2、登陸流程簡單的說明:
打開 其中login下的login-webflow.xml,並找到下邊的代碼:
<view-state id="viewLoginForm" view="casLoginView" model="credential">
<binder>
<binding property="username" required="true"/>
<binding property="password" required="true"/>
<!--
<binding property="rememberMe" />
-->
</binder>
<on-entry>
<set name="viewScope.commandName" value="'credential'"/>
<!--
<evaluate expression="samlMetadataUIParserAction" />
-->
</on-entry>
<transition on="submit" bind="true" validate="true" to="realSubmit"/>
</view-state>
看這段代碼的最後一句:<transition on="submit" bind="true" validate="true" to="realSubmit"/>,這句的大概意思就是當點擊submit按鈕之後,進入 realSubmit流程。這裏就是登陸驗證所以動作的開始!!
既然如此,我們在去找realSubmit:
<action-state id="realSubmit">
<evaluate
expression="authenticationViaFormAction.submit(flowRequestContext, flowScope.credential, messageContext)"/>
<transition on="warn" to="warn"/>
<!--
To enable AUP workflows, replace the 'success' transition with the following:
<transition on="success" to="acceptableUsagePolicyCheck" />
-->
<transition on="success" to="sendTicketGrantingTicket"/>
<transition on="successWithWarnings" to="showMessages"/>
<transition on="authenticationFailure" to="handleAuthenticationFailure"/>
<transition on="error" to="initializeLogin"/>
</action-state>
解釋一下這段代碼:
evaluate:可以理解爲realSubmit這個流程裏邊的核心處理代碼,authenticationViaFormAction:這個是具體處理的action,它是AuthenticationViaFormAction 類的註解,這個可以在源碼裏去找。最通俗話就是點擊頁面登陸之後,程序就進入AuthenticationViaFormAction 類的submit方法驗證登陸了。
下邊的transition 代表處理的不同結果,進入不同的下一個流程。如果驗證成功就進入sendTicketGrantingTicket。然後我們再去找sendTicketGrantingTicket,sendTicketGrantingTicket處理成功之後就進入
<decision-state id="serviceCheck">
<if test="flowScope.service != null" then="generateServiceTicket" else="viewGenericLoginSuccess"/>
</decision-state>
這裏有一個判斷,flowScope.service裏邊封裝的是客戶端請求的url,如果它不是是空的就進入 generateServiceTicket 否則進入viewGenericLoginSuccess,依次類推,整個步驟就是這樣了。
3、自定義流程:
默認的登陸流程是最基礎的,有兩種方式實現自定義流程,第一、我們可以在realSubmit之前添加一個或者多個自己寫的流程,第二直接修改realSubmit的evaluate讓登陸驗證指向我們自己寫的驗證代碼(這種方式需要參考源碼去寫,比如返回的key得跟transition 中on屬性一致等等)。
不管是哪種方式,我們都需要自己去寫局部或者整體的驗證代碼,步驟如下:
a、在根目錄下創建包org.jasig.cas,因爲cas註解掃描是從這個包開始的,這個可以在spring-configuration裏找到(項目裏沒有說明你沒有將其從target中拷貝上來,去target裏去找就行了),源碼是:
<context:component-scan base-package="org.jasig.cas" />
這個不能改!!如果改成自己的包路徑,它就無法解析別的了。
b、創建自己的驗證action:
package org.jasig.cas.login;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.jasig.cas.authentication.Credential;
import org.jasig.cas.web.support.WebUtils;
import org.springframework.binding.message.MessageContext;
import org.springframework.stereotype.Component;
import org.springframework.webflow.execution.RequestContext;
import com.demo.login.UsernamePasswordVCodeCredential;
@Component("authenticationViaFormVCodeAction")
public class AuthenticationViaFormVCodeAction {
//添加自定義驗證方法1
public final String validatorCode(RequestContext flowRequestContext,Credential credential,MessageContext messageContext) throws Exception {
System.out.println("進入了自定義驗證邏輯!!!!");
//這裏可以寫自己的驗證邏輯,比如驗證碼之類的。
return "success";
}
//添加自定義驗證方法2
public String goSys(RequestContext flowRequestContext,Credential credential,MessageContext messageContext) throws Exception {
HttpServletResponse response = WebUtils.getHttpServletResponse(flowRequestContext);
UsernamePasswordVCodeCredential ucredential = (UsernamePasswordVCodeCredential)credential;
//response.sendRedirect(ucredential.getSys_url());
return ucredential.getSys_url();
}
}
c、添加或者修改流程
如果修改realSubmit,只需要修改一下evaluate指向,上邊已經說過。
如果在realSubmit之前添加一個新的流程:
在login-webflow.xml中添加一個action-state,讓它指向我們自己的驗證邏輯代碼,並設置transition ,如果成功進入realSubmit,失敗進入initializeLogin(重新初始化登陸頁)例如:
<!-- 自定義驗證 -->
<action-state id="vCodeValidate">
<evaluate expression="authenticationViaFormVCodeAction.validatorCode(flowRequestContext, flowScope.credential, messageContext)" />
<transition on="error" to="initializeLogin" />
<transition on="success" to="realSubmit" />
</action-state>
然後將點擊登陸後的處理流程指向它:
<view-state id="viewLoginForm" view="casLoginView" model="credential">
<binder>
<binding property="username" required="true"/>
<binding property="password" required="true"/>
<!--
<binding property="rememberMe" />
-->
</binder>
<on-entry>
<set name="viewScope.commandName" value="'credential'"/>
<!--
<evaluate expression="samlMetadataUIParserAction" />
-->
</on-entry>
<transition on="submit" bind="true" validate="true" to="vCodeValidate"/>
</view-state>
以上就基本實現了自定義登陸了。
4、添加驗證參數
實際項目中可能要驗證的不止是用戶名和密碼,還需要有角色啊什麼的,這時就需要增加參數。
看上邊的代碼,很明顯<binding property="password" required="true"/>這個就是我們的參數了,所以我們要增加參數也需要在這裏配置,但是如果我們直接在這個後邊添加上新的參數,在後臺並沒有獲取到,原因是 默認的實體類配置的是:
<var name="credential" class="org.jasig.cas.authentication.UsernamePasswordCredential"/>
org.jasig.cas.authentication.UsernamePasswordCredential這個類裏邊只有用戶名和密碼,所以肯定是取不到的,所以我們要創建自己的實體類,並讓它繼承這個UsernamePasswordCredential,然後把新的屬性加進去就行了,例如:
package com.demo.login;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import org.jasig.cas.authentication.UsernamePasswordCredential;
public class UsernamePasswordVCodeCredential extends UsernamePasswordCredential{
@NotNull
@Size(
min=1,
message = "required.sys_url"
)
private String sys_url;
public String getSys_url() {
return sys_url;
}
public void setSys_url(String sys_url) {
this.sys_url = sys_url;
}
}
這樣就新加了一個 一個sys_url 參數進去,然後將配置原來的實體類代碼註釋掉,換成新的自定義實體類:
<!--默認的-->
<!-- <var name="credential" class="org.jasig.cas.authentication.UsernamePasswordCredential"/> -->
<!--新的-->
<var name="credential" class="com.demo.login.UsernamePasswordVCodeCredential"/>
再把新增的屬性添加都password後邊,例如:
<binding property="password" required="true"/>
<binding property="sys_url" required="true"/>
...
最後頁面上添加一個 name=sys_url的input即可,例如:
<input type="hidden" id="sys_url" name="sys_url" value="http://127.0.0.1:8081/prdicman" />
後臺獲取的時候只需要轉義一下:
UsernamePasswordVCodeCredential ucredential = (UsernamePasswordVCodeCredential)credential;
即可。
總結:
修改登陸流程,首先要了解spring web flow只要瞭解了spring web flow,那麼我們就可以隨意去修改了,這裏只需要注意的是將新的驗證代碼放到org.jasig.cas路徑下邊,讓Spring能裝載到就行了。