Symfony2 users have shared multiple applications
I have several symfony2 applications that have common entities but use different database settings. Each of these databases has tables user
, user_role
and role
.
Here's the catch: I would like this user to be able to log in app1
by visiting www.myproject.com/app1/login
and after changing the url to /app2/
to use the existing token ONLY if an identical user exists in the database app2
(same username, password, and salt). Currently, it only checks the same username, which you have to agree is rather inconvenient ...
I cannot see when refreshUser()
... is called : - /
All applications use the same user
, and role
the nature and UserRepository
.
Any help would be greatly appreciated!
UserRepository:
class UserRepository extends EntityRepository implements \Symfony\Component\Security\Core\User\UserProviderInterface{
/** @var User */
private $user;
public function loadUserByUsername($username) {
/** @var $Q \Doctrine\ORM\Query */
$Q = $this->getEntityManager()
->createQuery('SELECT u FROM CommonsBundle:User u WHERE u.username = :username')
->setParameters(array(
'username' => $username
));
$user = $Q->getOneOrNullResult();
if ( $user == null ){
throw new UsernameNotFoundException("");
}
return $this->user = $user;
}
public function refreshUser(UserInterface $user) {
return $this->loadUserByUsername($user->getUsername());
}
public function supportsClass($class) {
return $class === 'CommonsBundle\Entity\User';
}
public function findById($id){
return $this->getEntityManager()
->createQuery('SELECT u FROM CommonsBundle:User u WHERE u.id = :id')
->setParameters(array(
'id' => $id
))
->getOneOrNullResult();
}
}
User # Equals () user interface:
I know there is a nicer way to write this method, but I rewrote it after seeing this work :)
public function equals(UserInterface $user)
{
if (!$user instanceof User) {
return false;
}
if ($this->password !== $user->getPassword()) {
return false;
}
if ($this->getSalt() !== $user->getSalt()) {
return false;
}
if ($this->username !== $user->getUsername()) {
return false;
}
return true;
}
source to share
Your question made me think. When using symfony2 security, you have one problem: either the session is valid, that is, the user is authenticated as anonymous or real user, or the session is invalid.
So with that in mind, I don't see your approach working the way you would like, because let user1 log in and use app 1. Now it switches to app2 and is not in the database, meaning it is not must have access. What to do now? Invalid session? This means he must log in to app 1 again.
If you use subdomains, you can associate your session with that subdomain, but this will mean that the user must be logged in again for each application.
Another problem arises: it looks like symfony2 stores the user ID in the session, so without access to the app1 database, you cannot know what the password and user roles in the app1 database are and cannot check for it.
I suppose that symfony2 security was simply not built for this behavior. It expects the session to be associated with the same user throughout your application.
I don't think symfony2 is a big problem here , but general handling with php. Let's think for a moment what I propose without symfony2:
When the user logs in, store the user and roles in a specific array in the session, for example:
user.app1 = array('username','password',array('role1','role2'))
Now, on every request to app1, I would check if user.app1 is in the session and read roles from there. If not, I would check for user.app2, user.app3 and so on. If I don't find any, please forward the login. If I find it, I would query the database to find a user with the same username and compare other values. If there is a match, store everything in the database. If not, check the next user from the session.
I personally think the design itself is not optimal here and you might be better off refactoring your code to use the same user for all applications and different roles (remember you can define many entity managers and use different databases) or even consolidate all databases and store everything in one database using acl to prevent users from viewing "wrong" content.
source to share