1. 程式人生 > >CAS4.0.3服務的搭建實戰三【編寫shiro-cas客戶端】

CAS4.0.3服務的搭建實戰三【編寫shiro-cas客戶端】

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,一是將loginUrlvalue設定為: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"/> <!--&lt;!&ndash; 登入成功後要跳轉的連線 &ndash;&gt;-->
<!--<property name="successUrl" value="/index.html"/>--> <!--&lt;!&ndash; 沒有許可權返回的地址 (拒絕訪問路徑)&ndash;&gt;--> <!--<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 中讀取到的使用者資料放入shirosession中去。可以看出這裡同樣用到了validate方法去請求cas驗證ticket的有效性