1. 程式人生 > >CAS修改原始碼支援多種方式登入認證

CAS修改原始碼支援多種方式登入認證

很多人在使用CAS作為自己的單點登入伺服器時,都想從CAS Server端獲取更多的使用者資訊,網上的介紹一般都是僅限於單條件SQL來進行查詢,而實際上,有些使用情況比較複雜,
比如我想讓CAS支援多種方式的登入,那就必須使用多條件的SQL來獲取使用者資訊,下面將介紹如何達成這一目的,而對於單條件SQL將不再贅述,網上一大把:
1、檢視org.jasig.services.persondir.support.jdbc.SingleRowJdbcPersonAttributeDao原始碼,修改deployerConfigContext.xml
通過SingleRowJdbcPersonAttributeDao找到父類AbstractJdbcPersonAttributeDao,可以看到有:private QueryType queryType = QueryType.AND;這個是組成SQL條件的連線符,預設是AND,
然後找到AbstractJdbcPersonAttributeDao的父類AbstractQueryPersonAttributeDao,可以找到:
private Map<String, Set<String>> queryAttributeMapping;
private Map<String, Set<String>> resultAttributeMapping;
private Set<String> possibleUserAttributes;
private boolean requireAllQueryAttributes = false;
private boolean useAllQueryAttributes = true;
private String unmappedUsernameAttribute = null;
看懂了這些,我們就可以在deployerConfigContext.xml中新增
<bean id="attributeRepository" class="org.jasig.services.persondir.support.jdbc.SingleRowJdbcPersonAttributeDao">
<constructor-arg index="0" ref="dataSource" />
<constructor-arg index="1" value="select * from user where {0} {1} {2}"/>
</constructor-arg>
<!-- 組裝sql用的查詢條件屬性 -->
<property name="queryAttributeMapping">
<map>
<entry key="nickname" value="nickname"/>
<entry key="cellphone" value="cellphone"/>
<entry key="email" value="email"/>
</map>
</property>
<!-- 如果要組裝多個查詢條件,需要加上下面這個,預設為AND -->
<property name="queryType">
<value>OR</value>
</property>
<!-- 要獲取的屬性在這裡配置 -->
<property name="resultAttributeMapping">
<map>
<!--key為對應的資料庫欄位名稱,value為提供給客戶端獲取的屬性名字,系統會自動填充值-->
<entry key="nickname" value="nickname" />
<entry key="cellphone" value="cellphone" />
<entry key="id" value="id" />
<entry key="email" value="email" />
</map>
</property>
</bean>
上面的配置中,關鍵點在:
<property name="queryAttributeMapping">
<map>
<entry key="nickname" value="nickname" />
<entry key="cellphone" value="cellphone" />
<entry key="id" value="id" />
<entry key="email" value="email" />
</map>
</property>
<property name="queryType">
<value>OR</value>
</property>
最終組裝而成的SQL是:nickname='xxxx' OR cellphone='xxxx' OR email='xxxxx'
好了,我們開始除錯,實際測試的結果不是我想要的,實際組裝成的SQL,永遠都只是取queryAttributeMapping的最後一個來組裝SQL條件:email='xxxx',經過分析,
發現CAS雖然在這裡可以配置成多條件SQL,但並未給出組裝成多條件SQL的方法,不知道是何緣故。
2、 在AbstractDefaultAttributePersonAttributeDao中新增toSeedMutiMap方法,返回一個多KEY的MAP
經過分析發現,在AbstractDefaultAttributePersonAttributeDao的toSeedMap方法中:final Map<String, List<Object>> seed = Collections.singletonMap(usernameAttribute, values);
這裡singletonMap永遠只會返回單條map,所以如果要返回多條KEY的MAP,必須自己新增一個方法,我加了一個方法:

protected Map<String, List<Object>> toSeedMutiMap(String uid) {
final List<Object> values = Collections.singletonList((Object)uid);

final String nicknameAttribute = this.usernameAttributeProvider.getNicknameAttribute();
final String cellphoneAttribute = this.usernameAttributeProvider.getCellphoneAttribute();
final String emailAttribute = this.usernameAttributeProvider.getEmailAttribute();

Map<String, List<Object>> seed =new HashMap<String, List<Object>>();
seed.put(nicknameAttribute , values);
seed.put(cellphoneAttribute , values);
seed.put(emailAttribute , values);
if (this.logger.isDebugEnabled()) {
this.logger.debug("Created seed map='" + seed + "' for uid='" + uid + "'");
}
return seed;
}


在IUsernameAttributeProvider中新增多增加的3個方法:
public String getNicknameAttribute();
public String getCellphoneAttribute();

public String getEmailAttribute();

在SimpleUsernameAttributeProvider中新增以下方法:

private String cellphoneAttribute = "cellphone";//和配置檔案中的key值一樣
private String nicknameAttribute = "nickname";";//和配置檔案中的key值一樣
private String emailAttribute = "email";";//和配置檔案中的key值一樣

public void setCellphoneAttribute(String cellphoneAttribute) {
Validate.notNull(cellphoneAttribute);
this.cellphoneAttribute = cellphoneAttribute;
}

public void setNicknameAttribute(String nicknameAttribute) {
Validate.notNull(nicknameAttribute);
this.nicknameAttribute = nicknameAttribute;
}

public void setEmailAttribute(String emailAttribute) {
Validate.notNull(emailAttribute);
this.emailAttribute = emailAttribute;
}

@Override
public String getCellphoneAttribute() {
// TODO Auto-generated method stub
return this.cellphoneAttribute;
}

@Override
public String getEmailAttribute() {
// TODO Auto-generated method stub
return this.emailAttribute;
}

@Override
public String getNicknameAttribute() {
// TODO Auto-generated method stub
return this.nicknameAttribute;
}


最後在public IPersonAttributes getPerson(String uid)中將final Map<String, List<Object>> seed = this.toSeedMap(uid);修改為:
final Map<String, List<Object>> seed = this.toSeedMutiMap(uid);

這樣就大功告成。