ekalokman/yii2-cas-uni

基于 silecs/yii2-auth-cas 的 Yii2 CAS 认证

安装次数: 45

依赖关系: 0

建议者: 0

安全: 0

星标: 0

关注者: 1

分支: 0

公开问题: 0

类型:yii2-extension

dev-main 2024-08-12 04:08 UTC

This package is auto-updated.

Last update: 2024-09-12 04:16:48 UTC


README

使用 phpCAS 库进行 CAS 认证的 Yii2 库。

用法

  1. 使用 composer require ekalokman/yii2-auth-uni 将其添加到项目中

  2. 配置 Yii2 应用程序,例如在 backend/config/main.php

    return [
        ...
        'modules' => [
            'cas' => [
                'class' => 'silecs\yii2auth\cas\CasModule',
                'config' => [
                    'host' => 'ssoserver.example.com', //insert your own host
                    'port' => '443', //insert your own port
                    'path' => '/cas',
                    'returnUrl' => '', //insert your own return url
                    // optional parameters
                    'certfile' => '', // empty, or path to a SSL cert, or false to ignore certs
                    'debug' => true, // will add many logs into X/runtime/logs/cas.log
                ],
            ],
    
  3. SiteController 中添加使用此 CAS 模块的动作

    public function actionLogin()
    {
        if (!Yii::$app->user->isGuest) {
            return $this->goHome();
        }
        return $this->redirect(['/cas/auth/login']);
    }
    
    public function actionLogout()
    {
        if (Yii::$app->user->isGuest) {
            return $this->redirect(['/cas/auth/logout']);
        }
        return $this->goHome();
    }
    
  4. common/models/LoginCas.php 中添加使用 casAuthenticate 检查用户是否为学生或员工并注册新用户的动作

    <?php
    namespace common\models;
    
    use Yii;
    use yii\base\Model;
    use phpCAS;
    use yii\helpers\Url;
    use common\models\User;
    use common\models\Student;
    use backend\models\StudentSt;
    
    /**
    * Login form
    */
    class LoginCas extends Model
    {
        private $_user;
    
        /**
        * @inheritdoc
        */
        public function rules()
        {
            return [
            ];
        }
    
        /**
        * Logs in a user using the provided username and password.
        *
        * @return boolean whether the user is logged in successfully
        */
        public function login()
        {
            $user = $this->casAuthenticate();
        
            if ($user) {
                $user = $this->getUser($user);
                return Yii::$app->user->login($user, false ? 3600 * 24 * 30 : 0);
            } else {
                return false;
            }
        }
    
        /**
        * Finds user by [[username]]
        *
        * @return User|null
        */
        protected function getUser($user)
        {
            if ($this->_user === null) {
                $this->_user = UserCas::findByUsername($user);
            }
    
            return $this->_user;
        }
    
        public static function casAuthenticate($username)
        {
    
            //may change checking below if want to check staff only
            $cStudentSt=new StudentSt(); //for checking username whether student or staff
            $StuData=$cStudentSt->getDataSt($username);
    
            $baseUrl = Url::base(true);
            $baseUrl = Url::base();
    
            //for student screen
            if ($baseUrl == '/stu'){
            
                if($StuData){ // for student checking username is student: true and not null
    
                    $userCas = Student::findByUsername($username);
    
                    if (empty($userCas)) {
    
                            $con = \Yii::$app->db;
                            $attributes = [
                                'username' => $username,
                                'auth_key' => Yii::$app->security->generateRandomString(),
                                'status' => '10',
                                'created_at' => time(),
                                'updated_at' => time()
                            ];
                            $con->createCommand()->insert('quest.qst_student', $attributes)->execute();
                        // $user = $this->getUser();
    
                    }
    
                }else{ //student is false
    
                    Yii::$app->user->logout();
                    unset($_COOKIE);
    
                    Yii::$app->user->logout();
    
                    header("cache-Control: no-store, no-cache, must-revalidate");
                    header("cache-Control: post-check=0, pre-check=0", false);
                    header("Pragma: no-cache");
                    header("Expires: Sat, 26 Jul 1997 05:00:00 GMT");
                
                    echo "<script>alert('Unauthorized access! This application only allow for IIUM student. \\nKindly contact the Administrator if any issue.');
                                window.location = 'https://cas.iium.edu.my:8448/cas/logout';
                    </script>";
                    exit;
    
                }
    
            //for staff screen
            }else{ 
    
                if(empty($StuData)){ //for staff checking username is student: false and null
    
                    $userCas = User::findByUsername($username); //checking staff is a
    
                    if ($userCas === null || $userCas->username === null) {
    
                        $con = \Yii::$app->db;
                        $attributes = [
                            'username' => $username,
                            'auth_key' => Yii::$app->security->generateRandomString(),
                            'status' => '10',
                            'created_at' => time(),
                            'updated_at' => time()
                        ];
                        $con->createCommand()->insert('table.user', $attributes)->execute(); //insert to your own table
    
                    }
    
                }else{//student is true and not staff
    
                    Yii::$app->user->logout();
    
                    unset($_COOKIE);
    
                    Yii::$app->user->logout();
    
                    header("cache-Control: no-store, no-cache, must-revalidate");
                    header("cache-Control: post-check=0, pre-check=0", false);
                    header("Pragma: no-cache");
                    header("Expires: Sat, 26 Jul 1997 05:00:00 GMT");
                
                    echo "<script>alert('Unauthorized access! This application only allow for IIUM staff. \\nKindly contact the Administrator if any issue.');
                                window.location = 'https://cas.iium.edu.my:8448/cas/logout';
                    </script>";
                    exit;
    
                }
    
            }
        }
    
    }
    
    

注意

实现 yii\web\IdentityInterfaceuser 组件将在查询 CAS 服务器后用于获取本地配置文件。这意味着如果 User 是应用程序组件且 CAS 返回的用户名为 "bibendum",则只有当 User::findIdentity("bibendum") 的结果不为空时,认证才会成功。

动作路径 '/cas/auth/login' 以应用程序配置中定义的模块别名为起始,例如 'cas''modules' => [ 'cas' => [ ... ] ]

使用 CAS 容器进行测试

以下是部署 Docker CAS 服务器以测试此库的说明。此过程将使用 Shibboleth 实例的 CAS 接口。已在 Debian Stretch 和 Buster(测试版)上进行了测试。

  1. 从 docker.io 的额外存储库安装 docker(我使用官方 Debian 存储库中的旧版 docker 时遇到了错误)。

  2. 从 Debian 或 docker.io 安装 docker-compose

  3. https://hub.docker.com/r/unicon/shibboleth-idp/ 克隆 Git。如果使用旧版本的 docker-compose,请检查 3c29f10,因为后来的提交需要更新的功能。

  4. 修改 docker-compose.yml,以便容器不会尝试使用端口 80,因此将 "80:80" 替换为 "8080:80"

  5. 如果您的本地 Yii2 应用程序不使用 HTTPS,请修改 idp/shibboleth-idp/conf/cas-protocol.xml,将 c:regex="https://idptestbed/.*" 替换为 c:regex="https?://idptestbed/.*"

  6. 127.0.0.1 idptestbed 添加到 /etc/hosts 中,作为 root。

  7. 配置您的 Yii2 应用程序以使用

     'host' => 'idptestbed',
     'port' => '443',
     'path' => '/idp/profile/cas',
     'certfile' => false,
     'debug' => true,
    
  8. 启动容器

     docker-compose build
     docker-compose run
    
  9. 访问您的 Yii2 应用的登录页面。

  10. 在容器终端中按 Ctrl-C 结束它们。

如果您想向 CAS 添加用户,可以修改 ldap/users.ldif。不要忘记在此之后重建 Docker 镜像。