Apache + Jetty 架设 CAS 单点登录
最近一段时间一直在断断续续地尝试 CAS 单点登录的问题,一般的文章,都是直接使用 Tomcat 或者 Jetty 等 Java 应用服务器直接配置 SSL 并安装 CAS 的,但我不太想让 Java 服务器直接 binding 到 443 端口,因此就想仍然用 Apache 处理 SSL 请求,并转发给 Jetty。在这个过程中,主要尝试了以下个问题:
- 如何生成自签名的证书
- 如何配置 Apache
- 如何配置 Jetty
- 安装、测试 CAS
- 把自己的 CA 证书导入到 Java 的 cacerts 文件中并测试 CAS Proxy
整个过程在 Ubuntu 7.10 上完成,现记录如下。
1. 生成自签名的证书
通常要配置 https 的服务器,都需要一个由正式的 CA 机构认证的 X509 证书。当客户端连接 https 服务器时,会通过 CA 的共钥来检查这个证书的正确性。但要获得 CA 的证书是一件很麻烦的事情,而且还要花费一定的费用。因此通常一些小的机构会是使用自签名的证书。也就是自己做 CA,给自己的服务器证书签名。
这个过程有两个主要的步骤,首先是生成自己的 CA 证书,然后再生成各个服务器的证书并为它们签名。 我是用 OpenSSL 来生成自签名证书的。
第一步是制作 CA 的证书:
以下是引用片段: openssl genrsa -des3 -out my-ca.key 2048 openssl req -new -x509 -days 3650 -key my-ca.key -out my-ca.crt |
这会生成 my-ca.key 和 my-ca.crt 文件,前者存放着使用 my-ca.crt 制作签名时必须的密钥,应当妥善保管。而后者是可以公开的。上面的命令为 my-ca.key 设定的有效期为 10 年。
用命令
以下是引用片段: openssl x509 -in my-ca.crt -text -noout |
可以查看 my-ca.crt 文件的内容。
有了 CA 证书之后,就可以为自己的服务器生成证书了:
以下是引用片段: openssl genrsa -des3 -out mars-server.key 1024 openssl req -new -key mars-server.key -out mars-server.csr openssl x509 -req -in mars-server.csr -out mars-server.crt -sha1 -CA my-ca.crt -CAkey my-ca.key -CAcreateserial -days 3650 |
前两个命令会生成 key、csr 文件,最后一个命令则通过 my-ca.crt 为 mars-server.csr 制作了 x509 的签名证书。
需要注意的是,在执行上述第二个命令时,Common Name 选项应当输入的是服务器的域名,否则在用户通过 https 协议访问时每次都会有额外的提示信息。
用命令
以下是引用片段: openssl x509 -in mars-server.crt -text -noout |
可以查看 mars-server.crt 文件的内容。
2. 配置 Apache 服务器
首先,创建 /etc/apache2/ssl 目录,将刚刚制作的 my-ca.crt、mars-server.key 和 mars-server.crt 文件拷贝到这个目录中。
接着执行命令
以下是引用片段: a2emod ssl |
激活 Apache 的 SSL 模块,然后在 /etc/apache2/sites-enable/ 中添加虚拟主机,这个过程与添加普通的虚拟主机类似,不同点在于该主机的端口应为 443。配置如下:
以下是引用片段: NameVirtualHost *:443 <VirtualHost *:443> ServerName localhost DocumentRoot /var/www SSLEngine On SSLCipherSuite HIGH:MEDIUM SSLProtocol all -SSLv2 SSLCertificateFile /etc/apache2/ssl/mars-server.crt SSLCertificateKeyFile /etc/apache2/ssl/mars-server.key SSLCACertificateFile /etc/apache2/ssl/my-ca.crt <Directory /var/www> Order deny,allow Allow from localhost </Directory> </VirtualHost> <VirtualHost *:80> ServerName localhost DocumentRoot /var/www <Directory /var/www> Order deny,allow Allow from localhost </Directory> </VirtualHost> |
以上配置保证了用户在访问 443 和 80 端口时可以看到相同的内容,而仅仅是使用的协议不同。修改好配置后,便可以重启 Apache 服务器,这时需要输入 mars-server.key 的密码。用浏览器访问
以下是引用片段: https://localhost/ |
这时应当看到一个弹出对话框,让你确认是否信任该站点的证书,选择信任后,便可以查看该站点的内容了。
由于大多数 Apache 服务器都是在服务器启动时自动启动,为了避免在启动 Apache 时输入密码,可以用以下命令生成不加密的 mars-server.key 文件:
以下是引用片段: openssl rsa -in mars-server.key -out mars-server.key.insecure |
用新生成的 mars-server.key.insecure 代替原有的 key 文件即可。
3. 配置 Jetty
Jetty 是一个很容易配置的 Java Servlet/JSP 服务器,下载解压后,用命令
以下是引用片段: java -jar start.jar |
即可执行。
由于我们希望通过 Apache 来访问 Jetty,就要激活 Jetty 对 AJP 的支持。可以用如下命令来启动服务器:
以下是引用片段: java -jar start.jar etc/jetty.xml etc/jetty-ajp.xml |
在 Apache 这一端,首先要安装 mod-jk 模块并激活它
以下是引用片段: apt-get install libapache2-mod-jk a2emod jk |
其次要编写一个 /etc/apache2/worker.properties 文件,描述一下刚刚配置好的 jetty 服务器,文件内容如下:
以下是引用片段: worker.list=jetty worker.jetty.port=8009 worker.jetty.host=127.0.0.1 worker.jetty.type=ajp13 worker.jetty.lbfactor=1 |
接着要编写一个 /etc/apache2/mods-enabled/jk.conf 文件,内容如下:
以下是引用片段: <IfModule mod_jk.c> JkWorkersFile "/etc/apache2/worker.properties" JkLogFile "/var/log/apache2/mod_jk.log" JkLogLevel info JkLogStampFormat "[%a %b %d %H:%M:%S %Y] " JkOptions +ForwardKeySize +ForwardURICompat </IfModule> |
最后,要修改刚刚的那个配置文件,让 mod_jk 来处理发送给 /cas/* 的请求,在虚拟主机的配置中加入如下命令:
以下是引用片段: JkMount /cas/* jetty |
4. 安装、测试 CAS
下载 CAS 3.x,并将 /modules/cas-server-webapp-*.war 文件复制到 jetty 的 webapps 目录下,改名为 cas.war。
此时通过浏览器访问 https://localhost/cas/ 便可看到 CAS 的界面了。我们是使用 LDAP 服务器来存储用户信息的,关于 CAS 的定制问题,稍后在其它的文章中再阐述。
我是通过 phpCAS 来对 CAS 服务器进行测试的,首先下载 phpCAS-0.6*、解压到 /var/www/phpcas 目录中。
安装 php-curl 和 php-pear,并通过 pear 安装 PEAR::DB。
以下是引用片段: pear install DB |
将 phpcas/docs/examples/ 中的文件复制到 phpcas/sources/ 目录中,修改这些文件中相关的 URL 信息,并用浏览器访问 example_simple.php,便可看到 CAS 的登录界面了。输入用户名密码后,应当可以看到登录成功的信息。
5. 将 my-ca.crt 导入到 Java 的 cacerts 文件中,并测试 CAS Proxy
CAS Proxy 的作用是让一个 CAS 的应用可以通过 CAS 来访问另一个 CAS 应用,而不需要用户多次提供密码。在这种情况下,CAS 会通过 https 访问每个 CAS 应用。由于我们的 CA 证书是自己制作的,它并不存在于 Java 的根证书列表中,这就导致 CAS 无法正常地连接我们的 https 服务器从而导致 CAS Proxy 功能不可用。要解决这个问题,必须将 my-ca.crt 文件导入到 Java 的根证书列表中。
我尝试了用 Java 提供的 keytool 来处理这个问题,但它总是要求输入 cacerts 文件的密码,而我根本没有这个密码。后来尝试用 IBM 的 keyman 解决了这个问题。keyman 是一个 GUI 程序,下载后用它来编辑 /etc/java-6-sun/security/cacerts 文件即可。注意导入密钥时,应选则 trustcacerts。
导入该密钥后,重启 Jetty 服务器,再访问 example_proxy.php 文件便可得到正确的结果了。
参考文献:
1. Van’s Apache SSL/TLS mini-HOWTO
2. Creating a self-signed SSL certificate
3. How to configure Apache SSL
4. Apache AJP13, mod_jk and mod_proxy_ajp
5. IBM KeyMan
建议继续学习:
- Netty和Jetty的Java NIO 网络框架模型分析 (阅读:4362)
- 互联网上的单点登录研究 (阅读:3989)
- 【译】无附加模块实现Drupal的多子域名下的单点登录 (阅读:2596)
- Jetty线程“互锁”导致数据传输性能降低问题分析 (阅读:2747)
- 关于 Jetty Continuation (阅读:2436)
- Jetty 8长连接上的又一个坑 (阅读:1268)
扫一扫订阅我的微信号:IT技术博客大学习
- 作者:beryl 来源: 无知的我
- 标签: CAS Jetty 单点登录
- 发布时间:2009-11-12 22:56:07
- [68] 如何拿下简短的域名
- [68] Go Reflect 性能
- [64] Oracle MTS模式下 进程地址与会话信
- [61] 图书馆的世界纪录
- [60] IOS安全–浅谈关于IOS加固的几种方法
- [60] 【社会化设计】自我(self)部分――欢迎区
- [58] android 开发入门
- [53] 视觉调整-设计师 vs. 逻辑
- [48] 读书笔记-壹百度:百度十年千倍的29条法则
- [47] 界面设计速成