【问题标题】:Extending IonAuth model, language files from the third party folder - Codeigniter4扩展 IonAuth 模型,第三方文件夹中的语言文件 - Codeigniter4
【发布时间】:2022-01-16 06:10:42
【问题描述】:

IonAuth 正在 Codeigniter4 上的第三方文件夹中运行。我已经扩展了控制器,因为我在我的 app/Controllers 目录中运行了 Auth.php 并且它正在工作。

如何扩展 IonAuth 库、模型和语言文件等?与 Auth.php 控制器不同,这些文件会被忽略。我不想编辑第三方文件夹中的文件,以便更容易升级等。谢谢。

【问题讨论】:

    标签: php authentication codeigniter-4 ion-auth


    【解决方案1】:

    看看我的代码像我一样做 按照我的方法 ctl认证

    <?php namespace Modules\Auth\Controllers;
    
    
    use Modules\Auth\Config\ModuleAuthConfig;
    use Modules\Auth\Config\Services;
    use Modules\Auth\Entities\AuthEntity;
    use Modules\Auth\Enums\RoleType;
    use Modules\Auth\Interfaces\AuthControllerInterface;
    use Modules\Shared\Config\ModuleSharedConfig;
    use Modules\Shared\Controllers\BaseController;
    use Modules\Shared\Enums\NotificationType;
    
    use CodeIgniter\HTTP\ResponseInterface;
    use Myth\Auth\AuthTrait;
    use Pusher\Pusher;
    use ReCaptcha\ReCaptcha;
    
    class Auth extends BaseController implements AuthControllerInterface
    {
        use AuthTrait;
    
    
        public function signInJwt(): ResponseInterface
        {
    
    
            /**
             * Attempts to verify the user's credentials
             * through a POST request.
             */
            $rules = [
                'login' => 'required',
                'password' => 'required'
    
            ];
    
            $config = config('Myth\Auth\Config\Auth');
    
            if ($config->validFields == ['email']) {
                $rules['login'] .= '|valid_email';
            };
    
    
            if (!$this->validate($rules)) {
    
    
                return $this->response->setJSON(['error' => $this->validator->getErrors()])
                    ->setStatusCode(ResponseInterface::HTTP_NOT_ACCEPTABLE, lang('Authenticate.auth.validation'))
                    ->setContentType('application/json');
            }
    
            $authEntity = new AuthEntity((array)$this->request->getVar());
    
            $authEntity->logInMode()->loginDate()->ipAddress($this->request->getIPAddress());
    
    
            $authService = Services::authService();
            $data = $authService->signInJwt($authEntity);
            $authConfig = new  ModuleAuthConfig();
    
            return $this->response->setHeader($authConfig->jwt['name'], $data['jwt']['token'])
                ->setCookie($authConfig->jwt['name'], $data['jwt']['token'], $data['jwt']['expire'])->
                setJSON($data)->setStatusCode(ResponseInterface::HTTP_OK, lang('Authenticate.auth.logIn'))
                ->setContentType('application/json');
    
    
        }
    
        public function signIn(): ResponseInterface
        {
    
    
            $this->setupAuthClasses();
    
    
            /**
             * Attempts to verify the user's credentials
             * through a POST request.
             */
            $rules = [
                'login' => 'required',
                'password' => 'required'
    
            ];
    
            $config = config('Myth\Auth\Config\Auth');
    
            if ($config->validFields == ['email']) {
                $rules['login'] .= '|valid_email';
            };
    
    
            if (!$this->validate($rules)) {
    
    
                return $this->response->setJSON(['error' => $this->validator->getErrors()])
                    ->setStatusCode(ResponseInterface::HTTP_NOT_ACCEPTABLE, lang('Authenticate.auth.validation'))
                    ->setContentType('application/json');
            }
    
    
            $authEntity = new AuthEntity((array)$this->request->getVar());
            $authEntity->logInMode();
    
    
            $remember = $authEntity->remember ?? false;
    
            if (!$this->authenticate->attempt([$authEntity->loginType => $authEntity->login, 'password' => $authEntity->password], $remember)) {
    
    
                return $this->response->setJSON(['error' => $this->authenticate->error(),
                ])
                    ->setStatusCode(ResponseInterface::HTTP_UNAUTHORIZED, lang('Auth.badAttempt'))
                    ->setContentType('application/json');
    
            }
    
            // Is the user being forced to reset their password?
            if ($this->authenticate->user()->force_pass_reset === true) {
    
                //  return redirect()->to(route_to('reset-password') . '?token=' . $this->auth->user()->reset_hash)->withCookies();
                return $this->response->setJSON(['token' => $this->authenticate->user()->reset_hash])
                    ->setStatusCode(ResponseInterface::HTTP_UNAUTHORIZED, lang('Authenticate.auth.foreResetPassword'))
                    ->setContentType('application/json');
    
            }
    
            $authService = Services::authService();
            $data = $authService->signIn($authEntity);
    
    
            return $this->response->setJSON(
                $data
            )->setStatusCode(ResponseInterface::HTTP_OK, lang('Authenticate.auth.logIn'))
                ->setContentType('application/json');
    
    
        }
    
    
        /**
         * Log the user out.
         */
        public function signOut(): ResponseInterface
        {
    
            $this->setupAuthClasses();
            $authConfig = new  ModuleAuthConfig();
    
            $jwtHeader = $this->request->getServer('HTTP_AUTHORIZATION');
            $jwtCookie = $this->request->getCookie($authConfig->jwt['name']);
    
    
            if ($this->authenticate->check()) {
                $this->authenticate->logout();
            } else if (!is_null($jwtHeader) || !is_null($jwtCookie)) {
    
    
                $authService = Services::authService();
    
                $requestWithUser = Services::requestWithUser();
                $authService->signOutJwt($requestWithUser->getUser());
    
                $this->response->setHeader($authConfig->jwt['name'], '');
                $this->response->setCookie($authConfig->jwt['name'], '', 0);
    
            }
    
            return $this->response->setJSON(['success' => true])
                ->setStatusCode(ResponseInterface::HTTP_OK, lang('Authenticate.auth.logOut'))
                ->setContentType('application/json');
    
    
        }
    
        /**
         * Log the user out.
         */
        public function isSignIn(): ResponseInterface
        {
    
            $this->setupAuthClasses();
            $requestWithUser = Services::requestWithUser();
    
            if ($this->authenticate->check() || isset($requestWithUser->getUser()->id)) {
    
                return $this->response->setJSON(['success' => true])
                    ->setStatusCode(ResponseInterface::HTTP_OK, lang('check is sign in'))
                    ->setContentType('application/json');
            } else {
                return $this->response->setJSON(['success' => false,
                ])
                    ->setStatusCode(ResponseInterface::HTTP_OK, lang('check is sign in'))
                    ->setContentType('application/json');
            }
    
    
        }
    
    
        //--------------------------------------------------------------------
        // Register
        //--------------------------------------------------------------------
    
        /**
         * Displays the user registration page.
         */
        public function signUp(): ResponseInterface
        {
    
    
            $throttler = \Codeigniter\Config\Services::throttler();
    
            if ($throttler->check($this->request->getIPAddress(), 5, MINUTE) === false) {
    
                return $this->response->setJSON(['data' => $throttler->getTokentime()])
                    ->setStatusCode(ResponseInterface::HTTP_TOO_MANY_REQUESTS, lang('Auth.tooManyRequests', [$throttler->getTokentime()]))
                    ->setContentType('application/json');
    
            }
    
            // Validate here first, since some things,
            // like the password, can only be validated properly here.
            // strong password didint work custom validation  strong_password
            // password=> strong_password
            helper('authentication');
    
            if (loginVia($this->request->getVar('login') ?? $this->request->getVar('login')) == 'email') {
    
                $lineRule = 'required|valid_email|is_unique[users.email]';
            } else if (loginVia($this->request->getVar('login') ?? $this->request->getVar('login')) == 'phone') {
    
                $lineRule = 'required|min_length[9]|is_unique[users.phone]';
            } else {
    
                return $this->response->setJSON(['error' => lang('Authenticate.auth.emailOrPhone')])
                    ->setStatusCode(ResponseInterface::HTTP_NOT_ACCEPTABLE, lang('Authenticate.auth.validation'))
                    ->setContentType('application/json');
            }
    
            $rules = [
                'username' => 'required|alpha_numeric_space|min_length[3]|is_unique[users.username]',
                'login' => $lineRule,
                'password' => 'required|min_length[6]',
                'passConfirm' => 'required|matches[password]',
                'action' => 'required',
                'token' => 'required',
                'socialLogin' => 'required'
    
            ];
    
            if (!$this->validate($rules)) {
    
                return $this->response->setJSON([
    
                    'error' => service('validation')->getErrors(),
                ])
                    ->setStatusCode(ResponseInterface::HTTP_NOT_ACCEPTABLE, lang('Authenticate.auth.validation'))
                    ->setContentType('application/json');
    
            }
    
    
            $authConfig = new  \Modules\Auth\Config\ModuleAuthConfig();
            // ->setExpectedHostname($_SERVER['SERVER_NAME'])
            $recaptcha = new ReCaptcha($authConfig->captcha['secretKey']);
            $resp = $recaptcha->setExpectedAction($this->request->getVar('action'))
                ->setScoreThreshold(0.2)
                ->verify($this->request->getVar('token'), $_SERVER['REMOTE_ADDR']);
            // verify the response
            if (!$resp->isSuccess() && !$this->request->getVar('socialLogin')) {
                // spam submission
                // show error message
                return $this->response->setJSON([
                    'error' => $resp->getErrorCodes()])
                    ->setStatusCode(ResponseInterface:: HTTP_UNAUTHORIZED, lang('Authenticate.auth.captchaError'))
                    ->setContentType('application/json');
            }
            $authEntity = new AuthEntity((array)$this->request->getVar());
            $authEntity->logInMode()->createdAt()->setRole(RoleType::Member);
            unset($authEntity->token);
            unset($authEntity->action);
            $authService = Services::authService();
            $authService->signUp($authEntity);
    
    
            $sharedConfig = new ModuleSharedConfig();
    
            $pusher = new Pusher(
                $sharedConfig->pusher['authKey'],
                $sharedConfig->pusher['secret'],
                $sharedConfig->pusher['appId'],
                ['cluster' => $sharedConfig->pusher['cluster'],
                    'useTLS' => $sharedConfig->pusher['useTLS']]
            );
            $data['type'] = NotificationType::NewUser;
            $data['message'] = 'new user register';
            $data['counter'] = 1;
            $data['date'] = date('Y-m-d H:i:s', time());;
            $pusher->trigger('notification-channel', 'my-event', $data);
    
    
            return $this->response->setJSON(['success' => true])
                ->setStatusCode(ResponseInterface::HTTP_OK, lang('Auth.registerSuccess'))
                ->setContentType('application/json');
    
    
        }
    
    //--------------------------------------------------------------------
    // Forgot Password
    //--------------------------------------------------------------------
    
        /**
         * Displays the forgot password form.
         */
        public
        function forgot(): ResponseInterface
        {
    
    
            $rules = [
    
                'login' => 'required',
                'action' => 'required',
                'token' => 'required',
    
            ];
    
            if (!$this->validate($rules)) {
    
    
                return $this->response->setJSON(['error' => service('validation')->getErrors()])
                    ->setStatusCode(ResponseInterface::HTTP_NOT_ACCEPTABLE, lang('Authenticate.auth.validation'))
                    ->setContentType('application/json');
    
            }
    
            $authConfig = new  \Modules\Auth\Config\ModuleAuthConfig();
            // ->setExpectedHostname($_SERVER['SERVER_NAME'])
            $recaptcha = new ReCaptcha($authConfig->captcha['secretKey']);
    
            $resp = $recaptcha->setExpectedAction($this->request->getVar('action'))
                ->setScoreThreshold(0.2)
                ->verify($this->request->getVar('token'), $_SERVER['REMOTE_ADDR']);
            // verify the response
            if (!$resp->isSuccess()) {
                // spam submission
                // show error message
                return $this->response->setJSON([
                    'error' => $resp->getErrorCodes()])
                    ->setStatusCode(ResponseInterface:: HTTP_UNAUTHORIZED, lang('Authenticate.auth.captchaError'))
                    ->setContentType('application/json');
            }
    
    
            $authEntity = new AuthEntity((array)$this->request->getVar());
            $authEntity->logInMode(false)->generateResetHash();
            unset($authEntity->token);
            unset($authEntity->action);
            $authService = Services::authService();
            $authService->forgot($authEntity);
    
    
            return $this->response->setJSON(['success' => true])
                ->setStatusCode(ResponseInterface::HTTP_OK, lang('Authenticate.auth.forgotEmailSmsSent'))
                ->setContentType('application/json');
    
        }
    
        /**
         * Displays the Reset Password form.
         */
        /**
         * Verifies the code with the email and saves the new password,
         * if they all pass validation.
         *
         * @return mixed
         */
    
        public
        function resetPasswordViaSms(): ResponseInterface
        {
    
    
            $rules = [
                'code' => 'required',
                'phone' => 'required',
                'password' => 'required',
                'passConfirm' => 'required|matches[password]',
            ];
    
            if (!$this->validate($rules)) {
    
                return $this->response->setJSON(['error' => $this->validator->getErrors(),])
                    ->setStatusCode(ResponseInterface::HTTP_NOT_ACCEPTABLE, lang('Authenticate.auth.validation'))
                    ->setContentType('application/json');
    
            }
    
            $authEntity = new AuthEntity((array)$this->request->getVar());
            $authEntity->resetPassword();
            $authService = Services::authService();
            $authService->resetPasswordViaSms($authEntity);
    
    
            return $this->response->setJSON(['success' => true])->setStatusCode(ResponseInterface::HTTP_OK, lang('Auth.resetSuccess'))
                ->setContentType('application/json');
    
    
        }
    
        /**
         * Verifies the code with the email and saves the new password,
         * if they all pass validation.
         *
         * @return mixed
         */
    
        public
        function resetPasswordViaEmail(): ResponseInterface
        {
    
    
            $rules = [
                'token' => 'required',
                'email' => 'required|valid_email',
                'password' => 'required',
                'passConfirm' => 'required|matches[password]',
            ];
    
    
            if (!$this->validate($rules)) {
    
                return $this->response->setJSON(['error' => $this->validator->getErrors()])
                    ->setStatusCode(ResponseInterface::HTTP_NOT_ACCEPTABLE, lang('Authenticate.auth.validation'))
                    ->setContentType('application/json');
            }
    
            $authEntity = new AuthEntity((array)$this->request->getVar());
            $authEntity->resetPassword()
                ->userAgent($this->request->getUserAgent())
                ->ipAddress($this->request->getIPAddress());
            $authService = Services::authService();
            $authService->resetPasswordViaEmail($authEntity);
    
            return $this->response->setJSON(['success' => true])->setStatusCode(ResponseInterface::HTTP_OK, lang('Auth.resetSuccess'))
                ->setContentType('application/json');
    
    
        }
    
        /**
         * Activate account.
         *
         * @return mixed
         */
        public
        function activateAccountViaEmail(): ResponseInterface
        {
            $rules = [
                'token' => 'required',
                'email' => 'required|valid_email',
            ];
            if (!$this->validate($rules)) {
    
                return $this->response->setJSON([
    
                    'error' => $this->validator->getErrors()])
                    ->setStatusCode(ResponseInterface::HTTP_NOT_ACCEPTABLE, lang('Authenticate.auth.validation'))
                    ->setContentType('application/json');
            }
    
    
            $authEntity = new AuthEntity((array)$this->request->getVar());
            $authEntity->activate()
                ->userAgent($this->request->getUserAgent())
                ->ipAddress($this->request->getIPAddress());
    
    
            $authService = Services::authService();
            $authService->activateAccountViaEmail($authEntity);
    
            return $this->response->setJSON(['success' => true])
                ->setStatusCode(ResponseInterface::HTTP_OK, lang('Auth.registerSuccess'))
                ->setContentType('application/json');
    
    
        }
    
        /**
         * Resend activation account.
         *
         * @return mixed
         * @throws \Exception
         */
        public
        function sendActivateCodeViaEmail(): ResponseInterface
        {
    
    
            $rules = [
                'email' => 'required',
            ];
    
            if (!$this->validate($rules)) {
                return $this->response->setJSON(['error' => service('validation')->getErrors()
                ])
                    ->setStatusCode(ResponseInterface::HTTP_NOT_ACCEPTABLE, lang('Authenticate.auth.validation'))
                    ->setContentType('application/json');
            }
    
    
            $authEntity = new AuthEntity((array)$this->request->getVar());
            $authEntity->generateActivateHash();
            $authService = Services::authService();
            $authService->sendActivateCodeViaEmail($authEntity);
    
            return $this->response->setJSON(['success' => true])
                ->setStatusCode(ResponseInterface::HTTP_OK, lang('Auth.activationSuccess'))
                ->setContentType('application/json');
    
        }
    
        /**
         * Activate account via sma.
         *
         * @return mixed
         */
        public
        function activateAccountViaSms(): ResponseInterface
        {
    
            $rules = [
                'phone' => 'required',
                'code' => 'required',
            ];
    
            if (!$this->validate($rules)) {
                return $this->response->setJSON(['error' => service('validation')->getErrors()])
                    ->setStatusCode(ResponseInterface::HTTP_NOT_ACCEPTABLE, lang('Authenticate.auth.validation'))
                    ->setContentType('application/json');
            }
    
    
            $authEntity = new AuthEntity((array)$this->request->getVar());
            $authEntity->activate();
            $authService = Services::authService();
            $authService->activateAccountViaSms($authEntity);
    
    
            return $this->response->setJSON(['success' => true])
                ->setStatusCode(ResponseInterface::HTTP_OK, lang('Authenticate.auth.registerSuccess'))
                ->setContentType('application/json');
    
        }
    
        /**
         * Activate account via sma.
         *
         * @return mixed
         */
        public
        function sendActivateCodeViaSms(): ResponseInterface
        {
    
            $rules = [
                'phone' => 'required',
            ];
    
            if (!$this->validate($rules)) {
                return $this->response->setJSON(['error' => service('validation')->getErrors()])
                    ->setStatusCode(ResponseInterface::HTTP_NOT_ACCEPTABLE, lang('Authenticate.auth.validation'))
                    ->setContentType('application/json');
            }
    
            $authEntity = new AuthEntity((array)$this->request->getVar());
            $authService = Services::authService();
            $authService->sendActivateCodeViaSms($authEntity);
    
    
            return $this->response->setJSON(['success' => true,
            ])
                ->setStatusCode(ResponseInterface::HTTP_OK, lang('Authenticate.auth.smsActivation'))
                ->setContentType('application/json');
    
    
        }
    
    
    }
    
    

    实体授权

    <?php namespace Modules\Auth\Entities;
    
    use \CodeIgniter\Entity;
    use CodeIgniter\I18n\Time;
    use Myth\Auth\Authorization\GroupModel;
    use Myth\Auth\Authorization\PermissionModel;
    use Myth\Auth\Entities\User;
    use Myth\Auth\Password;
    
    class  AuthEntity extends Entity
    {
    
        protected $id;
        protected $phone;
        protected $username;
        protected $image;
        protected $email;
        protected $password;
        protected $login;
        protected $loginType;
        protected $remember;
        protected $IpAddress;
        protected $userAgent;
        protected $role;
        protected $code;
        protected $token;
        protected $action;
    
    
        protected $attributes = [
            'id' => null,
            'username' => null,
            'phone' => null,
            'email' => null,
            'active' => null,
            'created_at' => null,
            'login' => null,
            'loginType' => null,
            'password' => null,
            'ip_address' => null,
            'date' => null,
            'success' => null,
            'role' => null,
            'code' => null,
            'token' => null,
            'user_agent' => null,
            'remember' => null,
    
        ];
        protected $datamap = [
    
            'createdAt' => 'created_at',
            'ipAddress' => 'ip_address',
            'userAgent' => 'user_agent',
    
        ];
    
    
        /**
         * Define properties that are automatically converted to Time instances.
         */
        protected $dates = ['reset_at', 'reset_expires', 'created_at', 'updated_at', 'deleted_at'];
    
        /**
         * Array of field names and the type of value to cast them as
         * when they are accessed.
         */
        protected $casts = [
            'active' => 'boolean',
            'force_pass_reset' => 'boolean',
        ];
    
        /**
         * Per-user permissions cache
         * @var array
         */
        protected $permissions = [];
    
        /**
         * Per-user roles cache
         * @var array
         */
        protected $roles = [];
    
        /**
         * Automatically hashes the password when set.
         *
         * @see https://paragonie.com/blog/2015/04/secure-authentication-php-with-long-term-persistence
         *
         * @param string $password
         */
        public function setPassword(string $password)
        {
            $this->attributes['password'] = $password;
            $this->attributes['password_hash'] = Password::hash($password);
    
            /*
                Set these vars to null in case a reset password was asked.
                Scenario:
                    user (a *dumb* one with short memory) requests a
                    reset-token and then does nothing => asks the
                    administrator to reset his password.
                User would have a new password but still anyone with the
                reset-token would be able to change the password.
            */
            $this->attributes['reset_hash'] = null;
            $this->attributes['reset_at'] = null;
            $this->attributes['reset_expires'] = null;
        }
    
        /**
         * Force a user to reset their password on next page refresh
         * or login. Checked in the LocalAuthenticator's check() method.
         *
         * @return $this
         * @throws \Exception
         *
         */
        public function forcePasswordReset(): AuthEntity
        {
            $this->generateResetHash();
            $this->attributes['force_pass_reset'] = 1;
    
            return $this;
        }
    
        /**
         * Generates a secure hash to use for password reset purposes,
         * saves it to the instance.
         *
         * @return $this
         * @throws \Exception
         */
        public function generateResetHash(): AuthEntity
        {
            $this->attributes['reset_hash'] = bin2hex(random_bytes(16));
            $this->attributes['reset_expires'] = date('Y-m-d H:i:s', time() + config('Auth')->resetTime);
    
            return $this;
        }
    
        /**
         * Generates a secure random hash to use for account activation.
         *
         * @return $this
         * @throws \Exception
         */
        public function generateActivateHash(): AuthEntity
        {
            $this->attributes['activate_hash'] = bin2hex(random_bytes(16));
    
            return $this;
        }
    
        /**
         * Activate user.
         *
         * @return $this
         */
        public function activate(): AuthEntity
        {
            $this->attributes['active'] = 1;
            $this->attributes['activate_hash'] = null;
    
            return $this;
        }
    
        /**
         * Unactivate user.
         *
         * @return $this
         */
        public function deactivate(): AuthEntity
        {
            $this->attributes['active'] = 0;
    
            return $this;
        }
    
        /**
         * Checks to see if a user is active.
         *
         * @return bool
         */
        public function isActivated(): bool
        {
            return isset($this->attributes['active']) && $this->attributes['active'] == true;
        }
    
    
        public function logInMode($flag = true): AuthEntity
        {
    // Determine credential type
    
            if ($flag == false) {
    
                if (filter_var($this->attributes['login'], FILTER_VALIDATE_EMAIL)) {
                    $this->attributes['loginType'] = 'email';
    
                } else if (is_numeric($this->attributes['login'])) {
                    $this->attributes['loginType'] = 'phone';
    
                } else {
                    $this->attributes['loginType'] = 'username';
    
                }
    
            } else {
    
    
                if (filter_var($this->attributes['login'], FILTER_VALIDATE_EMAIL)) {
                    $this->attributes['loginType'] = 'email';
                    $this->attributes['email'] = $this->attributes['login'];
                } else if (is_numeric($this->attributes['login'])) {
                    $this->attributes['loginType'] = 'phone';
                    $this->attributes['phone'] = $this->attributes['login'];
    
                } else {
                    $this->attributes['loginType'] = 'username';
                    $this->attributes['username'] = $this->attributes['login'];
                }
            }
            return $this;
        }
    
        public function ipAddress(string $ip): AuthEntity
        {
            $this->attributes['ip_address'] = $ip;
            return $this;
        }
    
        public function loginDate(): AuthEntity
        {
            $this->attributes['date'] = date('Y-m-d H:i:s', time());;
            return $this;
        }
    
        public function loginSuccess(bool $flag): AuthEntity
        {
            $this->attributes['success'] = $flag;
            return $this;
        }
    
        public function createdAt(): AuthEntity
        {
            $this->attributes['created_at'] = date('Y-m-d H:i:s', time());;
            return $this;
        }
    
        public function setRole(string $role): AuthEntity
        {
            $this->attributes['role'] = $role;
            return $this;
        }
    
        public function resetPassword(): AuthEntity
        {
            $this->attributes['reset_hash'] = null;
            $this->attributes['reset_expires'] = null;
            $this->attributes['reset_at'] = date('Y-m-d H:i:s');
            $this->attributes['force_pass_reset'] = false;
    
    
            return $this;
        }
    
        public function userAgent(string $agent): AuthEntity
        {
            $this->attributes['user_agent'] = $agent;
            return $this;
        }
    }
    
    
    

    【讨论】:

      【解决方案2】:

      服务认证

      <?php namespace Modules\Auth\Services;
      
      
      use Codeigniter\Config\Services;
      use CodeIgniter\Session\SessionInterface;
      use Config\Email;
      use Modules\Auth\Config\ModuleAuthConfig;
      use Modules\Auth\Entities\AuthEntity;
      use Modules\Auth\Interfaces\AuthServiceInterface;
      use Modules\Auth\Models\GroupsPermissionModel;
      use Modules\Auth\Models\UsersPermissionModel;
      use Modules\Shared\Config\ModuleSharedConfig;
      use Modules\Shared\Libraries\MainService;
      use Modules\Shared\Libraries\Sms;
      use CodeIgniter\HTTP\ResponseInterface;
      use Modules\Auth\Libraries\CsrfSecurity;
      use Myth\Auth\Authorization\GroupModel;
      use Myth\Auth\Authorization\PermissionModel;
      use Myth\Auth\AuthTrait;
      
      
      use Myth\Auth\Models\LoginModel;
      use Myth\Auth\Models\UserModel;
      use Myth\Auth\Password;
      
      
      class AuthService extends MainService implements AuthServiceInterface
      {
          use AuthTrait;
      
          private CsrfSecurity $csrfSecurity;
          private GroupModel $groupModel;
          private PermissionModel $permissionModel;
          private ModuleAuthConfig $authConfig;
          private UserModel $userModel;
          private SessionInterface $session;
          private LoginModel $loginModel;
          private ModuleSharedConfig $sharedConfig;
          private Sms $sms;
          private GroupsPermissionModel $groupsPermissionModel;
          private UsersPermissionModel $usersPermissionModel;
      
          private \CodeIgniter\Email\Email $email;
      
      
          public function __construct()
          {
              $this->userModel = new UserModel();
              $this->authConfig = new  ModuleAuthConfig();
              $this->groupModel = new GroupModel();
              $this->csrfSecurity = new CsrfSecurity();
              $this->permissionModel = new PermissionModel();
              $this->loginModel = new LoginModel();
              $this->session = \Config\Services::session();
              $this->sharedConfig = new ModuleSharedConfig();
              $this->sms = new Sms($this->sharedConfig->sms['userName'],
                  $this->sharedConfig->sms['password'],
                  0);
              $this->groupsPermissionModel = new GroupsPermissionModel();
              $this->usersPermissionModel = new UsersPermissionModel();
      
              $this->email = Services::email();
              $emailConfig = new Email();
              $this->email->initialize($emailConfig)->
              setFrom($emailConfig->fromEmail, getenv('siteAddress'));
          }
      
          public function signInJwt(AuthEntity $entity): array
          {
              if (is_null($entity)) $this->httpException(lang('Shared.api.validation'), ResponseInterface::HTTP_CONFLICT);
      
      
              $findUser = $this->userModel->asObject()->where($entity->loginType, $entity->login)->first();
      
              if (!$findUser) {
                  $entity->loginSuccess(false);
                  $this->loginModel->save($entity);
                  $this->httpException(lang('Authenticate.auth.accountNotExist'), ResponseInterface::HTTP_CONFLICT);
              }
              if ($findUser->active == false) {
                  $entity->loginSuccess(false);
                  $this->loginModel->save($entity);
                  $this->httpException(lang('Authenticate.auth.accountNotActive'), ResponseInterface::HTTP_CONFLICT);
      
              }
              if ($findUser->status == true) {
                  $entity->loginSuccess(false);
                  $this->loginModel->save($entity);
                  $this->httpException(lang('Authenticate.auth.accountIsBand'), ResponseInterface::HTTP_CONFLICT);
      
              }
      
              if (!Password::verify($entity->password, $findUser->password_hash)) {
                  $entity->loginSuccess(false);
                  $this->loginModel->save($entity);
                  $this->httpException(lang('Authenticate.auth.accountNotExist'), ResponseInterface::HTTP_CONFLICT);
      
              }
      
              $entity->loginSuccess(true);
             $this->loginModel->save($entity);
      
              $role = $this->groupModel->asObject()->getGroupsForUser($findUser->id);
      
              $permissions = $this->permissionModel->asObject()->where('active', '1')->findAll();
              $permissionUser = $this->usersPermissionModel->permissionsOfUser($findUser->id);
              $permissionGroup = $this->groupsPermissionModel->permissionsOfGroup($role[0]['group_id']);
      
              helper('jwt');
      
              $timeJwt = isset($entity->remember) ? timeJwt(true) : timeJwt(false);
      
              $jwtToken = generateJWT($findUser->id, $timeJwt['init'], $timeJwt['expire'], $this->authConfig->jwt['secretKey']);
      
              $data = [
                  'success' => true,
                  'role' => [
                      'name' => $role[0]['name'],
                      'id' => $role[0]['group_id']
                  ],
                  'permissions' => $permissions,
                  'permissionUser' => $permissionUser,
                  'permissionGroup' => $permissionGroup,
                  'userInformation' => [
                      'id' => $findUser->id,
                      'userName' => $findUser->username,
                      'image' => $findUser->image,
                      'firstName' => $findUser->first_name,
                      'lastName' => $findUser->last_name,
                      'email' => $findUser->email,
                      'phone' => $findUser->phone,
                  ],
                  'csrf' => $this->csrfSecurity->init(),
                  'jwt' => [
                      "token" => $jwtToken,
                      "expire" => $timeJwt['expire'],
                  ],
      
              ];
      
              return $data;
      
      
          }
      
          public function signIn(AuthEntity $entity): array
          {
              if (is_null($entity)) $this->httpException(lang('Shared.api.validation'), ResponseInterface::HTTP_CONFLICT);
      
              helper('cookie');
      
      
      //
              $findUser = $this->userModel->asObject()->where($entity->loginType, $entity->login)->first();
      
              $role = $this->groupModel->asObject()->getGroupsForUser($findUser->id);
              $permissions = $this->permissionModel->asObject()->where('active', '1')->findAll();
              $permissionUser = $this->usersPermissionModel->permissionsOfUser($findUser->id);
              $permissionGroup = $this->groupsPermissionModel->permissionsOfGroup($findUser->id);
      
              // store user inof in session
      //        $this->session->set('userInformation', [
      //            'userName' => $this->authenticate->user()->username,
      //            'image' => $this->authenticate->user()->image,
      //            'firstName' => $this->authenticate->user()->first_name,
      //            'lastName' => $this->authenticate->user()->last_name,
      //            'email' => $this->authenticate->user()->email,
      //            'phone' => $this->authenticate->user()->phone,
      //        ]);
      
      
              $data = [
                  'success' => true,
                  'role' => [
                      'name' => $role[0]['name'],
                      'id' => $role[0]['group_id']
                  ],
                  'permissions' => $permissions,
                  'permissionUser' => $permissionUser,
                  'permissionGroup' => $permissionGroup,
                  'userInformation' => [
                      'id' => $findUser->id,
                      'userName' => $findUser->username,
                      'image' => $findUser->image,
                      'firstName' => $findUser->first_name,
                      'lastName' => $findUser->last_name,
                      'email' => $findUser->email,
                      'phone' => $findUser->phone,
                  ],
                  'csrf' => $this->csrfSecurity->init(),
              ];
      
              return $data;
      
          }
      
      
          /**
           * Log the user out.
           * @param object $userData
           */
          public function signOutJwt(object $userData): void
          {
              if (!isset($userData->id)) $this->httpException(lang('Authenticate.filter.jwt'), ResponseInterface::HTTP_CONFLICT);
      
      
              $findUser = $this->userModel->asObject()->where("id", $userData->id)->first();
      
              if (is_null($findUser)) $this->httpException(lang('Auth.forgotNoUser'), ResponseInterface::HTTP_UNAUTHORIZED);
      
      
          }
      
      
      
          //--------------------------------------------------------------------
          // Register
          //--------------------------------------------------------------------
      
          /**
           * Displays the user registration page.
           * @param AuthEntity $entity
           */
          public function signUp(AuthEntity $entity): void
          {
              if (is_null($entity)) $this->httpException(lang('Shared.api.validation'), ResponseInterface::HTTP_CONFLICT);
      
              $entity->generateActivateHash();
      
              $this->userModel->withGroup($entity->role);
      
              if (!$this->userModel->save($entity)) {
      
      
                  $message = lang('Authenticate.auth.rejectRegistration') . " , " . serializeMessages($this->userModel->errors());
                  $this->httpException($message, ResponseInterface::HTTP_BAD_REQUEST);
      
              }
      
      
              if ($entity->loginType == 'email') {
      
      
                  $isSent = $this->email
                      ->setTo($entity->email)
                      ->setSubject(lang('Auth.activationSubject'))
                      ->setMessage(view($this->authConfig->views['emailActivation'],
                          ['hash' => $entity->toArray()['activate_hash']]))
                      ->setMailType('html')->send();
      
      
                  if (!$isSent) {
                      $this->groupModel->removeUserFromAllGroups($this->userModel->getInsertID());
                      $this->userModel->where('id', $this->userModel->getInsertID())->delete();
      
      
                      $message = lang('Authenticate.auth.failRegistration') . " , " . serializeMessages($this->activator->error() ?? lang('Auth.unknownError'));
                      $this->httpException($message,
                          ResponseInterface::HTTP_BAD_REQUEST, $this->email->printDebugger(['headers']));
      
                  }
              } else if ($entity->loginType == 'phone') {
      
      
                  $isSend = $this->sms->sendActivationCode($entity->phone, getenv('siteAddress'));
      
                  if ($isSend < 2000) {
      
                      $message = lang('Authenticate.auth.smsSendFail');
                      $this->httpException($message, ResponseInterface::HTTP_FOUND);
      
                  }
              }
      
      
          }
      
      //--------------------------------------------------------------------
      // Forgot Password
      //--------------------------------------------------------------------
      
          /**
           * Displays the forgot password form.
           * @param AuthEntity $entity
           */
          public
          function forgot(AuthEntity $entity): void
          {
              if (is_null($entity)) $this->httpException(lang('Shared.api.validation'), ResponseInterface::HTTP_CONFLICT);
      
      
              $findUser = $this->userModel->where($entity->loginType, $entity->login)->first();
      
              if (is_null($findUser)) $this->httpException(lang('Auth.forgotNoUser'), ResponseInterface::HTTP_UNAUTHORIZED);
      
              $statusEmail = false;
              $statusSms = 0;
              if (!is_null($findUser->email)) {
      
                  $statusEmail = $this->email
                      ->setTo($findUser->email)
                      ->setSubject(lang('Auth.forgotSubject'))
                      ->setMessage(view($this->authConfig->views['emailForgot'],
                          ['hash' => $entity->toArray()['reset_hash']]))
                      ->setMailType('html')->send();
      
      
              }
      
      
              if (!is_null($findUser->phone)) {
      
                  $statusSms = $this->sms->sendActivationCode($findUser->phone, getenv('siteAddress'));
      
              }
      
      
              if ($statusSms < 2000 && !$statusEmail) $this->httpException(lang('Auth.unknownError'),
                  ResponseInterface::HTTP_BAD_REQUEST, $this->email->printDebugger(['headers']));
      
      
              if (!$this->userModel->update($findUser->id, $entity)) {
      
      
                  $this->httpException(lang('Shared.api.reject'), ResponseInterface::HTTP_BAD_REQUEST, serializeMessages($this->userModel->errors()));
      
              }
      
      
          }
      
      
          /**
           * Verifies the code with the email and saves the new password,
           * if they all pass validation.
           *
           * @param AuthEntity $entity
           */
      
          public
          function resetPasswordViaSms(AuthEntity $entity): void
          {
              if (is_null($entity)) $this->httpException(lang('Shared.api.validation'), ResponseInterface::HTTP_NOT_ACCEPTABLE);
      
      
              $findUser = $this->userModel->where('phone', $entity->phone)->first();;
      
      
              if (is_null($findUser)) $this->httpException(lang('Authenticate.forgotNoUserPhone'), ResponseInterface::HTTP_CONFLICT);
      
      
              if (!$this->sms->isActivationCodeValid($entity->phone, $entity->code)) $this->httpException(lang('Auth.resetTokenExpired'), ResponseInterface::HTTP_NOT_ACCEPTABLE);
      
      
              unset($entity->phone);
              if (!$this->userModel->update($findUser->id, $entity)) {
      
      
                  $this->httpException(lang('Shared.api.reject'), ResponseInterface::HTTP_BAD_REQUEST, serializeMessages($this->userModel->errors()));
      
              }
      
      
          }
      
          /**
           * Verifies the code with the email and saves the new password,
           * if they all pass validation.
           *
           * @param AuthEntity $entity
           */
      
          public
          function resetPasswordViaEmail(AuthEntity $entity): void
          {
              if (is_null($entity)) $this->httpException(lang('Shared.api.validation'), ResponseInterface::HTTP_NOT_ACCEPTABLE);
      
      
              $this->userModel->logResetAttempt(
                  $entity->email,
                  $entity->token,
                  $entity->ip_address,
                  $entity->user_agent
              );
      
      
              $findUser = $this->userModel->where('email', $entity->email)
                  ->where('reset_hash', $entity->token)->first();
      
      
              if (is_null($findUser)) $this->httpException(lang('Auth.forgotNoUser'), ResponseInterface::HTTP_CONFLICT);
      
      
              // Reset token still valid?
              if (!empty($findUser->reset_expires) && time() > $findUser->reset_expires->getTimestamp()) $this->httpException(lang('Auth.resetTokenExpired'), ResponseInterface::HTTP_NOT_ACCEPTABLE);
      
              unset($entity->email);
              if (!$this->userModel->update($findUser->id, $entity)) {
      
                  $this->httpException(lang('Shared.api.reject'), ResponseInterface::HTTP_BAD_REQUEST, serializeMessages($this->userModel->errors()));
      
              }
      
          }
      
          /**
           * Activate account.
           *
           * @param AuthEntity $entity
           */
          public
          function activateAccountViaEmail(AuthEntity $entity): void
          {
              if (is_null($entity)) $this->httpException(lang('Shared.api.validation'), ResponseInterface::HTTP_NOT_ACCEPTABLE);
      
              $this->userModel->logActivationAttempt(
                  $entity->token,
                  $entity->ip_address,
                  $entity->user_agent
              );
      
      
              $findUser = $this->userModel->where('activate_hash', $entity->token)
                  ->where('active', 0)->where('email', $entity->email)
                  ->first();
              if (is_null($findUser)) $this->httpException(lang('Auth.activationNoUser'), ResponseInterface::HTTP_CONFLICT);
      
              unset($entity->email);
              if (!$this->userModel->update($findUser->id, $entity)) {
      
                  $this->httpException(lang('Shared.api.reject'), ResponseInterface::HTTP_BAD_REQUEST, serializeMessages($this->userModel->errors()));
      
              }
      
          }
      
          /**
           * Resend activation account.
           * @param AuthEntity $entity
           */
          public
          function sendActivateCodeViaEmail(AuthEntity $entity): void
          {
              if (is_null($entity)) $this->httpException(lang('Shared.api.validation'), ResponseInterface::HTTP_NOT_ACCEPTABLE);
      
              $findUser = $this->userModel->where('email', $entity->email)
                  ->where('active', 0)
                  ->first();
      
              if (is_null($findUser)) $this->httpException(lang('Auth.activationNoUser'), ResponseInterface::HTTP_CONFLICT);
      
      
              $isSent = $this->email
                  ->setTo($entity->email)
                  ->setSubject(lang('Auth.activationSubject'))
                  ->setMessage(view($this->authConfig->views['emailActivation'],
                      ['hash' => $entity->toArray()['activate_hash']]))
                  ->setMailType('html')->send();
      
              if (!$isSent) {
      
      
                  $this->httpException(lang('Auth.unknownError'),
                      ResponseInterface::HTTP_BAD_REQUEST, $this->email->printDebugger(['headers']['headers'] ?? lang('Auth.unknownError')));
      
              }
              unset($entity->email);
      
      
              if (!$this->userModel->update($findUser->id, $entity)) {
      
      
                  $this->httpException(lang('Shared.api.reject'), ResponseInterface::HTTP_BAD_REQUEST, serializeMessages($this->userModel->errors()));
      
              }
      
          }
      
          /**
           * Activate account via sma.
           *
           * @param AuthEntity $entity
           */
          public function activateAccountViaSms(AuthEntity $entity): void
          {
              if (is_null($entity)) $this->httpException(lang('Shared.api.validation'), ResponseInterface::HTTP_NOT_ACCEPTABLE);
      
              $result = $this->sms->isActivationCodeValid($entity->phone,
                  $entity->code);
      
              if ($result == false) $this->httpException(lang('Authenticate.auth.smsActivationFail'), ResponseInterface::HTTP_CONFLICT);
      
              $findUser = $this->userModel->where('active', 0)
                  ->where('phone', $entity->phone)->first();
      
              if (is_null($findUser)) $this->httpException(lang('Auth.activationNoUser'), ResponseInterface::HTTP_CONFLICT);
      
              unset($entity->phone);
              if (!$this->userModel->update($findUser->id, $entity)) {
      
                  $this->httpException(lang('Shared.api.reject'), ResponseInterface::HTTP_BAD_REQUEST, serializeMessages($this->userModel->errors()));
      
              }
          }
      
          /**
           * Activate account via sma.
           *
           * @param AuthEntity $entity
           */
          public
          function sendActivateCodeViaSms(AuthEntity $entity): void
          {
              if (is_null($entity)) $this->httpException(lang('Shared.api.validation'), ResponseInterface::HTTP_NOT_ACCEPTABLE);
      
              $findUser = $this->userModel
                  ->where('active', 0)->where('phone', $entity->phone)->first();
              if (is_null($findUser)) $this->httpException(lang('Auth.activationNoUser'), ResponseInterface::HTTP_CONFLICT);
      
              $result = $this->sms->sendActivationCode($entity->phone, getenv('siteAddress'));
              if ($result < 2000) $this->httpException(lang('Authenticate.auth.smsSendFail'), ResponseInterface::HTTP_BAD_REQUEST);
      
      
          }
      
      
      }
      
      

      【讨论】:

        猜你喜欢
        • 2018-03-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-09-03
        • 2020-05-20
        • 2015-09-20
        • 1970-01-01
        相关资源
        最近更新 更多