浏览模式: 标准 | 列表分类:系统工程师

CAS单点登陆实例实现

下面我们以 tomcat 5.0 作为 CAS Server(server1) ,另外一台 tomcat5.0 为 client(client1)

为例进行说明。

1. 下载 cas-server 和 cas-client( 可选,建议使用)

http://www.ja-sig.org/downloads/cas/cas-server-3.0.5.zip

http://www.ja-sig.org/downloads/cas-clients/cas-client-java-2.1.1.zip

2. 将 cas-server-3.0.5.zip 解压,并将 lib/cas.war 拷贝到 server1 的 webapps 下

3. 产生 SERVER 的证书

PS: 参数与各系统本身一致

%JAVA_HOME%\bin\keytool -delete -alias tomcat -keypass changeit

%JAVA_HOME%\bin\keytool -genkey -alias tomcat -keypass changeit -keyalg RSA

%JAVA_HOME%\bin\keytool -export -alias tomcat -keypass changeit  -file %FILE_NAME%

%JAVA_HOME%\bin\keytool -import -file server.crt -keypass changeit -keystore %JAVA_HOME%/jre/lib/security/cacerts

%JAVA_HOME%\bin\keytool -import -file server.crt -keystore %JAVA_HOME%\jre\lib\security\cacerts

4. 在 server1 配置 tomcat 使用 HTTPS

$CATALINA_HOME/conf/server.xml 里

<Connector className="org.apache.coyote.tomcat5.CoyoteConnector"

port="8443" minProcessors="5" maxProcessors="75"

enableLookups="true" disableUploadTimeout="true"

acceptCount="100" debug="0" scheme="https"

secure="true">

<Factory className="org.apache.coyote.tomcat5.CoyoteServerSocketFactory"

keystoreFile="/path/to/your/keystore-file"

keystorePass="your-password" clientAuth="false" protocol="TLS" />

</Connector>

5. 在要使用 CAS 的客户端 client1 里设置(以 servlets-examples 这个 APP 为例),我们使用

ServletFilter(CAS client 里提供的 ) 来实现 SSO 的检查。

修改 servlets-examples/WEB-INF/web.xml

<filter>

<filter-name>CASFilter</filter-name>

<filter-class>edu.yale.its.tp.cas.client.filter.CASFilter</filter-class>

<init-param>

<param-name>edu.yale.its.tp.cas.client.filter.loginUrl</param-name>

<param-value>https://your.cas.server.name(eg:server1):port/cas/login</param-value>

</init-param>

<init-param>

<param-name>edu.yale.its.tp.cas.client.filter.validateUrl</param-name>

<param-value>https://your.cas.server.name(eg:server1):port/cas/proxyValidate</param-value>

</init-param>

<init-param>

<param-name>edu.yale.its.tp.cas.client.filter.serviceUrl</param-name>

<param-value>your.client.server.ip(eg:127.0.0.1):port</param-value>

</init-param>

</filter>

<filter-mapping>

<filter-name>CASFilter</filter-name>

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

</filter-mapping>

PS: 在 client 端配置 filter 时 , 需要将 CAS 的 filter 放在 web.xml 最上端 ,. 如果在你的 web.xml 有类似 encodingFilter 的 filter 也需要将这个 filter 放在 CAS filter 下面 , 否则你会发现每次访问时都需要你进行验证 。

6. 将 cas-client-java-2.1.1.zip 解压,把 java/lib/casclient.jar 拷贝到 client1 服务器上的

webapps/servlets-examples/WEB-INF/lib 目录下(如果没有就建一个)

7. 导出 SERVER 的证书,用来给所有需要用到的客户端导入

keytool -export -file server.crt -alias my-alias-name -keystore keystore-file

8. 在客户端的 JVM 里导入信任的 SERVER 的证书 ( 根据情况有可能需要管理员权限 )

keytool -import -keystore $JAVA_HOME/jre/lib/security/cacerts -file server.crt -alias my-alias-name

9.test & done.

把 server1 和 client1 分别起来,检查启动的 LOG 是否正常,如果一切 OK ,就访问

http://client1:8080/servlets-examples/servlet/HelloWorldExample

系统会自动跳转到一个验证页面,随便输入一个相同的账号 , 密码,验证通过之后就会访问

到真正的 HelloWorldExample 这个 servlet 了

实现自已的认证代码 (java 代码和相关注释 , 需要 cas-server-3.0.5.jar 包 )

package  com.mcm.sso; 

 

import  org.jasig.cas.authentication.handler.support.AbstractUsernamePasswordAuthenticationHandler; 

import  org.jasig.cas.authentication.principal.UsernamePasswordCredentials; 

import  org.springframework.util.StringUtils; 

 

public   class  MyUsernamePasswordAuthenticationHandler  extends  

              AbstractUsernamePasswordAuthenticationHandler 


 

       
public   boolean  authenticateUsernamePasswordInternal( 

                     
final  UsernamePasswordCredentials credentials) 

              
final  String username  =  credentials.getUsername(); 

              
final  String password  =  credentials.getPassword(); 

              

              
//  此处实现你的登陆验证代码 

              
if  (StringUtils.hasText(username)  &&  StringUtils.hasText(password) ) 

                     getLog().debug( 

                                   
" User [ "   +  username  +   " ] was successfully authenticated with ucix. " ); 

                     
return   true

              }
 

 

              getLog().debug(
" User [ "   +  username  +   " ] failed authentication " ); 

 

              
return   false

       }
 

 

       
protected   void  afterPropertiesSetInternal()  throws  Exception 

              
super .afterPropertiesSetInternal(); 

       }
 

}
 

 

然后将这个类配置到 deployerConfigContext.xml 文件里 , 替代 <bean class="org.jasig.cas.authentication.handler.support.SimpleTestUsernamePasswordAuthenticationHandler" />

可能要用到数据库连接之类的配置,具体可参照 spring framework 相关文档

在 client 端取到登陆相关信息及登出系统

1. 取得用用户 ID

以下两种方式都可以

session.getAttribute(CASFilter.CAS_FILTER_USER);

session.getAttribute("edu.yale.its.tp.cas.client.filter.user");

也可以直接取得认证 java 对象

session.getAttribute(CASFilter.CAS_FILTER_RECEIPT);

session.getAttribute("edu.yale.its.tp.cas.client.filter.receipt");

JSP2.0 标准写法

<c:out value="${sessionScope['edu.yale.its.tp.cas.client.filter.user']}"/>

在 jsp 中使用 CAS Tag Library 标签

除实现以上功能完还可以实现登出之类的相关功能,具体参照 cas 官方文档

http://www.ja-sig.org/products/cas/client/jsp/index.html

Tags: cas, 单点登陆

CAS单点登陆原理

总结主要来源于网上的一些文章和论坛的记录以及我自已的一些想法.
CAS (Central Authentication Service) 是 Yale 大学的 ITS 开发的一套 JAVA 实现的开源

的 SSO(single sign-on) 的服务(主要是2.0,到3.0为ja-sig)。

关键字

TGC(ticket-granting cookie)--------- 受权的票据证明

KDC( Key Distribution Center ) ---------- 密钥发放中心

Service ticket(ST) --------- 服务票据, 由 KDC 的 TGS 发放。 任何一台 Workstation 都需要拥有一张有效的 Service Ticket 才能访问域内部的应用 (Applications) 。 如果能正确接收 Service Ticket ,说明在 CASClient-CASServer 之间的信任关系已经被正确建立起来 , 通常为一张数字加密的证书

Ticket Granting tieckt(TGT) --------- 票据授权票据,由 KDC 的 AS 发放。即获取这样一张票据后,以后申请各种其他服务票据 (ST) 便不必再向 KDC 提交身份认证信息 ( 准确术语是 Credentials) 。

authentication service (AS) --------- 认证用服务,索取 Crendential ,发放 TGT

ticket-granting service (TGS) --------- 票据授权服务,索取 TGT ,发放 ST

 

CAS 单点服务器的认证过程,所有应用服务器收到应用请求后,检查 ST 和 TGT ,如果没有或不对,转到 CAS 认证服务器登陆页面,通过安全认证后得到 ST 和 TGT 再重定向到相关应用服务器,在会话生命周期之内如果再定向到别的应用,将出示

ST 和 TGT 进行认证 , 注意 , 取得 TGT 的过程是通过 SSL 安全协议的 ( 换句话说就是如果不用 ssl 协议 , 每访问一个应用服务,就得重新到认证服务中心认证一次 ) ,关于 SSL 的相关描述可以查看附录 .

 

白话描述 :

单点登陆 , 无非就是提供给用户一次登陆 , 多个系统共享用户信息的操作 .

这个是怎么操作的呢 ? 有简单的方法 , 当用户访问其他系统的时候 , 写个 URL 带上用户的 ID 和 PASS 提交到相应的系统就可以了 . 这也是一种方法

那 CAS 是怎么操作的呢 ? 或则是 KRB(Kerberos 是一个加密认证协议,允许网络用户不使用明文密码访问服务,一个普通
的协议实现包括 LOGIN 服务存在伪造欺骗对 Key Distribution Center 的响应 。

) 怎么操作的呢 ?

他并不是很复杂 , 他先是建立一个 专门认证用户的 服务 (SERVER) 这个服务只做一件事 , 负责验证用户的 ID 和 PASS 是否是正确 , 在正确的情况提供用户一个名为 TGT 的票据 ,

相当你要去游乐场玩 , 首先你要在门口检查你的身份 ( 即 CHECK 你的 ID 和 PASS), 如果你通过验证 , 游乐场的门卫 (AS) 即提供给你一张门卡 (TGT).

这张卡片的用处就是告诉 游乐场的各个场所 , 你是通过正门进来 , 而不是后门偷爬进来的 , 并且也是获取进入场所一把钥匙 .

好的 , 现在你有张卡 , 但是这对你来不重要 , 因为你来游乐场不是为了拿这张卡的 , 好的 , 我们向你的目的出发 , 恩 , 你来到一个摩天楼 , 你想进入玩玩 ,

这时摩天轮的服务员 (client) 拦下你 , 向你要求摩天轮的 (ST) 票据 , 你说你只有一个门卡 (TGT), 好的 , 那你只要把 TGT 放在一旁的票据授权机 (TGS) 上刷一下 ,

票据授权机 (TGS) 就根据你现在所在的摩天轮 , 给你一张摩天轮的票据 (ST), 哈 , 你有摩天轮的票据 , 现在你可以畅通无阻的进入摩天轮里游玩了 .

当然如果你玩完摩天轮后 , 想去游乐园的咖啡厅休息下 , 那你一样只要带着那张门卡 (TGT). 到相应的咖啡厅的票据授权机 (TGS) 刷一下 , 得到咖啡厅的票据 (ST) 就可以进入咖啡厅

当你离开游乐场后 , 想用这张 TGT 去刷打的回家的费用 , 呵呵 , 对不起 , 你的 TGT 已经过期了 , 在你离开游乐场那刻开始 , 你的 TGT 就已经销毁了 ~

 

 

Yale CAS Server 的配置过程

 

CAS (Central Authentication Service) 是 Yale 大学的 ITS 开发的一套 JAVA 实现的开源

的 SSO(single sign-on) 的服务。该服务是以一个 java web app(eg:cas.war) 来进行服务的,

使用时需要将 cas.war 发布到一个 servlet2.3 兼容的服务器上,并且服务器需要支持 SSL ,

在需要使用该服务的其他服务器(客户),只要进行简单的配置就可以实现 SSO 了。

 

CAS 的客户端可以有很多种,因为验证的结果是以 XML 的格式返回的, CAS 的客户端已

打包进去的有 java,perl,python,asp,apache module 等好几种客户端示例,你还可以根据

需要实现一个自己的客户端,非常简单 !~

Tags: cas, 单点登陆

疑难杂症咋整?

问:websphere6的下面,为什么ajax的调用会出现乱码?

答:请修改对应web-inf下面的ibm-web-ext.xmi 里面的内容,请将autoRequestEncoding="true" autoResponseEncoding="true"中的true改成false,就ok了。

继续问:为什么我改了,还不ok?

继续答:因为websphere的同步机制,在profiles下面对应的config里面,还有一个命名一摸一样的文件,ibm-web-ext.xmi ,请修改其中的相同的地方的内容。

原理猜想:websphere解析的时候,不是类似于tomcat直接解析web目录下面web-inf里面的配置文件,而是解析config里面的web-inf里面的配置文件,中间的同步的机制就不得而知,据我所知,bea的weblogic的同步是根据时间戳的,但是IBM的貌似不跟时间戳打交道,保险起见,还是手工copy的比较好。

同理,添加servlet也一样,需要手工发布2个地方的web.xml.

websphere是一个很严格的J2EE容器,它会严格的检查web.xml里面的配置,还有jsp的页面的java的写法,很多tomcat或者jboss不抛出的错误,在websphere下面都能立显无疑。

eos的应用中,往往会用到hiddensubmit.js的这个文件,也就是说,会用到隐含提交这玩意,如果不修改上面提到的ibm-web-ext.xmi,一定会出现乱码,并且是提交到pr,数据总线中就乱掉。:)

似乎应该考虑,把eos的平台升级成utf-8。

加班到11点,做个记号先!

Tags: websphere

验证文件大小

<html> 
<input type="file" name="file1" onchange="ShowSize(this.value)"> 
<script language="JavaScript">  
function ShowSize(files) 

  var fso,f; 
  fso=new ActiveXObject("Scripting.FileSystemObject"); 
  f=fso.GetFile(files); 
  alert(f.size+" Bytes"); 
}   
</script>

只是需要fso,怎么才能不用fso呢?

Tags: javascript, fso

websphere的jndi的获取

Context ctx=new InitialContext();

    
Connection conn=null;

    
Hashtable     parms     =     new     Hashtable();     

    
parms.put(Context.INITIAL_CONTEXT_FACTORY,     "com.ibm.ejs.ns.jndi.CNInitialContextFactory");     

    try{

    
ctx = new InitialContext(parms);     

    
DataSource ds = (DataSource)ctx.lookup("jdbc/test");     

    
conn     =     ds.getConnection("test","test");     

    }catch(
NamingException ne){

    
System.out.println(ne);

    }
 

Tags: websphere, jndi, 数据库