Symfony2如何使用两个不同的用户名对用户进行身份验证以访问不同的URL

时间:2017-04-09 09:31:34

标签: symfony symfony-2.3 symfony-2.8 symfony-2.7

我正在开发一个symfony项目,我对用户的身份验证有一个问题,我希望你解决,因为我是新手。

我的项目是关于一所学校,其中有教师类型的用户在数据库中具有usernamepassword属性。用户名由字母t后跟个人识别码组成,例如t48945110。此外,教师有一个布尔属性来指示哪一个是校长(只有一个)。

我的项目中的安全设置如下:

Secutiry.yml

security:

  firewalls:

    intranet:
        pattern:  ^/
        anonymous: ~
        provider: teachers
        form_login:
            login_path: /login
            check_path: /login_check
           # use_referer: true
            default_target_path: /teacher
        logout: ~

    access_control:
    - { path: ^/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
    - { path: admin/, roles: ROLE_ADMIN }
    - { path: /teacher, roles: ROLE_TEACHER }

    providers:
      teachers:
        entity: { class: School\BackendBundle\Entity\Teacher, property: username}

   encoders:
      School\BackendBundle\Entity\Teacher: { algorithm: sha512 }

通过上述内容,教师可以通过登录表单访问他的私人部分,但是当我想访问导演(数据库中具有属性(director=1)的教师)时,我遇到了问题。我希望这位老师能够使用其他用户名访问,但不能将其保存在数据库中,只需更改主要字母,然后在身份验证中查找教师的正常用户名,并检查导演是否将其重定向到/ admin代替/teacher。例如,学校的负责人可以通过用户名t48945110以教师的身份访问他的个人区域,也可以使用用户名d48945110访问学校的管理区域。

这个想法不是创建两种不同的登录表单,而是访问应用程序的所有用户(学生,教师,导演......)。

我不知道是否可以通过事件监听器或其他方式完成。感谢您的帮助。

1 个答案:

答案 0 :(得分:1)

我认为你可能会过度复杂化。我非常确定您的导演不想使用不同的用户名登录以进入单独的部分。在不知道更多细节的情况下,我建议您将getRoles()中的School\BackendBundle\Entity\Teacher更改为以下内容:

public function getRoles()
{
    $roles = array('ROLE_TEACHER');
    if ($this->director == 1) {
        $roles[] = 'ROLE_DIRECTOR';
        $roles[] = 'ROLE_ADMIN';
    }

    return $roles;
}

这可能是让用户成为可以访问其安全区域的教师以及无需切换帐户即可访问管理区域的导演的最简单方法。

如果由于某种原因这不起作用,你可以查看Security Voters。这看起来像这样:

class TeacherIsDirectorVoter extends Voter
{

    protected function supports($attribute, $subject)
    {
        // This voter will always be used
        return true;
    }

    protected function voteOnAttribute($attribute, $subject, TokenInterface $token)
    {
        $user = $token->getUser();
        // This voter will allow access if the currently logged in user is teacher and is a director

        return ($user instanceof Teacher && $user->isDirector());
    }
}

同样,这将为作为导演的教师授予访问权限,而不要求他们以其他用户身份登录。请谨慎对待这位选民,因为它总是会向拥有director=1默认选民策略的教师授予您网站所有部分的访问权限。有一些方法可以改变这种情况,或者你可以根据提供的属性和被投票的主题添加支票。

我认为对于您的用例,第一个选项(更新角色)可能是最简单的,并且适用于您。

如果您希望学生,教师和导演在登录后重定向到不同的页面,您可以做一些小技巧。在SecurityController中(或者您的loginAction的任何位置)创建一个新的targetAction(),在成功登录后用作目标。在security.yml中,将form_login的default_target_path分配给该路由,而不是/ teacher。所有3个用户组都应该可以访问该操作。现在只需根据用户的角色重定向:

public function targetAAction()
{
    $user = $this->getUser();
    if (in_array('ROLE_ADMIN', $user->getRoles())) {
        return $this->redirectToRoute('intranet_admin_page');
    }
    if (in_array('ROLE_TEACHER', $user->getRoles())) {
        return $this->redirectToRoute('intranet_teacher_page');
    }

    return $this->redirectToRoute('generic_page_for_users');
}