CAS搭建+MySQL认证+自定义加密+PHP客户端

第一篇博客,折腾了好久,以前没什么写博客的习惯,这次强行装个B

工程环境以及模块版本

  1. CentOS 6.3 x86_64
  2. Java 1.7
  3. CAS-server 4.0.0
  4. tomcat 6
  5. MySQL 5.1
  6. PHP 5.3.3

安装Java环境

Java应该都会装,懒得写了。。。

部署tomcat

安装

1
$ yum install tomcat6.x86_64

启动

1
$ service tomcat6 start

tomcat日志(/var/log/tomcat6/catalina.out)中有一个报错

  • 安装OpenSSL

  • 安装APR(Apache Portable Runtime)

  • 安装tomcat-native

    1
    2
    3
    4
    $ tar zxvf tomcat-native.tar.gz
    $ cd ./tomcat-native-1.1.33-src/jni/native
    $ ./configure --with-apr=/usr/local/apr --with-java-home=/usr/local/java
    $ make && make install

    加载APR的环境变量,编辑/etc/profile,添加

    1
    2
    LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/apr/lib
    export LD_LIBRARY_PATH

    然后执行

    1
    $ source /etc/profile

    重启tomcat,解决~

部署CAS-server

官网:http://developer.jasig.org/cas/

下载,上传服务器,解压

1
$ cp ./cas-server-4.0.0/modules/cas-server-webapp-4.0.0.war /usr/share/tomcat6/webapps/cas.war

访问:http://cas.changg-1991.com:8080/cas/login

此时还没有使用https,所以会有一个警告,接下来给自己颁发证书

  • 生成证书
    1
    $ keytool -genkey -alias changg-1991_cas -keyalg RSA -keystore /root/cas.keystore

把信息按照提示输入

  • 导出证书

    1
    $ keytool -export -file /root/changg-1991_cas.crt -alias changg-1991_cas -keystore /root/changg-1991_cas.keystore
  • 导入证书
    这一步似乎不需要,我按照网上的办法导入提示:证书回复与秘钥库中的证书是相同的

  • 编辑tomcat配置文件server.xml

    重启tomcat,日志中有一个报错

    查了半天,原来是修改server.xml中SSL的属性protocol为org.apache.coyote.http11.Http11Protocol,参考

    重启tomcat,之前的报错消失,出现新的问题

    原来是权限问题,把keysore拷贝到/home/下面一个专门的文件夹,修改文件夹用户组权限为:tomcat.tomcat,同时修改server.xml中对应的配置,参考

    重启tomcat,报错消失,还有几个没有什么卵用的报错暂时忽略,访问:https://cas.changg-1991.com:8443/cas/login?locale=zh_CN
    弹出证书无效的提示,无视之,点击继续

默认的账号密码又坑了我一会儿,网上铺天盖地的说只要账号密码一致就可以登录,屁啊,那是哪年的版本了,终于找到一个靠谱的说法,我又去配置文件里找了一下果然账号是casuser,密码是Mellon(不知道Mellon是个什么鬼),成功登录

至此CAS-server部署完毕~

部署CAS-client

官网:http://developer.jasig.org/cas-clients/

搞了一会儿,想了想不对,我最终是用PHP实现这个客户端,所以去github上搜了一下“cas php”找到:https://github.com/Jasig/phpCAS
工程下载下来并没有文档和demo,囧,用sourcetree clone了一份,有了,测试一下,访问:http://www.changg-1991.com/phpCAS/docs/examples/example_gateway.php
500错误,需要重命名配置文件为config.php
编辑config.php,配置$cas_host、$cas_context和$cas_port为刚刚搭建好的CAS-server的相关值,保存退出重新访问,又报500错误,apache的error_log报错

原来是缺少php-xml模块,yum装上,重启apache,再次访问

点击login跳转到

输入用户名密码点击登录

点击Logout

PHP的CAS-client搭建成功~

配置CAS连接MySQL进行认证

拷贝cas-server-support-jdbc-4.0.0.jar

1
$ cp /root/cas-server-4.0.0/modules/cas-server-support-jdbc-4.0.0.jar /usr/share/tomcat6/webapps/cas-server-webapp-4.0.0/WEB-INF/lib/

下载mysql-connector-java,官网:http://dev.mysql.com/downloads/connector/j/
上传服务器

1
$ cp /root/mysql-connector-java-5.1.37-bin.jar /usr/share/tomcat6/webapps/cas-server-webapp-4.0.0/WEB-INF/lib/

编辑cas/WEB-INF/deployerConfigContext.xml,注释掉

与注释同等级的地方增加标签:

1
2
3
4
5
6
7
8
9
10
11
12
<bean id="mysqlAuthenticationHandler"
class="org.jasig.cas.adaptors.jdbc.QueryDatabaseAuthenticationHandler">

<property name="sql" value="select password from foodies where foodname=?" />
<property name="dataSource" ref="dataSource" /></property>
</bean>

<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName"><value>com.mysql.jdbc.Driver</value></property>
<property name="url"><value>jdbc:mysql://localhost:3306/cas_auth</value></property>
<property name="username"><value>root</value></property>
<property name="password"><value>123456</value></property>
</bean>

接下来在下面还需要进行一个修改

数据库建库cau_auth
建表foodies

1
2
3
4
5
6
7
8
9
10
11
12
13
CREATE TABLE `foodies` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`foodname` varchar(50) NOT NULL default '',
`password` varchar(100) NOT NULL default '',
`salt` varchar(100) NOT NULL default '',
`zh_name` varchar(20) NOT NULL default '',
`email` varchar(100) NOT NULL default '',
`status_flag` tinyint(4) NOT NULL DEFAULT 0,
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
PRIMARY KEY (`id`),
UNIQUE KEY `index_foodname` (`foodname`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

在数据库中插入一条数据,重启tomcat,访问:http://www.changg-1991.com/phpCAS/docs/examples/example_gateway.php

用插入的账号密码去登录,验证OK,此时密码是明文的,接下来自定义加密方式

CAS自定义加密方式

这个地方是最最最蛋疼的,搞了好久,网上的东西不是CAS-server版本和我用的不一样,就是根本用不了,要不还有就简简单单的一个MD5加密,本着对系统负责任的态度,决定搞的彻底一些,用sha1(salt+md5(password))的模式,这块最后做下来并没有很复杂的改动,说到底就是一个耐心和坚持,还好最终搞出来了,和大家分享一下

  1. 首先修改deployerConfigContext.xml

    1
    <property name="sql" value="select salt, password from foodies where foodname=?" />
  2. 重写cas-server-support-jdbc/src/main/java/org/jasig/cas/adaptors/jdbc/QueryDatabaseAuthenticationHandler.java
    这个就是cas-server-support-jdbc.jar的源码,在下载下来的CAS-server包里有

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    /**
    * 新建一个内部类Foodies
    */

    private class Foodies {
    private String salt;
    private String password;

    public void setSalt(final String salt) {
    this.salt = salt;
    }

    public void setPassword(final String password) {
    this.password = password;
    }

    public final String getSalt() {
    return this.salt;
    }

    public final String getPassword() {
    return this.password;
    }
    }
    /**
    * 继承RowMapper,重写mapRow的方法
    */

    private class FoodiesRowMapper implements RowMapper {
    @Override
    public Object mapRow(ResultSet resultSet, int value) throws SQLException {
    Foodies foodies = new Foodies();
    foodies.setSalt(resultSet.getString("salt"));
    foodies.setPassword(resultSet.getString("password"));
    return foodies;
    }
    }

    @Override
    protected final HandlerResult authenticateUsernamePasswordInternal(final UsernamePasswordCredential credential)
    throws GeneralSecurityException, PreventedException {


    final String username = credential.getUsername();
    // final String encryptedPassword = this.getPasswordEncoder().encode(credential.getPassword());
    final String password = this.getPasswordEncoder().encode(credential.getPassword());
    try {
    // final String dbPassword = getJdbcTemplate().queryForObject(this.sql, String.class, username);
    // 这个地方和源代码不同的地方就在于,查出来的是一个RowMapper类的对象,可以携带多个值返回,对应上面配置中的select salt, password from foodies
    final Foodies foodies = (Foodies)getJdbcTemplate().queryForObject(this.sql, new FoodiesRowMapper(), username);
    final String salt = foodies.getSalt();
    final String dbPassword = foodies.getPassword();

    // 自定义的加密方式,直接替换之前的明文比较的办法,md5和sha1是用messageDigest类实现的方法
    final String encryptedPassword = this.sha1(salt + this.md5(password));
    if (!dbPassword.equals(encryptedPassword)) {
    throw new FailedLoginException("Password does not match value on record.");
    }
    } catch (final IncorrectResultSizeDataAccessException e) {
    if (e.getActualSize() == 0) {
    throw new AccountNotFoundException(username + " not found with SQL query");
    } else {
    throw new FailedLoginException("Multiple records found for " + username);
    }
    } catch (final DataAccessException e) {
    throw new PreventedException("SQL exception while executing query for " + username, e);
    } catch (final NoSuchAlgorithmException ignored) {
    // 这个exception是md5和sha1抛出来的
    }
    return createHandlerResult(credential, new SimplePrincipal(username), null);
    }

然后打jar包

1
$ jar cvf cas-server-support-jdbc-4.0.0.jar cas-server-support-jdbc/

用这个jar包去覆盖cas/WEB-INF/lib/cas-server-support-jdbc-4.0.0.jar
重启tomcat报了无数行的错误。。。我并不会java,都是边查边写的,我一直以为是我代码写错了,改了又改,直到问了我们安卓@大锅,他告诉我这是maven打的包,这才又有一丝希望,累觉不爱。。。
mac安装maven环境

1
$ brew install maven

继续打包,cd到cas-server-support-jdbc源码下面

1
$ mvn package

打了很久很久,很多downloading。。。,最后失败了,又和@大锅调了半天,改了一下pom.xml

1
$ mvn clean package -DskipTests=true -Dlicense.skip=true

终于成功了!

修改数据库中password字段为sha1(“yan”+md5(“123456”))
重启tomcat,访问:http://www.changg-1991.com/phpCAS/docs/examples/example_gateway.php
尝试用root和123456去登录,成功!

CAS登录获取更多用户信息

编辑deployerConfigContext.xml,注释掉

在同一级的位置新增

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<bean class="org.jasig.services.persondir.support.jdbc.SingleRowJdbcPersonAttributeDao" id="attributeRepository">
<constructor-arg index="0" ref="dataSource"/>
<constructor-arg index="1" value="select foodname, email from foodies where {0}"/>
<property name="queryAttributeMapping">
<map>
<entry key="username" value="foodname"/>
</map>
</property>
<property name="resultAttributeMapping">
<map>
<entry key="email" value="email"/>
</map>
</property>
</bean>

在下面还需要做一个修改

编辑cas/WEB-INF/view/jsp/protocol/2.0/casServiceValidationSuccess.jsp

客户端用phpCAS::getAttribute(‘email’)方法获取额外信息
重启tomcat,访问:http://www.changg-1991.com/phpCAS/docs/examples/example_gateway.php
返回页面

Mission Compete!

接下来要做的事

  1. 防止SQL注入
  2. 更改登录界面

CAS防止sql注入暂时用一个非常严格(select)的本机连接授权给解决了

参考
http://www.micmiu.com/enterprise-app/sso/sso-cas-sample/
http://www.micmiu.com/enterprise-app/sso/cas-server-auth-db/
http://www.kafeitu.me/sso/2010/11/05/sso-cas-full-course.html
http://showerlee.blog.51cto.com/2047005/1265405
http://www.tuicool.com/articles/7ZbEju
http://www.mkyong.com/spring/spring-jdbctemplate-querying-examples/
http://pkaq.github.io/2015/01/14/2015-01-14-CAS/

著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处
作者:changg-1991
链接:http://blog.changg-1991.com/2015/11/13/CAS搭建-MySQL认证-自定义加密-PHP客户端