cas 服务器端配置

时间:2022-12-13 17:28:57

目前,我们使用的CAS Server 3.1.1的是基于Spring Framework编写的,因此在CAS服务器端的配置管理中,绝大多数是Spring式的Java Bean XML配置。CAS 的服务器提供了一套易于定制的用户认证器接口,我们将围绕着身份认证模块定制和界面定制这两方面展开。

cas 服务端下载地址http://www.jasig.org/cas/download,解压下载包

cas 文档https://wiki.jasig.org/display/CASC

解压后 找到modules/cas-server-webapp-3.5.0.war 把文件部署到tomcat 或eclipse 新建项目导入

1 连接数据库配置

 打开WEB-INF/deployerConfigContext.xml,添加数据源

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
   <property name="driverClassName">
       <value>com.mysql.jdbc.Driver</value>
   </property>
   <property name="url">
       <value>jdbc:mysql://localhost:3306/test</value>
   </property>
   <property name="username">
       <value>root</value>
   </property>
   <property name="password">
       <value>123456</value>
   </property>
</bean>

然后把以下jar包 复制到项目lib

mysql-connector-java-5.1.7-bin.jar,commons-collections-3.2.1.jar(cas 自带),commons-dbcp.jar,commons-pool.jar

2 身份认证模块定制

(1) cas 自带jdbc 验证

         

 找到authenticationHandlers, 在list 中

  注释掉 

  <bean  class="org.jasig.cas.authentication.handler.support.SimpleTestUsernamePasswordAuthenticationHandler" /> 

 加入

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

         定义密码加密模式

        <bean id="myPasswordEncoder" class="org.jasig.cas.authentication.handler.DefaultPasswordEncoder">
    <constructor-arg value="MD5"/>
</bean>

       最后复制modules/cas-server-support-jdbc-3.5.0.jar 到项目llib 

(2)自定义验证

      自定义验证类UsernameLengthAuthnHandler继承AbstractUsernamePasswordAuthenticationHandler

      代码如下

     package net.cas;


import java.util.Map;


import javax.sql.DataSource;
import org.jasig.cas.authentication.handler.AuthenticationException;
import org.jasig.cas.authentication.handler.support.AbstractUsernamePasswordAuthenticationHandler;
import org.jasig.cas.authentication.principal.UsernamePasswordCredentials;
import org.springframework.jdbc.core.JdbcTemplate;


public class UsernameLengthAuthnHandler  extends AbstractUsernamePasswordAuthenticationHandler{


private JdbcTemplate jdbcTemplate;
private DataSource dataSource;

public JdbcTemplate getJdbcTemplate() {
return this.jdbcTemplate;
}
public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}


public void setDataSource(DataSource dataSource) {
        this.jdbcTemplate = new JdbcTemplate(dataSource);
        this.dataSource = dataSource;
    }



public DataSource getDataSource() {
        return this.dataSource;
    }




@SuppressWarnings("unused")
@Override
protected boolean authenticateUsernamePasswordInternal(
UsernamePasswordCredentials credentials) throws AuthenticationException {
/*
* 这里写身份验证代码,加密方式等等逻辑
* */

Map<String, Object> yonghu = getJdbcTemplate().queryForMap("select * from huiyuan where username=?",new Object[] {credentials.getUsername()});


if(yonghu.get("password").toString().equals(credentials.getPassword())){
return true;
}

return false;
}


}


   deployerConfigContext.xml 配置如下

  找到authenticationHandlers, 在list 中

  注释掉 

  <bean  class="org.jasig.cas.authentication.handler.support.SimpleTestUsernamePasswordAuthenticationHandler" /> 

 加入

  <bean class="net.cas.UsernameLengthAuthnHandler" >
        <property name="dataSource" ref="dataSource"/>
  </bean>

(3)采用hibernate自定义验证

自定义验证类UsernameLengthAuthnHandler继承AbstractUsernamePasswordAuthenticationHandler

      代码如下

package net.cas;


import java.util.Map;
import java.util.List;
import javax.annotation.Resource;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.transform.Transformers;
import org.jasig.cas.authentication.handler.AuthenticationException;
import org.jasig.cas.authentication.handler.support.AbstractUsernamePasswordAuthenticationHandler;
import org.jasig.cas.authentication.principal.UsernamePasswordCredentials;


public class UsernameLengthAuthnHandler  extends AbstractUsernamePasswordAuthenticationHandler{

private SessionFactory sessionFactory;


protected Session getSession() {
return sessionFactory.getCurrentSession();
}
@Resource
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}


@SuppressWarnings("unused")
@Override
protected boolean authenticateUsernamePasswordInternal(
UsernamePasswordCredentials credentials) throws AuthenticationException {
/*
* 这里写身份验证代码,加密方式等等逻辑
* */
String sql = "select * from huiyuan where username=:username";
Transaction tx = getSession().beginTransaction(); 
List list = this.getSession().createSQLQuery(sql).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP)
.setParameter("username",  credentials.getUsername())
.list();
tx.commit();
if(list.size() > 0){
Map huiyuan = (Map) list.get(0);
if(huiyuan.get("password").toString().equals(credentials.getPassword())){

return true;
}
}
return false;
}
}

  

 deployerConfigContext.xml 配置如下

  找到authenticationHandlers, 在list 中

  注释掉 

  <bean  class="org.jasig.cas.authentication.handler.support.SimpleTestUsernamePasswordAuthenticationHandler" /> 

 加入

  <bean class="net.cas.UsernameLengthAuthnHandler" >
        <property name="dataSource" ref="dataSource"/>
  </bean>

 

在 xml 中加入

<bean id="sessionFactory"
        class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <property name="hibernateProperties">
            <value>
                hibernate.dialect=org.hibernate.dialect.MySQLDialect
                hibernate.show_sql=false
                hibernate.hbm2ddl.auto=none
                javax.persistence.validation.mode=none
                hibernate.current_session_context_class=thread
              </value>
        </property>
    </bean>

(4)用户信息设置

本来想像身份验证那样定义自己的用户信息类,但是。。。。,所以只能使用网上通用的做法,

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 username from huiyuan where {0}"/>
<!--这里的key需写username,value对应数据库用户名字段 -->
<property name="queryAttributeMapping">
<map>
<entry key="username" value="username"/>
</map>
</property>
<!--key对应数据库字段,value对应客户端获取参数 -->
<property name="resultAttributeMapping">
<map>
<entry key="username" value="yonghuming"/> 
</map>
</property>

</bean>


取消红色部分

<bean
id="serviceRegistryDao"
        class="org.jasig.cas.services.InMemoryServiceRegistryDaoImpl">
            <property name="registeredServices">
                <list>
                    <bean class="org.jasig.cas.services.RegexRegisteredService">
                        <property name="id" value="0" />
                        <property name="name" value="HTTP and IMAP" />
                        <property name="description" value="Allows HTTP(S) and IMAP(S) protocols" />
                        <property name="serviceId" value="^(https?|imaps?)://.*" />
                        <property name="evaluationOrder" value="10000001" />
                    </bean>
                    <!--
                    Use the following definition instead of the above to further restrict access
                    to services within your domain (including subdomains).
                    Note that example.com must be replaced with the domain you wish to permit.
                    -->
                    <!--
                    <bean class="org.jasig.cas.services.RegexRegisteredService">
                        <property name="id" value="1" />
                        <property name="name" value="HTTP and IMAP on example.com" />
                        <property name="description" value="Allows HTTP(S) and IMAP(S) protocols on example.com" />
                        <property name="serviceId" value="^(https?|imaps?)://([A-Za-z0-9_-]+\.)*example\.com/.*" />
                        <property name="evaluationOrder" value="0" />
                    </bean>
                    -->
                </list>
            </property>

        </bean>

       改后

<bean id="serviceRegistryDao"class="org.jasig.cas.services.InMemoryServiceRegistryDaoImpl">
    </bean>


配置用户认证凭据转化的解析器,也是在deployerConfigContext.xml中,找到

UsernamePasswordCredentialsToPrincipalResolver注入attributeRepository,那么attributeRepository就会被触发并通过此类进行解析,红色为新添部分。

<bean class="org.jasig.cas.authentication.principal.UsernamePasswordCredentialsToPrincipalResolver" >
<property name="attributeRepository"> 
        <ref local="attributeRepository"/> 
        </property>

</bean>

在默认的WEB-INF/view/jsp/protocol/2.0/casServiceValidationSuccess.jsp中,只包括用户名

,并不提供其他的属性信息,因此需要对页面进行扩展,如下,红色为新添加部分

<cas:serviceResponse xmlns:cas='http://www.yale.edu/tp/cas'>
<cas:authenticationSuccess>
<cas:user>${fn:escapeXml(assertion.chainedAuthentications[fn:length(assertion.chainedAuthentications)-1].principal.id)}</cas:user>
<c:if test="${not empty pgtIou}">
<cas:proxyGrantingTicket>${pgtIou}</cas:proxyGrantingTicket>
</c:if>
<c:if test="${fn:length(assertion.chainedAuthentications) > 1}">
<cas:proxies>
<c:forEach var="proxy" items="${assertion.chainedAuthentications}" varStatus="loopStatus" begin="0" end="${fn:length(assertion.chainedAuthentications)-2}" step="1">
<cas:proxy>${fn:escapeXml(proxy.principal.id)}</cas:proxy>
</c:forEach>
</cas:proxies>
</c:if>


<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>



</cas:authenticationSuccess>
</cas:serviceResponse>

(5)取消Https 协议

服务器端:

1.找到cas\WEB-INF\spring-configuration\ticketGrantingTicketCookieGenerator.xml, p:cookieSecure="true改为 p:cookieSecure="false" 如下:

<bean id="ticketGrantingTicketCookieGenerator" class="org.jasig.cas.web.support.CookieRetrievingCookieGenerator"
p:cookieSecure
="false"
p:cookieMaxAge
="-1"
p:cookieName
="CASTGC"
p:cookiePath
="/cas" />

2.找到cas\WEB-INF\spring-configuration\warnCookieGenerator.xml ,将 p:cookieSecure="改为 p:cookieSecure="false",改完如下:

<bean id="warnCookieGenerator" class="org.jasig.cas.web.support.CookieRetrievingCookieGenerator"
p:cookieSecure
="false"
p:cookieMaxAge
="-1"
p:cookieName
="CASPRIVACY"
p:cookiePath
="/cas" />

3.找到cas\WEB-INF\deployerConfigContext.xml,在文件中找到“HttpBasedServiceCredentialsAuthenticationHandlerbean,然后添加:p:requireSecure="false",改完如下:

<bean class="org.jasig.cas.authentication.handler.support.HttpBasedServiceCredentialsAuthenticationHandler"
p:httpClient-ref
="httpClient" p:requireSecure="false" />


客户端:

PHP客户端的修改:

1.PHP安装目录下找到php.ini文件,将其中的extension=php_curl.dll的注释去除

2.修改CAS/client.php 函数_getServerBaseURL,_getCallbackURL,getURL    将“https”改为“http