Symfony2 - 在进入匿名区域时重定向登录用户

时间:2016-10-10 13:59:19

标签: symfony security authorization

我创建了一个操作,根据用户的类型和ROLE(实习生,公司或大学让我们说),处理重定向到受尊重区域的操作。如果用户未登录,则会重定向到主页(匿名区域),如果已登录,则会重定向到其个人资料页面。我在主页和许多其他情况下使用它,例如,注册和登录成功重定向。

public function authorizationAction(Request $request)
{
    $user = $this->getUser();
    $authorizationChecker = $this->get('security.authorization_checker');

    $request->cookies->remove('action');

    if ($user) {
        if ($user->getType() == 'company' && $authorizationChecker->isGranted('ROLE_COMPANY_GUEST')) {
            /** @var Company $company */
            $company = $user->getCompany();
            if ($user->getState() == 'active' && $company->getState() == 'active') {
                $response = $this->redirectToRoute('company');
            } else {
                $response = $this->redirectToRoute('company_profile');
            }
        } elseif ($user->getType() == 'university' && $authorizationChecker->isGranted('ROLE_UNIVERSITY_GUEST')) {
            /** @var University $university */
            $university = $user->getUniversity();
            if ($user->getState() == 'active' && $university->getState() == 'active') {
                $response = $this->redirectToRoute('university');
            } else {
                $response = $this->redirectToRoute('university_profile');
            }
        } elseif ($user->getType() == 'trainee' && $authorizationChecker->isGranted('ROLE_TRAINEE')) {
            /** @var Trainee $trainee */
            $trainee = $user->getTrainee();
            if ($user->getState() == 'active' && $trainee->getState() == 'active') {
                $response = $this->redirectToRoute('trainee');
            } else {
                $response = $this->redirectToRoute('trainee_profile');
            }
        } else {
            $response = $this->redirectToRoute('homepage');
        }
    } else {
        $response = $this->redirectToRoute('homepage');
    }

    return $response;
}

我见过一些examples建议使用symfony事件(kernel.request)来处理它最小化控制器代码。但在这种情况下,我将无法将此操作用作注册和登录成功路径。

我没有使用FOS,因为缺少用户自定义。我更喜欢处理用户自己。

我的方法是错误的还有什么值得担心的?

我担心的一些事情:

  1. 重定向次数:
  2. 例如。我已登录用户并转到主页并被重定向到我的操作,我会检查是否已登录,并且根据用户类型,我被重定向到受尊重的页面。

    public function indexAction(Request $request)
    {
        if ($this->get('security.authorization_checker')->isGranted('IS_AUTHENTICATED_FULLY')) {
            return $this->redirectToRoute('authorization');
        }
    
        // ...
    
    }
    
    1. 减速网站:
    2. 将来我将在更多页面中使用此操作,每次在每个页面上执行相同的代码时,网站都会放慢速度。

2 个答案:

答案 0 :(得分:0)

Symfony documentation中的访问控制部分可能提供更简单的限制访问的解决方案。在我使用Symfony的时候,我总是能够将它用于重定向和访问控制。

答案 1 :(得分:0)

  

由于缺乏用户自定义,我没有使用FOS。我更喜欢处理用户自己。   块引用

你真的不应该在这里重新发明轮子但是即使你想要评估扩展FOS很难是错误的,看看这个gist我们有多少Symfony Devs扩展FOS才能启用通过HWIOauthBundle进行社交登录。将其扩展用于其他目的同样微不足道。

自OP的评论以来更新

...

use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
use Symfony\Component\Security\Core\Authentication\Token\AnonymousToken;
use AppBundle\Form\Type\LoginType;

...

...

$login_form = $this->createForm(LoginType::class);
$login_form->handleRequest($request);

if (!$login_form->isValid()){
    //throw error
}

$email = strip_tags($login_form->get('email')->getData());
$password = $login_form->get('password')->getData();

// Call the User Manager
$userManager = $this->get('fos_user.user_manager');
$user = $userManager->findUserByUsernameOrEmail($email);

if(!$user){
    //throw error : User With Submitted Credentials Does Not Exist
}

$user_password = $user->getPassword();
$encoded_password = $this->get('security.password_encoder')->encodePassword($user, $password);

if($encoded_password != $user_password){
    //throw error : Wrong Password, Please Check Your Details & Re-submit
}

// Successful query of username/email and password now we log in user

// Create new token
$token = new UsernamePasswordToken($user, $user->getPassword(), 'main', $user->getRoles());

// Login New User
$tokenStorage = $this->get('security.token_storage');
$tokenStorage->setToken($token);

// User now logged in
$user_id = $user->getId();

...

  

重定向计数:

在您的情况下,每次重定向都会导致至少1个数据库查询来验证用户会话,因此很多可能会导致糟糕的使用和服务器体验。如果您将FOSUserBundle与Doctrine的二级缓存一起使用,则每次调用$ this-> getUser();

时都可以避免此查询
  

网站减速:

这一小段代码几乎不会成为你的瓶颈,但为了论证,我们假设它是。我会通过引入客户端会话来解决这个问题。像Angular或我个人最喜欢的Ember这样的框架允许您在客户端上存储用户会话,以免因为检查身份验证或角色这样的琐碎任务而一直无法回到服务器。我仍然建议你为那些想要在你的代码中挖洞的那些厚颜无耻的用户保留一些服务器端代码。