authorization - CakePHP 4 Request AuthorizationMiddleware - 如何动态重定向unauthorized用户

我在 CakePHP 4.0 中实现了新的身份验证、Authorization 和 RequestAuthorization 中间件。我想将 unauthorized 请求(来自经过身份验证的用户)重定向到各个页面,具体取决于他们的角色、状态等几个条件。目前,所有 unauthorized 请求都重定向到我的 unauthorized 重定向 url - Pages/权限页面。有没有办法从 RequestPolicy/canAccess 函数中动态更改 unauthorized 重定向 url?

我的 RequestPolicy/canAccess 函数如下所示(已编辑):

public function canAccess($identity, ServerRequest $request)
{
    $unauthenticatedActions = $request->getAttribute('authentication')->getConfig('unauthenticatedActions');
    if (in_array($request->getParam('action'), $unauthenticatedActions, true)) { 
        return true;
    }
    else if(!empty($identity)){
        //check based on actions and user roles

        $userRole = $identity->role;
        $userStatus = $identity->status;
        $accountType = $identity->accountsubType;
        $action = $request->getParam('action');
        $controller = $request->getParam('controller');

        switch ($controller) {

            case 'Pages':
                return true;
                break;

            case 'Users':
                    if($userRole === 'ADMIN' && $userStatus === 'ACTIVE'){
                        return true;
                    }elseif($action === 'aaa'){
                        if($userRole === 'xxx' && $userStatus === 'ACTIVE'){
                            return true;
                        }
                        elseif($userRole === 'xxx' && $userStatus === 'EXPIRED'){
                            //redirect to custom 'suspended access' page
                            return false;
                        }
                        elseif($userRole === 'yyy' && $accountType === 'c'){
                            //redirect to custom 'restricted access' page 
                            return false;
                        }
                        else{
                            return false;
                        }
                    }
                    ...
                    return false;
            case: "Sales":   
            ...
            default:
                //none of the Controller names matches
                return false; //redirects to the default unauthorized redirect url (pages/permission)
                //here if I return true, I get the MissingControllerException, MissingActionException etc as expected
    }else{
        //force them back to the login page
        $request =  $request
                    ->withParam('controller', 'users')
                    ->withParam('action', 'login');
        return true; 
    }
}

src/应用程序/中间件()

$middlewareQueue
            ....
            ->add(new AuthenticationMiddleware($this))
            ->add(new AuthorizationMiddleware($this, [
                    'requireAuthorizationCheck' => true,
                    'unauthorizedHandler' => [
                        'className' => 'CustomRedirect',
                        'url' => '/pages/permission',
                        'exceptions' => [
                            'MissingIdentityException' => 'Authorization\Exception\MissingIdentityException',
                            'ForbiddenException' => 'Authorization\Exception\ForbiddenException'
                        ],
                    ],
                ]))
            ->add(new RequestAuthorizationMiddleware());

回答1

不,策略不能这样做,这不是它所关心的,它应该做的就是回答是否允许给定身份访问给定资源的问题。

如果您想要自定义重定向,那么您应该考虑实现自定义“unauthorized 处理程序”,您可以在其中检查身份并计算重定向 URL。例如扩展内置的重定向处理程序,并覆盖其 URL 生成方法,类似于以下内容:

// in src/Middleware/UnauthorizedHandler/IdentityRedirectHandler.php

namespace App\Middleware\UnauthorizedHandler;

use Authorization\Middleware\UnauthorizedHandler\RedirectHandler;
use Psr\Http\Message\ServerRequestInterface;

class IdentityRedirectHandler extends RedirectHandler
{
    protected function getUrl(ServerRequestInterface $request, array $options): string
    {
        $identity = $request->getAttribute('identity');
        
        $role = $identity->get('role');
        $status = $identity->get('status');
        
        if ($role === 'xxx' && $status === 'b') {
            $url = '/suspended';
        } elseif ($role === 'yyy' && $status === 'c') {
            $url = '/restricted';
        } else {
            // default URL from middleware config
            $url = $options['url'];
        }

        $options['url'] = $url;
        
        return parent::getUrl($request, $options);
    }
}
// in src/Applicatiom.php

new AuthorizationMiddleware($this, [
    'unauthorizedHandler' => [
        'className' => 'IdentityRedirect',
        'url' => '/default-redirect-url',
        // ...
    ],
])

也可以看看

相似文章