cas server 4.0深度研究

一.體系結構

1.須要注意的幾個配置文件

WEB-INF/deployerConfigContext.xml,WEB-INF/login-webflow.xmlcss

 

2.AuthenticationManager

    配置位置 deployerConfigContext.xmlhtml

    主要涉及的方法是Authentication authenticate(final Credential... credentials),以及在authenticate方法中調用的AuthenticationBuilder authenticateInternal(final Credential... credentials)。java

    身份認證管理器,經過指定認證憑證的認證處理程序來定義認證的安全策略。3.5的時候實現類是 org.jasig.cas.authentication.AuthenticationManagerImpl , 4.0變爲org.jasig.cas.authentication.PolicyBasedAuthenticationManager,這是3.5和4.0改變最大的緣由。沒有改造的必要,若是debug看代碼從PolicyBasedAuthenticationManager的Authentication authenticate(final Credential... credentials) 方法開始。web

 

 

3.Credential

    配置位置 login-webflow.xmlspring

    由登錄提交的信息封裝成的認證憑證,主要須要定製的內容,注意修改時同時須要修改login-webflow 中 viewLoginForm 的 binder安全

 

4.AuthenticationHandler

    配置位置 deployerConfigContext.xml服務器

    主要涉及方法 String getName();session

                          boolean supports(Credential credential) 判斷是否由該AuthenticationHandler處理app

                          HandlerResult authenticate(Credential credential) 傳入封裝好的jsp

    

    AuthenticationManager經過委託AuthenticationHandler(處理器)處理Credential(認證憑證)。認證該組件提供身份認證在您的環境中使用的各種證件。

    注意:(1)每一個處理器都須要一個惟一的名稱。

            (2)不一樣於3.5的AuthenticationHandler(包路徑改變)中authenticate方法返回boolean值,4.0版本AuthenticationHandler中返回的是HandlerResult。

 

5.PrincipalResolver

    配置位置 deployerConfigContext.xml

    主要涉及方法 Principal resolve(Credential credential);

    經過解析AuthenticationHandler(處理器)處理認證經過的Credential(認證憑證),構建Principal(認證結果)。

    在4.0中能夠不配置AuthenticationHandler對應的PrincipalResolver,這樣,程序會調用AuthenticationHandler處理結果中HandlerResult的

 

 6.Principal

    一個通用概念,表明一個通過認證的東西。這裏是認證結果的封裝。

    在這裏是一個接口,SimplePrincipal是官方提供的一個實現。有兩個方法 getId() 方法用於返回惟一標識,Map<String, Object> getAttributes()能夠在重寫後返回其它的屬性,可是須要修改casServiceValidationSuccess.jsp,修改方法以前的文章中有過講解,這裏再也不贅述。

    結果屬性中Map<String, Object> Object儘可能不要放集合,casServiceValidationSuccess.jsp很差修改.

 

 

 二.輸入參數和返回值的訂製

yale-cas服務器端深度定製 文章中已經介紹過3.5如何進行訂製,這裏主要說一下4.0不同的地方

 

1.deployerConfigContext.xml

PolicyBasedAuthenticationManager中配置AuthenticationHandler的方式發生改變,如今能夠向下面這樣配置一個自定義的AuthenticationHandler。

上面說過能夠不配置PrincipalResolver

  

<bean id="authenticationManager" class="org.jasig.cas.authentication.PolicyBasedAuthenticationManager">
    <constructor-arg>
        <map>
            <entry key-ref="proxyAuthenticationHandler" value-ref="proxyPrincipalResolver"/>
            <entry key-ref="myAuthenticationHandler">
                <null/>
            </entry>
        </map>
    </constructor-arg>
    <property name="authenticationPolicy">
        <bean class="org.jasig.cas.authentication.AnyAuthenticationPolicy"/>
    </property>
</bean>
 

  

2.AuthenticationHandler

    主要的認證工做和服務器端返回值都在AuthenticationHandler的authenticate方法中完成,注意 getName和 supports 兩個方法也須要重寫

 

@Override
public HandlerResult authenticate(Credential credential) throws GeneralSecurityException, PreventedException {
    MyCredential myCredential = (MyCredential)credential;
    if (credential == null) {
        throw new FailedLoginException();
    } else if (StringUtils.isBlank(credential.getId())) {
        logger.debug("{} was not found in the map.", credential);
        throw new AccountNotFoundException(credential + " not found in backing map.");
    }

    Map<String, Object> attributes = Maps.newHashMap();
    attributes.put("中文KEY", "中文value");
    attributes.put("空值key", "");
    attributes.put("custom", myCredential.getCustom());

    Principal principal = new SimplePrincipal(credential.getId(), attributes);
    return new HandlerResult(this, new BasicCredentialMetaData(credential), principal);
}
 

 

 

 

3.login-webflow.xml

設置自定義Credential(認證憑證),MyCredential是一個只有有三個String屬性username,password,custom的pojo

 

<var name="credential" class="com.gqshao.sso.credential.MyCredential" />
除了var credential外還要設置view-state id="viewLoginForm"中binder,與Credential中參數一一對應。 

 

<binder>
    <binding property="username" />
    <binding property="password" />
    <binding property="custom" />
</binder>

 

 

4./WEB-INF/view/jsp/protocol/2.0/casServiceValidationSuccess.jsp

修改casServiceValidationSuccess.jsp,用於將Principal中Attributes發送到客戶端

3.0展現不須要修改,由於沒有對應3.0的客戶端

  

<cas:user>${fn:escapeXml(assertion.primaryAuthentication.principal.id)}</cas:user>
<!-- 解析返回的參數 Custom By SGQ -->
<c:if test="${fn:length(assertion.chainedAuthentications[fn:length(assertion.chainedAuthentications)-1].principal.attributes) > 0}">
    <cas:attributes>
        <c:forEach var="attr" items="${assertion.chainedAuthentications[fn:length(assertion.chainedAuthentications)-1].principal.attributes}">
            <cas:${fn:escapeXml(attr.key)}>${fn:escapeXml(attr.value)}</cas:${fn:escapeXml(attr.key)}>
        </c:forEach>
    </cas:attributes>
</c:if>
<!-- Custom By SGQ-->

5.WEB-INF/view/jsp/default/ui/casLoginView.jsp

<%@ page pageEncoding="UTF-8" %>
<%@ page contentType="text/html; charset=UTF-8" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <title>單點登陸認證系統</title>
</head>
<body id="cas">
<c:if test="${not pageContext.request.secure}">
    <div id="msg">
        <h2>非安全鏈接</h2>

        <p>您正在經過非安全鏈接訪問單點登陸系統。單點登陸將沒法正常工做。爲了單點登陸正常工做,你必須經過HTTPS登陸。</p>
    </div>
</c:if>
<form id="fm1" action="/cas-server/login" method="post">
    <h2>請輸入您的用戶名和密碼.</h2>

    <div>
        <label for="username">用戶名:</label>
        <input id="username" name="username" type="text" value=""/>
    </div>
    <div>
        <label for="password">密碼:</label>
        <input id="password" name="password" type="password" value=""/>
    </div>
    <div>
        <label for="custom">自定義:</label>
        <input id="custom" name="custom" type="text" value=""/>
    </div>
    <div>
        <input id="warn" name="warn" value="true" type="checkbox"/>
        <label for="warn">轉向其餘站點前提示我。</label>
    </div>
    <div>
        <input type="hidden" name="lt" value="${loginTicket}"/>
        <input type="hidden" name="execution" value="${flowExecutionKey}"/>
        <input type="hidden" name="_eventId" value="submit"/>
        <input name="submit" value="登陸" type="submit"/>
        <input name="reset" value="重置" type="reset"/>
    </div>
</form>
</body>
</html>
  

6.cas.properties

設置以下值用於單點登出,同3.5一致

cas.logout.followServiceRedirects=true

 

三.國際化管理

WEB-INF/spring-configuration/applicationContext.xml文件中bean id=messageSource配置國際化,能夠修改路徑

 

四.自定義登錄錯誤

AuthenticationHandler中經過throw Exception,好比throw new FailedLoginException();或throw new FailedLoginException();拋出異常,經過查看WEB-INF/cas-servlet.xml(bean 定義),WEB-INF/login-webflow.xml(流程定義)兩個文件,發現最終交給 org.jasig.cas.web.flow.AuthenticationExceptionHandler 這個類處理異常。經過閱讀源代碼知道會按照不一樣的Exception對應國際化文件中的key來顯示到WEB-INF/view/jsp/default/ui/casLoginView.jsp上的。

經過,WEB-INF/view/jsp/default/ui/casLoginView.jsp文件中

<form:form method="post" id="fm1" commandName="${commandName}" htmlEscape="true">
    <form:errors path="*" id="msg" cssClass="errors" element="div" htmlEscape="false"/>
</form:form>

form:errors標籤打印提示,該標籤必須放在form:form中

 

 

標記

測試時使用的客戶端版本是3.3.1,單點登出時會出現下面的問題,3.3.0版本也會有這個問題,應該會在3.4.0版本中解決,在這裏有提到 https://issues.jasig.org/browse/CASC-223

java.lang.NullPointerException
	at org.jasig.cas.client.util.CommonUtils.safeGetParameter(CommonUtils.java:330)
	at org.jasig.cas.client.session.SingleSignOutHandler.isTokenRequest(SingleSignOutHandler.java:114)
	at org.jasig.cas.client.session.SingleSignOutFilter.doFilter(SingleSignOutFilter.java:66)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
	at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:110)
... ...

 

 另一個單點登出的問題是,登錄時參數service,裏面的ip或地址必須是單點登錄服務器能夠訪問的有效地址,好比localhost這種就不能夠使用。

相關文章
相關標籤/搜索