CAS4.0.3服務的搭建實戰三【編寫shiro-cas客戶端】
阿新 • • 發佈:2018-11-26
shiro與cas可以實現無縫的整合,只需要加入幾個依賴的jar包,修改部分shiro的配置檔案,定義一個自己的casRealm
專案結構
一、在pom中加入cas相關依賴
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-cas</artifactId>
<version>${cas-version}</version>
</dependency>
二、修改shiro配置檔案
主要修改三處:
1、shiroFilter
,一是將loginUrl
的value
設定為:cas認證服務地址/login?service=客戶端訪問地址/cas
,二是配置新增的casFilter
,和固定的攔截規則:/cas = cas
修改如下:
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<!-- 構建securityManager環境 -->
<property name="securityManager" ref="securityManager" />
<!-- 要求登入時的連結(可根據專案的URL進行替換),非必須的屬性,預設會自動尋找Web工程根目錄下的"/login.jsp"頁面 -->
<property name="loginUrl" value="https://sso.siwash.net:8443/login?service=http://client.siwash.net:8081/cas"/>
<!--<!– 登入成功後要跳轉的連線 –>-->
<!--<property name="successUrl" value="/index.html"/>-->
<!--<!– 沒有許可權返回的地址 (拒絕訪問路徑)–>-->
<!--<property name="unauthorizedUrl" value="/index.jsp" />-->
<property name="filters">
<util:map>
<entry key="cas" value-ref="casFilter"/>
<entry key="logoutFilter" value-ref="logoutFilter"/>
</util:map>
</property>
<property name="filterChainDefinitions">
<value>
/casFailure.jsp=anon
/cas = cas
/index.jsp=anon
/index.html=anon
/**=authc
/logout = logoutFilter
/users/** = user
</value>
</property>
</bean>
2.新增一個casFilter:
<bean id="casFilter" class="org.apache.shiro.cas.CasFilter">
<property name="failureUrl" value="http://client.siwash.net:8081/casFailure.jsp" />
<property name="successUrl" value="http://client.siwash.net:8081/zone.html" />
</bean>
3.定義自己的casRealm
,其中casServerUrlPrefix
為cas服務端地址,casService
為客戶端地址,這裡配置這兩個的目的是:在應用A已經認證後應用B訪問時,則會直接進入該casRealm,在程式碼中回去請求認證中心如下url:
https://sso.siwash.net:8443/cas/serviceValidate?ticket=xxxx&service=客戶端地址
去驗證有效性,並返回使用者的資訊,當驗證通過後應用B則直接進入B系統,而不需要進行二次登陸。
<bean id="realm" class="rpf.study.shiro.casRealm">
<property name="casServerUrlPrefix" value="https://sso.siwash.net:8443/"/>
<property name="casService" value="http://client.siwash.net:8081/cas"/>
</bean>
三、定義自己的casRealm
public class casRealm extends CasRealm{
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
CasToken casToken = (CasToken)token;
if (token == null) {
return null;
} else {
String ticket = (String)casToken.getCredentials();
if (!StringUtils.hasText(ticket)) {
return null;
} else {
TicketValidator ticketValidator = this.ensureTicketValidator();
try {
Assertion casAssertion = ticketValidator.validate(ticket, this.getCasService());
AttributePrincipal casPrincipal = casAssertion.getPrincipal();
String userId = casPrincipal.getName();
Map<String, Object> attributes = casPrincipal.getAttributes();
casToken.setUserId(userId);
String rememberMeAttributeName = this.getRememberMeAttributeName();
String rememberMeStringValue = (String)attributes.get(rememberMeAttributeName);
boolean isRemembered = rememberMeStringValue != null && Boolean.parseBoolean(rememberMeStringValue);
if (isRemembered) {
casToken.setRememberMe(true);
}
List<Object> principals = CollectionUtils.asList(new Object[]{userId, attributes});
PrincipalCollection principalCollection = new SimplePrincipalCollection(principals, this.getName());
return new SimpleAuthenticationInfo(principalCollection, ticket);
} catch (TicketValidationException var14) {
throw new CasAuthenticationException("Unable to validate ticket [" + ticket + "]", var14);
}
}
}
}
}
這裡只是將父類的方法直接複製了過來,實際開發中可以將程式碼中attributes
中讀取到的使用者資料放入shiro
的session
中去。可以看出這裡同樣用到了validate
方法去請求cas驗證ticket的有效性