CAS實現SSO 學習(五)

(五)擴展基於數據庫的身份驗證

1. 應用場景

前面提到的基於數據庫的集中身份驗證主要是通過用戶名、密碼的方式完成驗證操作,然而在實際使用過程中,用戶可能需要多種形式的認證手段,除了用戶名密碼的方式外,還可能通過郵箱或手機號登錄,但不管使用何種方式登錄,都對應同一用戶。下例如淘寶網在登錄時允許用戶以“手機號/會員名/郵箱”三種方式登錄系統。

2. 數據庫設計

針對上述需求,重新設計數據庫字段,如下圖所示:

輸入測試用數據.

3. 自定義數據庫驗證Handler

關於自定義數據庫驗證Handler的文章比較多,我主要參考了《CAS擴展——自定義查詢數據庫驗證Handler》和《CAS重新實現登陸認證邏輯》。但是這兩篇文章介紹的相對較糙,對於不瞭解Java的人來說實施起來着實有點困難,所以在這裏我將兩人的東西綜合一下並給出詳盡的操作流程供參考。

說明:大家可以從解壓縮的“cas-server-3.5.2\cas-server-support-jdbc\src”文件夾下找到“QueryDatabaseAuthenticationHandler.java”的源代碼以及其它相關源碼供參考。

(1)安裝Eclipse。Eclipse是非常常用的一種Java編輯器。爲了完成組件編寫,我們首先需要安裝Eclipse。Eclipse的下載與安裝非常簡單,在這裏就不再贅述。

(2)啓動Eclipse,選擇“File/New/Java Project”,打開新建項目對話框,在“Project Name”文本框中輸入“MultiCriteriaQueryDatabaseAuthenticationHandler”,單擊“Finish”按鈕。如下圖所示:


(3)在“Package Explorer”中右擊項目“MultiCriteriaQueryDatabaseAuthenticationHandler”,選擇“New/Folder”,在彈出的對話框中輸入“lib”並單擊“Finish”按鈕。

(4)從解壓縮的“cas-server-3.5.2\modules”文件夾中找到“cas-server-core-3.5.2.jar”與“cas-server-support-jdbc-3.5.2.jar”兩個文件,將其拷貝到新建的“lib”文件夾下。

(5)從網上搜索並下載“spring.jar”與“javax.validation-1.0.0.GA.jar”兩個文件,也將其拷貝到新建的“lib”文件夾。


(6)在“Package Explorer”中右擊項目“MultiCriteriaQueryDatabaseAuthenticationHandler”,選擇“Build Path/Add External Archives...”,依次將剛纔拷貝到lib文件夾下的四個jar文件添加至項目的“Reference Libraries”中。


(7)在“src”文件夾上右擊,選擇“New/Class”,彈出新建Java類對話框。在Package文本框中輸入“org.jasig.cas.adaptors.jdbc”,在Name文本框中輸入“MultiCriteriaQueryDatabaseAuthenticationHandler”,單擊“Finish”按鈕。


(8)用下面的代碼替換“MultiCriteriaQueryDatabaseAuthenticationHandler.java”文件中的現有代碼,單擊保存按鈕保存修改。

protected final boolean authenticateUsernamePasswordInternal(
            UsernamePasswordCredentials credentials)
            throws AuthenticationException {
        final String id = getPrincipalNameTransformer().transform(
                credentials.getUsername());
        final String password = credentials.getPassword();
        final String encryptedPassword = this.getPasswordEncoder().encode(
                password);

        try {
            String dbPassword = getJdbcTemplate().queryForObject(
                    this.getPwdSql, String.class, new Object[] { id, id, id });

            String username = getJdbcTemplate().queryForObject(
                    this.getUsernameSql, String.class,
                    new Object[] { id, id, id });

            credentials.setUsername(username);
            return dbPassword.equals(encryptedPassword);
        } catch (final IncorrectResultSizeDataAccessException e) {
            // this means the username was not found.
            return false;
        }
    }

    public void setGetPwdSql(final String getPwdSql) {
        this.getPwdSql = getPwdSql;
    }

    public void setGetUsernameSql(final String getUsernameSql) {
        this.getUsernameSql = getUsernameSql;
    }
}
(9)在“Package Explorer”中右擊項目“MultiCriteriaQueryDatabaseAuthenticationHandler”,選擇“Export...”打開Export對話框。
(10)在“Export”對話框中選擇“JAR file”,單擊“Next”按鈕。


(11)在JAR文件設置對話框中,去掉“lib”文件夾前面的對勾,同時去掉“.classpath”和“.project”前面的對勾,選擇JAR文件的保存路徑到桌面,單擊“Finish”按鈕。


(12)將桌面上生成的“MultiCriteriaQueryDatabaseAuthenticationHandler.jar”文件拷貝至“%TOMCAT_HOME%\webapps\cas\WEB-INF\lib”文件夾下。

(13)以管理員身份啓動文本編輯器,打開“%TOMCAT_HOME%\webapps\cas\WEB-INF\deployerConfigContext.xml”。找到下面的代碼(這段代碼是上篇博文中我們添加進去的):


<bean class="org.jasig.cas.adaptors.jdbc.QueryDatabaseAuthenticationHandler">
    <property name="sql" value="select Password from users where username=?" />
    <property name="dataSource" ref="dataSource" />
</bean>

(14)將上面這段代碼註釋掉,並在其下插入如下配置信息並保存:


<bean class="org.jasig.cas.adaptors.jdbc.MultiCriteriaQueryDatabaseAuthenticationHandler">  
  <property name="getPwdSql" value="select password from users where username=? or email=? or mobile=?" />  
  <property name="getUsernameSql" value="select username from users where username=? or email=? or mobile=?" />  
  <property name="dataSource" ref="dataSource" />  
</bean>

如圖:


(15)重新啓動Tomcat服務。


4.測試自定義數據庫身份驗證Handler

從客戶端運行前面調試好的WebForm程序,輸入庫中用戶名或郵箱或手機號、密碼,測試是否登錄成功。可以看到,不管用戶使用郵件還是手機號登錄,客戶端始終顯示用戶名,而非郵箱和手機號。這是因爲在MultiCriteriaQueryDatabaseAuthenticationHandler.java代碼中如下代碼所決定的:

String username = getJdbcTemplate().queryForObject(
        this.getUsernameSql, String.class,
        new Object[] { id, id, id });

credentials.setUsername(username);

登錄後的用戶界面如下圖所示:


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章