单点登录系统CAS筹建及取得更多用户信息的实现

国内私募机构九鼎控股打造APP,来就送 20元现金领取地址:http://jdb.jiudingcapital.com/phone.html
内部邀请码:C8E245J (不写邀请码,没有现金送)
国内私募机构九鼎控股打造,九鼎投资是在全国股份转让系统挂牌的公众公司,股票代码为430719,为“中国PE第一股”,市值超1000亿元。 

 

------------------------------------------------------------------------------------------------------------------------------------------------------------------

 

 

单点登录系统CAS搭建及取得更多用户信息的实现

 

一、            单点登录简介

单点登录(Single sign-on,简称为 SSO),是目前比较流行的企业业务整合的解决方案之一。其简单定义是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统。类似的,用户只需要执行一次退出操作就可以终止对所有相关应用系统的访问。

本文主旨在介绍如何使用CAS实现单点登录时取得更多的用户信息,单点登录的原理将不作阐述。

二、            CAS简介

CAS是CentralAuthentication Service即中央认证服务的简称,它是由耶鲁大学发起的开源项目,其目的是为Web系统提供可靠的单点登录机制。2004年12月CAS正式成为JASIG(jasig.org)的一个项目。

CAS的Server需要作为独立Web应用部署,并且当前Server仅支持Java,但其Client端则支持Java、.Net、PHP、Perl、Apache、uPortal、Ruby等多种开发语言。

各版本的CAS可以分别从以下地址下载。

CAS Server的下载地址:http://downloads.jasig.org/cas/

CAS Client的下载地址:http://downloads.jasig.org/cas-clients/

本文验证环境使用CASServer 3.5.2、CAS Client 3.2.1(Java Client端)、CAS1.3.2(PHP Client端)。当前网上可查找到的大部分资料并不适用于CAS Server 3.5.2,因此如果使用其它版本本文可能也存在不适用的情况。

三、            CAS部署、基本配置与使用

1.      Server端部署

将下载的CASServer压缩包解压,可以发现这个包中已经包含了Server侧的全部源代码及编译完成的Jar及war包。将modules目录下的cas-server-webapp-3.5.2.war拷贝至Tomcat的webapps下后启动Tomcat即可完成部署。

上述war包中包含了Server的版本号,因此部署完成后的应用访问URL中也会包含版本信息。如果期望为Client端提供更多的伸缩性和兼容性,可以在启动Tomcat前将war包的名称修改为cas.war。这样如果以后Server端进行升级,Client端也不需要做任何修改。

部署完成并启动Tomcat以后,就可以在浏览器中输入对应的URL(例如:http://192.168.202.176:8080/cas)访问CAS了。CAS Server提供的默认界面如下图所示。

在Username与Password输入框中输入相同的字符即可成功登录,登录成功后的界面如下图。

2.      Server端配置

上述部署完成的Server存在两个问题,一是通过HTTP协议访问服务安全性较差,通常应当使用HTTPS协议以提供较高的安全性;另一方面登录账号与密码其实与系统不存在关联,不能在实际应用中加以使用,因此需要进一步做一些配置解决上述问题。

2.1 配置Tomcat的HTTPS协议

为Tomcat配置HTTPS协议分为两步,一是为Tomcat生成服务证书并将对应CA根证书导入keystore的可信列表中,二是修改Tomcat的配置文件。

关于证书生成,不同的应用场景与需求其具体过程会有一些差异。如果对此没有特殊要求,可以采用最为简单的自签名证书。其具体生成过程简述如下:

创建一个用于保存证书的目录,然后通过cmd命令进入命令提示符窗口,并将当前工作目录切换至刚刚创建的用于保存证书的目录(Linux系统过程类似)。随后执行以下命令,其中红色部分可以根据实际需要加以替换:

keytool-genkey -aliascas_key -keyalg RSA -storepass yanzhijun -keystorecas.keystore-validity 3600

注意:如果上述命令执行时提示找不到keytool,请检查环境变量JAVA_HOME和PATH是否已正确配置。

随后,keytool会提示输入一些与证书相关的信息,例如可以依次输入下图中所示值。其中特别要注意的是要输入的第一项“passport.yanzhijun.net”必须要输入CAS Server的实际域名或IP,否则在后面建立HTTPS连接时将不能建立可信连接。其它项可以根据实际情况输入或随意输入合法值即可。

上述命令成功执行以后,将生成名为cas.keystore的文件,Tomcat将使用它来建立HTTPS连接。

通常CAS Client端与Server端进行通信时也使用HTTPS协议并通过证书对Server进行身份确认,因此还需要将上述步骤中生成的证书导出备用。以下命令将证书导出为名为cas.cer的文件:

keytool-export -trustcacerts -alias cas_key -file cas.cer -keystore cas.keystore-storepass yanzhijun

注意:上述命令中的参数要与生成证书的命令中的参数保持对应一致。

完成证书生成以后,还需要对Tomcat的配置文件conf/server.xml进行修改。首先将标签Connectorport="8443"前后的注释删除,然后将其修改为类似以下内容:

<Connectorport="8443"protocol="org.apache.coyote.http11.Http11NioProtocol"SSLEnabled="true"

              maxThreads="150" scheme="https"secure="true"

              clientAuth="false" sslProtocol="TLS"

              keystoreFile="C:/cert/cas.keystore"

                keystorePass="yanzhijun"/>

注意:keystoreFile与keystorePass要与生成证书时输入的参数保持一致。

至此,Tomcat的HTTPS协议配置完成,重新启动Tomcat,就可以使用HTTPS协议访问cas了(例如https://passport.yanzhijun.net:8443/cas)。如果必要,可以将前述生成的cas.cer导入系统或浏览器的证书库中,以便访问CAS Server时浏览器不再显示警告信息。

2.2 配置CAS从数据库中取得数据验证登录的有效性

         CASServer提供了多种身份验证方法,可以配置文件WEB-INF/deployerConfigContext.xml中对其加以修改。

         在deployerConfigContext.xml中查找“<property name="authenticationHandlers">”,其中以下配置表明登录时Username与Password一致则通过验证。

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

         要使用数据库中的信息对登录进行验证,需要将上述bean配置项注释或删除掉,然后在对应位置添加以下配置:

<beanclass="org.jasig.cas.adaptors.jdbc.QueryDatabaseAuthenticationHandler">

              <property name="sql" value="selectpassword fromuserinfowhereuserName=?" />

              <property name="dataSource" ref="dataSource"/>

</bean>

         其中userinfo是保存用户信息的表名,userName是表userinfo中存储用户名的字段名称,password则是表userinfo中存储用户密码(或加密后的密码)的字段名称。

         如果数据库中的密码是加密存储的(通常都应加密存储),则上述配置中需要增加名为“passwordEncoder”的property指定加密方法。例如以下配置指定了以SHA加密密码。

<propertyname="passwordEncoder"> 

      <beanclass="org.jasig.cas.authentication.handler.DefaultPasswordEncoder"> 

            <constructor-argvalue="SHA"/> 

      </bean> 

</property>

         在指定从数据库中查询用户信息进行验证时,同时指定了要使用数据源dataSource,因此还需要对数据源进行配置。以下数据源配置使用位于本机的MySQL数据库,可以将其配置在节点beans下的任意位置。

<beanid="dataSource"class="org.springframework.jdbc.datasource.DriverManagerDataSource">

          <property name="driverClassName"value="com.mysql.jdbc.Driver"></property>

          <property name="url"value="jdbc:mysql://localhost:3306/cas_usr"></property>

          <property name="username"value="cas_usr"></property>

          <property name="password"value="123"></property> 

</bean>

         注意:使用数据库时需要将与之对应的数据库Java驱动拷入WEB-INF/lib目录下。

         至此,CAS Server全部搭建完成。

3.      Java Client端配置与使用

首先需要将下载的JavaClient压缩包解压并在解压后将modules目录下的cas-client-core-3.2.1.jar及commons-logging-1.1.jar拷入准备集成CAS的Web应用的WEB-INF/lib下。

随后需要在Web应用的web.xml文件中添加CAS的相关配置,具体配置项如下,请注意修改其中CAS Server的地址、端口信息及当前应用的地址、端口信息。

<filter>

                   <filter-name>CASAuthentication Filter</filter-name>

                   <filter-class>

                            org.jasig.cas.client.authentication.AuthenticationFilter

                   </filter-class>

                   <!-- CAS验证服务器地址-->

                   <init-param>

                            <param-name>casServerLoginUrl</param-name>

                            <param-value>

                                    https://passport.yanzhijun.net:8443/cas/login

                            </param-value>

                   </init-param>

                   <init-param>

                            <param-name>renew</param-name>

                            <param-value>false</param-value>

                   </init-param>

                   <init-param>

                            <param-name>gateway</param-name>

                            <param-value>false</param-value>

                   </init-param>

                   <!--客户端应用服务器地址-->

                   <init-param>

                            <param-name>serverName</param-name>

                            <param-value>http://192.168.202.176:8080</param-value>

                   </init-param>

         </filter>

 

         <!--负责Ticket校验-->

         <filter>

                   <filter-name>CASValidation Filter</filter-name>

                   <filter-class>                     

                            org.jasig.cas.client.validation.Cas20ProxyReceivingTicketValidationFilter

                   </filter-class>

                   <!-- CAS验证服务器地址(上下文) -->

                   <init-param>

                            <param-name>casServerUrlPrefix</param-name>

                            <param-value>https://passport.yanzhijun.net:8443/cas/</param-value>

                   </init-param>

                   <!--客户端应用服务器地址-->

                   <init-param>

                            <param-name>serverName</param-name>

                            <param-value>http://192.168.202.176:8080</param-value>

                   </init-param>

                   <init-param>

                            <param-name>useSession</param-name>

                            <param-value>true</param-value>

                   </init-param>

                   <init-param>

                            <param-name>redirectAfterValidation</param-name>

                            <param-value>true</param-value>

                   </init-param>

         </filter>

 

         <filter>

                   <filter-name>CASHttpServletRequest Wrapper Filter</filter-name>

                   <filter-class>

                            org.jasig.cas.client.util.HttpServletRequestWrapperFilter

                   </filter-class>

         </filter>

 

         <filter>

                   <filter-name>CASAssertion Thread Local Filter</filter-name>

                   <filter-class>

                            org.jasig.cas.client.util.AssertionThreadLocalFilter

                   </filter-class>

         </filter>

 

         <filter-mapping>

                   <filter-name>CAS AuthenticationFilter</filter-name>

                   <url-pattern>/*</url-pattern>

         </filter-mapping>

 

         <filter-mapping>

                   <filter-name>CASValidation Filter</filter-name>

                   <url-pattern>/*</url-pattern>

         </filter-mapping>

 

         <filter-mapping>

                   <filter-name>CAS HttpServletRequestWrapper Filter</filter-name>

                   <url-pattern>/*</url-pattern>

         </filter-mapping>

 

         <filter-mapping>

                   <filter-name>CASAssertion Thread Local Filter</filter-name>

                   <url-pattern>/*</url-pattern>

         </filter-mapping>

至此,CAS机制已经可以发挥作用了,如果尝试打开Web应用,可以发现页面跳转到了CAS Server的登录页面,输入正确的Username与Password并提交后页面又跳转回当前Web应用。不过通常Web应用程序也需要知道当前登录的用户名称,以下示例JSP页面显示了在Web应用中获取当前登录用户名的几种方法。

<%@pageimport="org.jasig.cas.client.authentication.AttributePrincipal" %>

<%@page import="org.jasig.cas.client.validation.Assertion"%>

 

<%

String loginName1 = request.getRemoteUser();

%>

request.getRemoteUser(): <%=loginName1%><br/>

 

<%

AttributePrincipal principal = (AttributePrincipal)request.getUserPrincipal();

String loginName2 = principal.getName();

%>

request.getUserPrincipal().getName():<%=loginName2%><br/>

 

<%

         Object object =request.getSession().getAttribute("_const_cas_assertion_");

         Assertion assertion =(Assertion)object;

         String loginName3 =assertion.getPrincipal().getName();

%>

request.getSession().getAttribute("_const_cas_assertion_").getPrincipal().getName():<%=loginName3%><br/>

查看上述代码运行后输出的结果,可以看到三种方式取得的用户称是一样的,均与登录时的名称保持一致。

4.      PHP Client端使用

解压PHP Client压缩包,将文件夹CAS及文件CAS.php拷至需要集成CAS的PHP应用的适当位置。修改docs/examples目录下的文件example_simple.php如下,并令example_simple.php与文件夹CAS及文件CAS.php同一目录,在浏览器中访问example_simple.php,页面将显示当前登录的用户名称。

<?php

require_once'CAS.php';

phpCAS::client(CAS_VERSION_2_0,'passport.yanzhijun.net',8443, '/cas');

phpCAS::setNoCasServerValidation();

phpCAS::forceAuthentication();

if(isset($_REQUEST['logout'])) {

         phpCAS::logout();

}

 

// forthis test, simply print that the authentication was successfull

?>

<html>

  <head>

    <title>phpCAS simpleclient</title>

  </head>

  <body>

    <h1>Successfull Authentication!</h1>

    <p>the user's login is<b><?php echo phpCAS::getUser(); ?></b>.</p>

    <p>phpCAS version is<b><?php echo phpCAS::getVersion(); ?></b>.</p>

    <p><ahref="?logout=">Logout</a></p>

  </body>

</html>

 

四、            CAS单点登录取得更多用户信息

通过上述部署与配置,多个Web应用已经可以共用一个登录服务。但是,上述过程中作为CAS Client端的Web应用只取得了用户登录名称信息,而在实际应用中,Web应用往往需要获得登录用户更多的信息,例如会员等级、性别、住址等。要达到此目的,只需对Server端稍做修改即可实现。

1.      服务端配置及修改

假定上述存储用户信息的数据表userinfo中还包含一个名为address的用于存储用户地址的字段,而Web应用程序希望能够从CAS Server处获得当前登录用户的地址信息,则Server端需要按以下内容修改deployerConfigContext.xml。部分配置说明请参见注释。

<!--将原有attributeRepository配置注释 -->        

<!--

<beanid="attributeRepository"

           class="org.jasig.services.persondir.support.StubPersonAttributeDao">

           <propertyname="backingMap">

                    <map>

                             <entrykey="uid" value="uid" />

                             <entrykey="eduPersonAffiliation" value="eduPersonAffiliation"/>

                             <entrykey="groupMembership" value="groupMembership" />

                    </map>

           </property>

</bean>

-->

<!--新增attributeRepository配置(开始) -->

<bean class="org.jasig.services.persondir.support.jdbc.SingleRowJdbcPersonAttributeDao"id="attributeRepository">

        <!-- 指定使用的数据源,此处dataSource是已配置好的数据源 -->

        <constructor-arg index="0"ref="dataSource"/>

        <!-- 从数据库中查询信息的SQL语句,通常只需要修改表名即可 -->

       <constructor-arg index="1" value="select * fromuserinfo where {0}"/>

        <propertyname="queryAttributeMapping">

            <map>

 <!-- 上述查询的参数,将userName替换为表中表示用户名的字段名称 -->

                <entrykey="username" value="userName"/>

            </map>

        </property>

        <propertyname="resultAttributeMapping">

            <map>

<!-- 需要返回给Web应用的其它信息,多个信息时可继续增加entry节点-->

<!--key值为数据表中的字段名称,value值为Client端取值时的名称标识-->

                <entry key="address" value="address"/>

            </map>

        </property>

</bean>

     <!--新增attributeRepository配置(结束) -->

<bean

           id="serviceRegistryDao"

       class="org.jasig.cas.services.InMemoryServiceRegistryDaoImpl">

            <propertyname="registeredServices">

                <list>

                    <beanclass="org.jasig.cas.services.RegexRegisteredService">

                        <propertyname="id" value="0" />

                        <propertyname="name" value="HTTP and IMAP" />

                        <propertyname="description" value="Allows HTTP(S) and IMAP(S)protocols" />

                        <propertyname="serviceId" value="^(https?|imaps?)://.*" />

                        <propertyname="evaluationOrder" value="10000001" />

                        <!--增加此项配置 -->

                       <property name="ignoreAttributes" value="true"/>

                    </bean>

                    … …                  

                </list>

            </property>

        </bean>

CASServer要将额外的信息传递至Client端,还需要修改完成信息组装的文件WEB-INF/view/jsp/protocol/2.0/casServiceValidationSuccess.jsp。casServiceValidationSuccess.jsp负责组装包含用户信息的XML,因此修改部分是将需要传递的额外信息加入到它最终生成的XML文件之中。具体修改如下:

<cas:serviceResponsexmlns: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:iftest="${fn:length(assertion.chainedAuthentications[fn:length(assertion.chainedAuthentications)-1].principal.attributes)> 0}">

                    <cas:attributes>

                             <c:forEachvar="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>

<!-- 新增额外信息(结束) -->

           <c:if test="${not emptypgtIou}">

                    <cas:proxyGrantingTicket>${pgtIou}</cas:proxyGrantingTicket>

           </c:if>

           <c:if test="${fn:length(assertion.chainedAuthentications)> 1}">

                    <cas:proxies>

                             <c:forEachvar="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>

</cas:authenticationSuccess>

</cas:serviceResponse>

 

2.      Java Client端取得更多用户信息

Java Client端不需要做任何修改就可以继续正常使用CAS服务,如果需要取得用户更多信息,可以通过AttributePrincipal对象取得Attribute列表(一个Map对象)后进行查询。

修改前述Java Client的示例代码,在最后追加取得address信息的代码,重启服务并重新访问页面,可以看到页面上显示了当前用户的address信息。

<%@pageimport="org.jasig.cas.client.authentication.AttributePrincipal" %>

<%@pageimport="org.jasig.cas.client.validation.Assertion" %>

<%@page import="java.util.*" %>

 

<%

String loginName1 = request.getRemoteUser();

%>

request.getRemoteUser(): <%=loginName1%><br/>

 

<%

AttributePrincipal principal = (AttributePrincipal)request.getUserPrincipal();

String loginName2 = principal.getName();

%>

request.getUserPrincipal().getName():<%=loginName2%><br/>

 

<%

         Object object =request.getSession().getAttribute("_const_cas_assertion_");

         Assertion assertion =(Assertion)object;

         String loginName3 =assertion.getPrincipal().getName();

%>

request.getSession().getAttribute("_const_cas_assertion_").getPrincipal().getName():<%=loginName3%><br/>

 

<br/>

<%

// 以下代码取得address信息

Map<String, Object> attributes = principal.getAttributes();

Iterator it = attributes.keySet().iterator();

String address = "NoAddress";

Object oaddress=attributes.get("address");

if(oaddress != null)

{

         address =oaddress.toString();

}

%>

address:<%=address%><br/>

3.      PHP Client端取得更多用户信息

PHP Client要取得额外的用户信息只需要直接调用phpCAS::getAttribute即可,例如要取得上述配置中增加的address信息,只需要在适当位置增加以下代码:

phpCAS::getAttribute('address');

时间: 2024-10-25 17:34:54

单点登录系统CAS筹建及取得更多用户信息的实现的相关文章

求资源-使用cas集成shiro框架生成单点登录系统

问题描述 使用cas集成shiro框架生成单点登录系统 谁有使用cas集成shiro框架生成单点登录系统的源码,最好是spring方式的,急用,谢了. 解决方案 http://www.360doc.com/content/15/0129/15/21706453_444745343.shtml

单点登录系统(SSO)详细设计说明书(上篇)

单点登录系统(SSO)详细设计说明书(上篇) 收藏 1.引言1.1编写目的              为了单点登录系统(SSO系统)的可行性,完整性,并能按照预期的设想实现该系统,特编写需求说明书.        同时,说明书也发挥与策划和设计人员更好地沟通的作用. 1.2背景          a.鉴于集团运营的多个独立网站(称为成员站点),每个网站都具有自己的身份验证机制,这样势必造成:生活中的             一位用户,如果要以会员的身份访问网站,需要在每个网站上注册,并且通过身份

单点登录系统(SSO)详细设计说明书(下篇)

单点登录系统(SSO)详细设计说明书(下篇) 收藏   3.3输入输出要求解释各输入输出数据的类型,并逐项对格式.数值范围.精度等作出准确定义.对软件的数据输出及必须标明的控制输出量进行解释并举例,包括对硬拷贝报告(正常结果输出.状态输出及异常输出)以及图形或显示报告的描述. 3.4 流程逻辑      3.4.1注册流程图       3.4.2会员登录流程图       3.4.3 会员登出流程图           3.4.4 会员修改密码流程图         3.4.5 会员找回密码流

android-安卓多后台单点登录问题CAS

问题描述 安卓多后台单点登录问题CAS 大神们好,现在公司需要做一个app,一共用得到了三个后台的数据,但是用户不同步,所以需要一个单点服务,请问大神们对于app下面的web单点有什么好的解决办法吗? 解决方案 http://www.android100.org/html/201501/28/105537.html 解决方案二: webshell定时器与CAS单点冲突的奇葩问题CAS单点登录

技术-java权限+单点登录系统做过的同学进来

问题描述 java权限+单点登录系统做过的同学进来 最近工作不忙,想自己搞一个权限+单点登录系统.权限大概涉及组织.职位.人.菜单.按钮等,所有通过单点登录的系统,都用这套权限. 有没有搞过的大神,java 用哪些技术实现?给指点指点.

SSO单点登录系统接入的例子

简单讲一下 SSO 单点登录系统的接入的原理,前提是系统本身有完善的用户认证功能,即基本的用户登录功能,那做起来就很方便了. SSO 登录请求接口往往是接口加上一个回调地址,访问这个地址会跳转到回调地址并带上一个 ticket 参数,拿着这个 ticket 参数再请求接口可以获取到用户信息,如果存在用户则自动登录,不存在就新增用户并登录. 比如这个 SSO 模型实现了两个方法,一个是获取接口 url,一个是凭 ticket 获取用户信息: PHP interface SSOLogin {    

SSO - 我们为何需要单点登录系统

SSO,Single Sign On,也就是单点登录,保证一个账户在多个系统上实现单一用户的登录 现在随着网站的壮大,很多服务会进行拆分,会做SOA服务,会使用dubbo做微服务,或者简单的小型分布式, 这样在服务与服务之间,或者系统与系统之间都是通过HTTP或者restful来进行通信的, 在以往的单系统应用中,我们都是把user存入session中的,需要用到的时候随时取,如果取不到就跳转到登录注册页面,非常简单的原理 但是在现如今的分布式应用中,如何保证session同步呢? 比如订单服务

LemonLDAP::NG v1.0.3发布 模块化的Web单点登录系统

Lemonldap::NG 是一个模块化的 Web  单点登录系统,基于 Apache::Session 模块.它简化了构建应用程序的保护区域.可管理认证和授权,可实现完全的 AAA 保护.LemonLDAP::NG 是在 Lemonldap 基础上完全重新,tar包中包含所需的所有组件,不过为 Lemonldap 开发的模块将无法在 LemonLDAP::NG 上使用. LemonLDAP::NG is an open source Web Single Sign On product (We

Web 单点登录系统 JA-SIG CAS

JA-SIG CAS(Central Authentication Service)为Web应用系统提供了单点登录服务.它的特性包括:一个开放和具有很好文档支持的协议:一个Java开源服务器组件:提供多种类型的客 户端包括Java..Net.PHP.Perl.Apache.uPortal等:能够与uPortal.BlueSocket.TikiWiki. Mule. Liferay.Moodle集成使用. -------------------------------------- 背景知识: 什