使用php处理cas认证

最近项目要嵌入到平台上做一个应用,数据对接用ms-security(见上篇博客),登录则使用cas认证,今天就把完整代码放进来,也是走了好些个弯路的。


代码的主要逻辑就是,当用户访问应用时,应用检测是否已登录,未登录则带上本地url跳转到cas登录中心,用户输入用户名、密码后,正确的话便带上ticket跳转到一开始带上的url(通常是该应用的登录接口),检测到ticket后便使用file_get_contents方法读取cas认证的页面,之后获取到想要的用户名,使用该用户名去该应用的用户表查找记录session并登录。


// cas服务器登录地址
$loginServer = "http://cas/sso/login";

// cas服务器验证地址
$validateServer = "http://cas/sso/serviceValidate";

// cas服务器回调地址
$address = "http://app/exam/";

// 若有回调地址,便在url里追加上
if (isset($_REQUEST["redirectUrl"]) && !empty($_REQUEST["redirectUrl"])) {
    $address .= "?redirectUrl=" . $_REQUEST["redirectUrl"];
}

// 如果请求带有ticket
if (isset($_REQUEST["ticket"]) && !empty($_REQUEST["ticket"])) {
    try {

        // url里带上ticket去cas服务验证地址
        $validateurl = $validateServer . "?ticket=" . $_REQUEST["ticket"] . "&service=" . $address;
        header("Content-Type:text/html;charset=utf-8");

        // 后去验证后的内容
        $validateResult = str_replace('cas:', '', file_get_contents($validateurl));
        $validateXML = simplexml_load_string($validateResult);
        $successnode = $validateXML->authenticationSuccess[0];

        // 验证成功
        if (!empty($successnode)) {

            // 获取用户名,并在该系统内查询用户相关的信息
            $account = (string)$successnode->user;
            $auth = M('Auth')->where(array('a_account' => $account))->field('a_id, s_id, a_account')->find();

            // 保存session
            setPassportId($auth['a_id']);

            //  保存登录信息
            $info['a_id'] = $auth['a_id'];
            $info['a_last_login_time'] = time();
            $info['a_last_login_ip'] = ip2long(get_client_ip());
            $info['a_login_count'] = array('exp', 'a_login_count+1');
            M('Auth')->save($info);

            // 加入登陆统计表
            $map = array();
            $map['l_year'] = date('Y', time());
            $map['l_month'] = date('m', time());
            $map['a_id'] = $auth['a_id'];
            $map['s_id'] = $auth['s_id'];
            $l_id = M('Login')->where($map)->getField('l_id');

            if ($l_id) {
                $map['l_count'] = array('exp', 'l_count+1');
                M('Login')->where(array('l_id' => $l_id))->save($map);
            } else {
                $map['l_count'] = 1;
                M('Login')->add($map);
            }

            redirect(__APP__ . '/Index');

            // 若验证失败,如ticket过期、不合法的service,则重新认证
        } else {
            header("Location: " . $loginServer . "?service=" . $address);
            exit;
        }
    } catch (Exception $e) {
        echo "出错了";
        echo $e->getMessage();
    }

    // 否则就去cas登录地址
} else {
    header("Location: " . $loginServer . "?service=" . $address);
    exit;
}


这里遇到的一个问题是认证返回的cas相关的xml是带有命名空间的,一开始(代码中没有使用str_replace)怎么都解析不了,后来到论坛问了下,之后自己又找了下xml的相关信息,最后用str_replace去掉了命名空间(namespace)之后解析正常,于是去论坛看看有朋友解答么,打开问题后,发现两位坛主说了下看法,其中唠叨大大不愧是经验丰富的,正确给出了答案,但是最下面的那个在我机子上没有解析出来

$str = <<<EOT
<cas:serviceResponse xmlns:cas='http://www.yale.edu/tp/cas'>
    <cas:authenticationSuccess>
        <cas:user>zhangjian</cas:user>
        <cas:language></cas:language>
    </cas:authenticationSuccess>
</cas:serviceResponse>
EOT;
  
  
 
$validateXML = simplexml_load_string($str, null, 0, 'cas', true);
print_r($validateXML);
 
$successnode = $validateXML->authenticationSuccess[0];
print_r($successnode);
 
// 此方法还是没有解析出来
$xml = new DOMDocument();
$xml -> loadXML($str);
print_r($xml);



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值