1,新建 CasClient.php

<?php

include_once (dirname ( __FILE__ ) . '/CasClientConfig.php'); // 注意这个

include_once (dirname ( __FILE__ ) . '/CAS.php'); // 注意这个

                                                  

// 初始化

phpCAS::setDebug ();

 

// initialize phpCAS

phpCAS::client ( CAS_VERSION_2_0, CAS_SERVER_HOSTNAME, CAS_SERVER_PORT, CAS_SERVER_APP_NAME );

 

// no SSL validation for the CAS server

phpCAS::setNoCasServerValidation ();

 

 

2,新建 CasClientConfig.php

 

// define ( 'CAS_SERVER_HOSTNAME', 'caslocal.youxituan.com' );

// define ( 'CAS_SERVER_PORT', 80 );

define ( 'CAS_SERVER_HOSTNAME', 'localhost' );

define ( 'CAS_SERVER_PORT', 34382 );

define ( 'CAS_SERVER_APP_NAME', "cas" );

define ( 'LocalLoginPath', '/cas/localogin.php' );

define ( 'LocalCheckPath', '/cas/logincheck.php' );

define ( 'LocalLogOffPath', '/cas/logoff.php' );

 

3, 修改 class_core.php

error_reporting(E_ALL);

 

define('IN_DISCUZ', true);

define('DISCUZ_ROOT', substr(dirname(__FILE__), 0, -12));

define('DISCUZ_CORE_DEBUG', false);

define('DISCUZ_TABLE_EXTENDABLE', false);

require_once DISCUZ_ROOT."Cas/CasClient.php";

set_exception_handler(array('core', 'handleException'));

 

if(DISCUZ_CORE_DEBUG) {

 

3,修改  function_member.php 支持 CAS 登录

 

增加一个方法

// 新加的方法,用以支持CAS 登录

function userloginCas($username, $password, $email, $uid) {

    $return = array ();

    $merge = 0;

    $status = $uid;

    $mockcallback = array($uid, $username, $password, $email, $merge);

    

    $return ['ucresult'] = $mockcallback;  

//     $return ['ucresult'] ['status'] = 0;

//     $return ['ucresult'] ['username'] = $username;

//     $return ['ucresult'] ['password'] = $password;

//     $return ['ucresult'] ['email'] = $email;

//     $return ['ucresult'] ['uid'] = $uid;

//     $return ['ucresult'] ['merge'] = $merge;

    // }

    $tmp = array ();

    $duplicate = '';

    list ( $tmp ['uid'], $tmp ['username'], $tmp ['password'], $tmp ['email'], $duplicate ) = $return ['ucresult'];

    $return ['ucresult'] = $tmp;

    if ($duplicate && $return ['ucresult'] ['uid'] > 0 || $return ['ucresult'] ['uid'] <= 0) {

        $return ['status'] = 0;

        return $return;

    }

    

    $member = getuserbyuid ( $return ['ucresult'] ['uid'], 1 );

    if (! $member || empty ( $member ['uid'] )) {

        $return ['status'] = - 1;

        return $return;

    }

    $return ['member'] = $member;

    $return ['status'] = 1;

    if ($member ['_inarchive']) {

        C::t ( 'common_member_archive' )->move_to_master ( $member ['uid'] );

    }

    if ($member ['email'] != $return ['ucresult'] ['email']) {

        C::t ( 'common_member' )->update ( $return ['ucresult'] ['uid'], array (

                'email' => $return ['ucresult'] ['email'] 

        ) );

    }

    

    return $return;

}

 

4,修改 class_member.php 添加支持 Cas登录支持

 

修改 OnLogin 方法

function on_login() {

        global $_G;

        if ($_G ['uid']) {

            $referer = dreferer ();

            $ucsynlogin = $this->setting ['allowsynlogin'] ? uc_user_synlogin ( $_G ['uid'] ) : '';

            $param = array (

                    'username' => $_G ['member'] ['username'],

                    'usergroup' => $_G ['group'] ['grouptitle'],

                    'uid' => $_G ['member'] ['uid'] 

            );

            showmessage ( 'login_succeed', $referer ? $referer : './', $param, array (

                    'showdialog' => 1,

                    'locationtime' => true,

                    'extrajs' => $ucsynlogin 

            ) );

        }

        

        list ( $seccodecheck ) = seccheck ( 'login' );

        if (! empty ( $_GET ['auth'] )) {

            $dauth = authcode ( $_GET ['auth'], 'DECODE', $_G ['config'] ['security'] ['authkey'] );

            list ( , , , $secchecklogin2 ) = explode ( "\t", $dauth );

            if ($secchecklogin2) {

                $seccodecheck = true;

            }

        }

        $seccodestatus = ! empty ( $_GET ['lssubmit'] ) ? false : $seccodecheck;

        $invite = getinvite ();

        

        // if(!submitcheck('loginsubmit', 1, $seccodestatus)) {

        if (1 == 2) {

            $auth = '';

            $username = ! empty ( $_G ['cookie'] ['loginuser'] ) ? dhtmlspecialchars ( $_G ['cookie'] ['loginuser'] ) : '';

            

            if (! empty ( $_GET ['auth'] )) {

                list ( $username, $password, $questionexist ) = explode ( "\t", authcode ( $_GET ['auth'], 'DECODE', $_G ['config'] ['security'] ['authkey'] ) );

                $username = dhtmlspecialchars ( $username );

                $auth = dhtmlspecialchars ( $_GET ['auth'] );

            }

            

            $cookietimecheck = ! empty ( $_G ['cookie'] ['cookietime'] ) || ! empty ( $_GET ['cookietime'] ) ? 'checked="checked"' : '';

            

            if ($seccodecheck) {

                $seccode = random ( 6, 1 ) + $seccode {0} * 1000000;

            }

            

            if ($this->extrafile && file_exists ( $this->extrafile )) {

                require_once $this->extrafile;

            }

            

            $navtitle = lang ( 'core', 'title_login' );

            include template ( $this->template );

        } else {

            

            if (! empty ( $_GET ['auth'] )) {

                list ( $_GET ['username'], $_GET ['password'] ) = daddslashes ( explode ( "\t", authcode ( $_GET ['auth'], 'DECODE', $_G ['config'] ['security'] ['authkey'] ) ) );

            }

            

            $loginhash = ! empty ( $_GET ['loginhash'] ) && preg_match ( '/^\w+$/', $_GET ['loginhash'] ) ? $_GET ['loginhash'] : '';

            

            if (! ($_G ['member_loginperm'] = logincheck ( $_GET ['username'] ))) {

                captcha::report ( $_G ['clientip'] );

                showmessage ( 'login_strike' );

            }

            if ($_GET ['fastloginfield']) {

                $_GET ['loginfield'] = $_GET ['fastloginfield'];

            }

            $_G ['uid'] = $_G ['member'] ['uid'] = 0;

            $_G ['username'] = $_G ['member'] ['username'] = $_G ['member'] ['password'] = '';

            

            

            phpCAS::$_PHPCAS_CLIENT->setNoClearTicketsFromUrl ();

            $auth1 = phpCAS::isAuthenticated ();

            

            $username='';

            if ($auth1) {

                $username = phpCAS::getUser ();

            } else {

                phpCAS::forceAuthentication ();

//                 showmessage ( '尚未登录,<a href="" onclick="return gocas();">前去登录</a>' );

                 

            }

 

         

            $password = '';

            $email = phpCAS::getAttribute('Email');

            $uid = phpCAS::getAttribute('Uid');

            // $result = userlogin($_GET['username'], $_GET['password'], $_GET['questionid'], $_GET['answer'], $this->setting['autoidselect'] ? 'auto' : $_GET['loginfield'], $_G['clientip']);

            $result = userloginCas ( $username, $password, $email, $uid );

            $uid = $result ['ucresult'] ['uid'];

            

            if (! empty ( $_GET ['lssubmit'] ) && ($result ['ucresult'] ['uid'] == - 3 || $seccodecheck)) {

                $_GET ['username'] = $result ['ucresult'] ['username'];

                $this->logging_more ( $result ['ucresult'] ['uid'] == - 3 );

            }

            

            if ($result ['status'] == - 1) {

                if (! $this->setting ['fastactivation']) {

                    $auth = authcode ( $result ['ucresult'] ['username'] . "\t" . FORMHASH, 'ENCODE' );

                    showmessage ( 'location_activation', 'member.php?mod=' . $this->setting ['regname'] . '&action=activation&auth=' . rawurlencode ( $auth ) . '&referer=' . rawurlencode ( dreferer () ), array (), array (

                            'location' => true 

                    ) );

                } else {

                    $init_arr = explode ( ',', $this->setting ['initcredits'] );

                    $groupid = $this->setting ['regverify'] ? 8 : $this->setting ['newusergroupid'];

                    

                    C::t ( 'common_member' )->insert ( $uid, $result ['ucresult'] ['username'], md5 ( random ( 10 ) ), $result ['ucresult'] ['email'], $_G ['clientip'], $groupid, $init_arr );

                    $result ['member'] = getuserbyuid ( $uid );

                    $result ['status'] = 1;

                }

            }

            

            if ($result ['status'] > 0) {

                

                if ($this->extrafile && file_exists ( $this->extrafile )) {

                    require_once $this->extrafile;

                }

                

                setloginstatus ( $result ['member'], $_GET ['cookietime'] ? 2592000 : 0 );

                checkfollowfeed ();

                if ($_G ['group'] ['forcelogin']) {

                    if ($_G ['group'] ['forcelogin'] == 1) {

                        clearcookies ();

                        showmessage ( 'location_login_force_qq' );

                    } elseif ($_G ['group'] ['forcelogin'] == 2 && $_GET ['loginfield'] != 'email') {

                        clearcookies ();

                        showmessage ( 'location_login_force_mail' );

                    }

                }

                

                if ($_G ['member'] ['lastip'] && $_G ['member'] ['lastvisit']) {

                    dsetcookie ( 'lip', $_G ['member'] ['lastip'] . ',' . $_G ['member'] ['lastvisit'] );

                }

                C::t ( 'common_member_status' )->update ( $_G ['uid'], array (

                        'lastip' => $_G ['clientip'],

                        'port' => $_G ['remoteport'],

                        'lastvisit' => TIMESTAMP,

                        'lastactivity' => TIMESTAMP 

                ) );

                $ucsynlogin = $this->setting ['allowsynlogin'] ? uc_user_synlogin ( $_G ['uid'] ) : '';

                

                $pwold = false;

                if ($this->setting ['strongpw'] && ! $this->setting ['pwdsafety']) {

                    if (in_array ( 1, $this->setting ['strongpw'] ) && ! preg_match ( "/\d+/", $_GET ['password'] )) {

                        $pwold = true;

                    }

                    if (in_array ( 2, $this->setting ['strongpw'] ) && ! preg_match ( "/[a-z]+/", $_GET ['password'] )) {

                        $pwold = true;

                    }

                    if (in_array ( 3, $this->setting ['strongpw'] ) && ! preg_match ( "/[A-Z]+/", $_GET ['password'] )) {

                        $pwold = true;

                    }

                    if (in_array ( 4, $this->setting ['strongpw'] ) && ! preg_match ( "/[^a-zA-z0-9]+/", $_GET ['password'] )) {

                        $pwold = true;

                    }

                }

                

                if ($_G ['member'] ['adminid'] != 1) {

                    if ($this->setting ['accountguard'] ['loginoutofdate'] && $_G ['member'] ['lastvisit'] && TIMESTAMP - $_G ['member'] ['lastvisit'] > 90 * 86400) {

                        C::t ( 'common_member' )->update ( $_G ['uid'], array (

                                'freeze' => 2 

                        ) );

                        C::t ( 'common_member_validate' )->insert ( array (

                                'uid' => $_G ['uid'],

                                'submitdate' => TIMESTAMP,

                                'moddate' => 0,

                                'admin' => '',

                                'submittimes' => 1,

                                'status' => 0,

                                'message' => '',

                                'remark' => '' 

                        ), false, true );

                        manage_addnotify ( 'verifyuser' );

                        showmessage ( 'location_login_outofdate', 'home.php?mod=spacecp&ac=profile&op=password&resend=1', array (

                                'type' => 1 

                        ), array (

                                'showdialog' => true,

                                'striptags' => false,

                                'locationtime' => true 

                        ) );

                    }

                    

                    if ($this->setting ['accountguard'] ['loginpwcheck'] && $pwold) {

                        $freeze = $pwold;

                        if ($this->setting ['accountguard'] ['loginpwcheck'] == 2 && $freeze) {

                            C::t ( 'common_member' )->update ( $_G ['uid'], array (

                                    'freeze' => 1 

                            ) );

                        }

                    }

                }

                

                $seccheckrule = & $_G ['setting'] ['seccodedata'] ['rule'] ['login'];

                if ($seccheckrule ['allow'] == 2) {

                    if ($seccheckrule ['nolocal']) {

                        require_once libfile ( 'function/misc' );

                        $lastipConvert = process_ipnotice ( convertip ( $_G ['member'] ['lastip'] ) );

                        $nowipConvert = process_ipnotice ( convertip ( $_G ['clientip'] ) );

                        if ($lastipConvert != $nowipConvert && stripos ( $lastipConvert, $nowipConvert ) == false && stripos ( $nowipConvert, $lastipConvert ) == false) {

                            $seccodecheck = true;

                        }

                    }

                    if (! $seccodecheck && $seccheckrule ['pwsimple'] && $pwold) {

                        $seccodecheck = true;

                    }

                    if (! $seccodecheck && $seccheckrule ['outofday'] && $_G ['member'] ['lastvisit'] && TIMESTAMP - $_G ['member'] ['lastvisit'] > $seccheckrule ['outofday'] * 86400) {

                        $seccodecheck = true;

                    }

                    if (! $seccodecheck && $_G ['member_loginperm'] < 4) {

                        $seccodecheck = true;

                    }

                    if (! $seccodecheck && $seccheckrule ['numiptry']) {

                        $seccodecheck = failedipcheck ( $seccheckrule ['numiptry'], $seccheckrule ['timeiptry'] );

                    }

                    if ($seccodecheck && ! $secchecklogin2) {

                        clearcookies ();

                        $auth = authcode ( $_GET ['username'] . "\t" . $_GET ['password'] . "\t" . ($_GET ['questionid'] ? 1 : 0) . "\t1", 'ENCODE', $_G ['config'] ['security'] ['authkey'] );

                        $location = 'member.php?mod=logging&action=login&auth=' . rawurlencode ( $auth ) . '&referer=' . rawurlencode ( dreferer () ) . (! empty ( $_GET ['cookietime'] ) ? '&cookietime=1' : '');

                        if (defined ( 'IN_MOBILE' )) {

                            showmessage ( 'login_seccheck2', $location );

                        } else {

                            $js = '<script type="text/javascript">location.href=\'' . $location . '\'</script>';

                            showmessage ( 'login_seccheck2', '', array (

                                    'type' => 1 

                            ), array (

                                    'extrajs' => $js 

                            ) );

                        }

                    }

                }

                

                if ($invite ['id']) {

                    $result = C::t ( 'common_invite' )->count_by_uid_fuid ( $invite ['uid'], $uid );

                    if (! $result) {

                        C::t ( 'common_invite' )->update ( $invite ['id'], array (

                                'fuid' => $uid,

                                'fusername' => $_G ['username'] 

                        ) );

                        updatestat ( 'invite' );

                    } else {

                        $invite = array ();

                    }

                }

                if ($invite ['uid']) {

                    require_once libfile ( 'function/friend' );

                    friend_make ( $invite ['uid'], $invite ['username'], false );

                    dsetcookie ( 'invite_auth', '' );

                    if ($invite ['appid']) {

                        updatestat ( 'appinvite' );

                    }

                }

                

                $param = array (

                        'username' => $result ['ucresult'] ['username'],

                        'usergroup' => $_G ['group'] ['grouptitle'],

                        'uid' => $_G ['member'] ['uid'],

                        'groupid' => $_G ['groupid'],

                        'syn' => $ucsynlogin ? 1 : 0 

                );

                

                $extra = array (

                        'showdialog' => true,

                        'locationtime' => true,

                        'extrajs' => $ucsynlogin 

                );

                

                if (! $freeze || ! $this->setting ['accountguard'] ['loginpwcheck']) {

                    $loginmessage = $_G ['groupid'] == 8 ? 'login_succeed_inactive_member' : 'login_succeed';

                    $location = $invite || $_G ['groupid'] == 8 ? 'home.php?mod=space&do=home' : dreferer ();

                } else {

                    $loginmessage = 'login_succeed_password_change';

                    $location = 'home.php?mod=spacecp&ac=profile&op=password';

                    $_GET ['lssubmit'] = 0;

                }

                if (empty ( $_GET ['handlekey'] ) || ! empty ( $_GET ['lssubmit'] )) {

                    if (defined ( 'IN_MOBILE' )) {

                        showmessage ( $loginmessage, $location, $param, array (

                                'location' => true 

                        ) );

                    } else {

                        if (! empty ( $_GET ['lssubmit'] )) {

                            if (! $ucsynlogin) {

                                $extra ['location'] = true;

                            }

                            showmessage ( $loginmessage, $location, $param, $extra );

                        } else {

                            $href = str_replace ( "'", "\'", $location );

                            showmessage ( 'location_login_succeed', $location, array (), array (

                                    'showid' => 'succeedmessage',

                                    'extrajs' => '<script type="text/javascript">' . 'setTimeout("window.location.href =\'' . $href . '\';", 3000);' . '$(\'succeedmessage_href\').href = \'' . $href . '\';' . '$(\'main_message\').style.display = \'none\';' . '$(\'main_succeed\').style.display = \'\';' . '$(\'succeedlocation\').innerHTML = \'' . lang ( 'message', $loginmessage, $param ) . '\';</script>' . $ucsynlogin,

                                    'striptags' => false,

                                    'showdialog' => true 

                            ) );

                        }

                    }

                } else {

                    showmessage ( $loginmessage, $location, $param, $extra );

                }

            } else {

                $password = preg_replace ( "/^(.{" . round ( strlen ( $_GET ['password'] ) / 4 ) . "})(.+?)(.{" . round ( strlen ( $_GET ['password'] ) / 6 ) . "})$/s", "\\1***\\3", $_GET ['password'] );

                $errorlog = dhtmlspecialchars ( TIMESTAMP . "\t" . ($result ['ucresult'] ['username'] ? $result ['ucresult'] ['username'] : $_GET ['username']) . "\t" . $password . "\t" . "Ques #" . intval ( $_GET ['questionid'] ) . "\t" . $_G ['clientip'] );

                writelog ( 'illegallog', $errorlog );

                loginfailed ( $_GET ['username'] );

                failedip ();

                $fmsg = $result ['ucresult'] ['uid'] == '-3' ? (empty ( $_GET ['questionid'] ) || $answer == '' ? 'login_question_empty' : 'login_question_invalid') : 'login_invalid';

                if ($_G ['member_loginperm'] > 1) {

                    showmessage ( $fmsg, '', array (

                            'loginperm' => $_G ['member_loginperm'] - 1 

                    ) );

                } elseif ($_G ['member_loginperm'] == - 1) {

                    showmessage ( 'login_password_invalid' );

                } else {

                    showmessage ( 'login_strike' );

                }

            }

        }

    }

    

 

 

修改 on_logout 支持同步退出

function on_logout() {

        global $_G;

        

        $ucsynlogout = $this->setting ['allowsynlogin'] ? uc_user_synlogout () : '';

        

        if ($_GET ['formhash'] != $_G ['formhash']) {

            showmessage ( 'logout_succeed', dreferer (), array (

                    'formhash' => FORMHASH,

                    'ucsynlogout' => $ucsynlogout,

                    'referer' => rawurlencode ( dreferer () ) 

            ) );

        }

        

        clearcookies ();

        $_G ['groupid'] = $_G ['member'] ['groupid'] = 7;

        $_G ['uid'] = $_G ['member'] ['uid'] = 0;

        $_G ['username'] = $_G ['member'] ['username'] = $_G ['member'] ['password'] = '';

        $_G ['setting'] ['styleid'] = $this->setting ['styleid'];

        

        if (defined ( 'IN_MOBILE' )) {

            showmessage ( 'location_logout_succeed_mobile', dreferer (), array (

                    'formhash' => FORMHASH,

                    'referer' => rawurlencode ( dreferer () ) 

            ) );

        } else {

            // 退出

            $service =  dreferer ()  ;

            phpCAS::logoutWithRedirectService ( $service );

            // 后面这个showmessage提示实际上已经不会执行了

//             showmessage ( 'logout_succeed', dreferer (), array (

//                     'formhash' => FORMHASH,

//                     'ucsynlogout' => $ucsynlogout,

//                     'referer' => rawurlencode ( dreferer () ) 

//             ) );

        }

    }

}

 

当然,最后把登录改成 到登录界面去登录的方式,这样才会生效,这其实是最简单的方法了。

如下图进行设置

 

 

CAS 结构 如下:

 

 

 

其中CAS 包我也做了小小的修改,但这个与主要业务无关,就不传了。

 

最后,我的版本是 Discuz! X3.1 Release 20131011 。

 

从 其它系统跳转到要检测是否已经登录,可以作用JS的方法判断CAS Server是否已经登录,如果已经登录,跳转到登录然后再返回

或使得JS方式从后台调用 CAS的方法进行登录,然后使用Ajax的方式,更新界面。

 

我的CASServer C# 版本 是自己的写的,但我基本上遵循的 CAS 2.0 的协议,所以对于Java版本CAS也差不多。相应代码可参见的GitHub上的代码。

 

 

**************************************************** 2014-8-27补充**********************************************************

其实还有一个问题没有说清楚的,

这个CAS Server的模式如下:

这个CAS Server 完全兼容了Discuz的UcCenter,也就是在支持标准CAS 协议的同时,也支持康盛的Uc接口,Discuz完全不再依赖于UC了。

 

其实在 DZ接入CasServer的时候,首先要关掉UC的同步登录功能。

接下来,由于DZ依赖于UC,要么改造一下CASServer适配为Uccenter,要么,改一下UcCenter来适应CASServer。

 

我上面的提到的代码中,应该算是一个思路,具体的实现,还是要根据实际情况进行修正。

Discuz 3.X 整合 CAS 的方法的更多相关文章

  1. 应用整合CAS服务器方法

    概要 在开发WEB程序时需要整合CAS实现单点登录,下面介绍一下应用整合CAS服务器的过程. 在开始之前,我们确定CAS服务器已经搭建完毕. 实现步骤 1.新建一个maven项目,引入casclien ...

  2. dedecmsV5.7和discuz!X3.4整合之后免激活登陆

    问题:dedecmsv5.7和discuz!X3.4整合之后,从dede过去的用户,第一次登陆discuz!X3.4,需要激活.后来我就上百度了一番,找到了一个方法 我找到的方法: 1.在dedecm ...

  3. Spring Security(20)——整合Cas

    整合Cas 目录 1.1           配置登录认证 1.1.1     配置AuthenticationEntryPoint 1.1.2     配置CasAuthenticationFilt ...

  4. Spring Security 3整合CAS 实现SSO

    spring security 3整合cas client用于实现各Application之间的单点登录. 1. 需要准备的jar spring-security-core-3.0.8.RELEASE ...

  5. discuz!X2头像无法显示解决方法

    discuz x2刚刚发布,很多站长就迫不及待地将自己的论坛升级. 可是安装完discuz X2之后,就马上发现论坛会的头像都不见了,取而代之的是一个小红叉.会员也没有办法设置自己的头像. 各位站长们 ...

  6. Spring整合Struts2的方法

    一.基本支持 通常我们整合Spring和struts2的目的是让Spring来管理struts2的控制器.也就是说把Action交由Spring来管理,利用IOC的特性把Action注入到业务逻辑中. ...

  7. Spring整合Hibernate的方法

    一.基本支持 Spring 支持大多数流行的 ORM 框架, 包括 Hibernate JDO, TopLink, Ibatis 和 JPA. Spring 对这些 ORM 框架的支持是一致的, 因此 ...

  8. CAS5.3服务器搭建及SpringBoot整合CAS实现单点登录

    1.1 什么是单点登录 单点登录(Single Sign On),简称为 SSO,是目前比较流行的企业业务整合的解决方案之一.SSO的定义是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的 ...

  9. Discuz封锁蜘蛛最有效的方法

    闲来无事翻代码,发现一个好东西,Discuz设计者考虑到了有些流氓搜索引擎不遵守roborts.txt,于是设计了一个NOROBOT变量,当这个变量为true 的时候,定义中的搜索引擎都会无法访问,默 ...

随机推荐

  1. 一、XML语法

    xml声明xml指令:<? ?>xml编码与乱码xml元素(标签)CDATA区空格与换行会被认为是标签的内容xml-stylesheet指令解析xml内容 <?xml version ...

  2. [IE兼容性] Table 之边框 (IE6 IE7 IE8(Q) 中 cellspacing 属性在重合的边框模型的表格中仍然有效)

    在 IE6 IE7 IE8(Q) 中,在通过 border-collapse:collapse 使用表格的重合边框模型后,其 cellspacing 属性仍然有效: 在 其他浏览器 中,此时的 cel ...

  3. linux命令:cat

    1:命令介绍: cat用来打印标准输入或连接文件.tac是其相反命令,从最后一行开始打印. 2:命令格式: cat [选项] 文件 3:命令参数: -A, --show-all           等 ...

  4. 【LeetCode OJ】Evaluate Reverse Polish Notation

    Problem link: http://oj.leetcode.com/problems/evaluate-reverse-polish-notation/ According to the wik ...

  5. XMPP即时通讯

    XMPP:XMPP是基于XML的点对点通讯协议,The Extensible Messaging and Presence Protocol(可扩展通讯和表示协议). XMPP可用于服务类实时通讯,表 ...

  6. OC多线程管理

    在OC中多线程管理包含GCD.NSThread.NSOperationQueue. 下面简单介绍. 进程和线程 进程:正在进行中的程序叫做进程,负责程序运行的内存分配. 每一个进程都有自己独立的虚拟内 ...

  7. HDU 5047

    http://acm.hdu.edu.cn/showproblem.php?pid=5047 直到看到题解,我才知道这道题考的是什么 首先交点数是Σ(16*i),区域区分的公式是 边数+点数+1=分成 ...

  8. EXT遮罩效果

    <link href="/resources/ext/resources/css/ext-all.css" rel="stylesheet" type=& ...

  9. 九、CCAction

    之前介绍CCNode的时候说过,动作是指在特定时间内完成移动.缩放.旋转等操作的行为,节点可以通过运行动作来实现动画效果,这里的动作就是指CCAction对象,它有很多的子类,每个子类都封装了不同的动 ...

  10. Find Minimum in Rotated Sorted Array II

    Follow up for "Find Minimum in Rotated Sorted Array":What if duplicates are allowed? Would ...