php - 用户管理员登录,给用户提升权限 - Symfony 4
问题描述
请原谅我的提问,我已经在我的网站登录/注册页面上工作了一段时间,最后两者看起来都完美无缺,我的下一个任务是访问控制,这样我就可以在我的论坛上做一些工作而无需加载我的 SSH 和进行数据库更改。
我的 Composer.JSON 包含我已经拥有的包列表
"require": {
"php": "^7.1.3",
"ext-iconv": "*",
"doctrine/doctrine-migrations-bundle": "^2.0",
"knplabs/knp-markdown-bundle": "^1.7",
"sensio/framework-extra-bundle": "^5.1",
"symfony/asset": "^4.0",
"symfony/console": "^4.0",
"symfony/flex": "^1.1",
"symfony/form": "^4.0",
"symfony/framework-bundle": "^4.0",
"symfony/maker-bundle": "^1.1",
"symfony/orm-pack": "^1.0",
"symfony/profiler-pack": "^1.0",
"symfony/security-bundle": "^4.0",
"symfony/translation": "^4.0",
"symfony/twig-bundle": "^4.0",
"symfony/validator": "^4.0",
"symfony/yaml": "^4.0"
},
"require-dev": {
"sensiolabs/security-checker": "^4.1",
"symfony/dotenv": "^4.0",
"symfony/web-server-bundle": "^4.0"
我遇到的问题是,当数据库返回一个空数组时,我的登录表单会自动输出'ROLE_USER'
,但是我不清楚如何将对象添加到数据库 JSON,因为我需要'ROLE_ADMIN'
字符串。
我知道我可以将管理员用户添加到内存中,但我想完全依赖于数据库,在我的根服务器上的文档中输入一些内容对我来说是正确的(出于某种原因)
我检查了 symfony 文档并在此处查看并没有发现任何对我有帮助的东西。
我想授予用户(我),'ROLE_ADMIN'
而所有其他用户仍然获得返回。我的防火墙已经设置了层次结构管理员继承用户,所以我不应该将自己锁定在其他页面之外。'ROLE_USER'
'getRoles()'
我已经实施了一些访问控制计数,如下所示
../config/packages/security.yaml
...
access_control:
- { path: ^/admin, roles: ROLE_ADMIN }
- { path: ^/profile, roles: ROLE_USER }
和
../templates/forum/index.html.twig
...
{% if is_granted('ROLE_ADMIN') %}
<li><a href="{{ path('page_admin') }}">Admin</a></li>
{% endif %}
...
在这里,我将为你们删除我所有的控制器/实体信息-*我所有的注册/身份验证文件都是使用 maker-bundle 生成的
../securityController
namespace App\Controller;
use App\Form\UserType;
use App\Entity\User;
use App\Form\RegistrationFormType;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Security\Http\Authentication\AuthenticationUtils;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
class SecurityController extends AbstractController
{
...
Registration function
...
/**
* @Route("/forum/login", name="app_login")
*/
public function login(AuthenticationUtils $authenticationUtils): Response
{
// get the login error if there is one
$error = $authenticationUtils->getLastAuthenticationError();
// last username entered by the user
$lastUsername = $authenticationUtils->getLastUsername();
return $this->render('security/login.html.twig', ['last_username' => $lastUsername, 'error' => $error]);
}
实体
.../Entity/User
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
use Symfony\Component\Security\Core\User\UserInterface;
/**
* @ORM\Entity(repositoryClass="App\Repository\UserRepository")
* @UniqueEntity(fields={"email"}, message="There is already an account with this email")
*/
class User implements UserInterface
{
/**
* @ORM\Id()
* @ORM\GeneratedValue()
* @ORM\Column(type="integer")
*/
private $id;
/**
* @ORM\Column(type="string", length=180, unique=true)
*/
private $email;
/**
* @ORM\Column(type="json")
*/
private $roles = [];
/**
* @var string The hashed password
* @ORM\Column(type="string")
*/
private $password;
public function getId(): ?int
{
return $this->id;
}
public function getEmail(): ?string
{
return $this->email;
}
public function setEmail(string $email): self
{
$this->email = $email;
return $this;
}
/**
* A visual identifier that represents this user.
*
* @see UserInterface
*/
public function getUsername(): string
{
return (string) $this->email;
}
/**
* @see UserInterface
*/
public function getRoles(): array
{
$roles = $this->roles;
// guarantee every user at least has ROLE_USER
$roles[] = 'ROLE_USER';
return array_unique($roles);
}
public function setRoles(array $roles): self
{
$this->roles = $roles;
return $this;
}
/**
* @see UserInterface
*/
public function getPassword(): string
{
return (string) $this->password;
}
public function setPassword(string $password): self
{
$this->password = $password;
return $this;
}
/**
* @see UserInterface
*/
public function getSalt()
{
// not needed when using the "bcrypt" algorithm in security.yaml
}
/**
* @see UserInterface
*/
public function eraseCredentials()
{
// If you store any temporary, sensitive data on the user, clear it here
// $this->plainPassword = null;
}
}
认证
<?php
namespace App\Security;
use App\Entity\User;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Exception\CustomUserMessageAuthenticationException;
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
use Symfony\Component\Security\Core\Exception\InvalidCsrfTokenException;
use Symfony\Component\Security\Core\Security;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\User\UserProviderInterface;
use Symfony\Component\Security\Csrf\CsrfToken;
use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface;
use Symfony\Component\Security\Guard\Authenticator\AbstractFormLoginAuthenticator;
use Symfony\Component\Security\Http\Util\TargetPathTrait;
class LoginAuthFormAuthenticator extends AbstractFormLoginAuthenticator
{
use TargetPathTrait;
private $entityManager;
private $urlGenerator;
private $csrfTokenManager;
private $passwordEncoder;
public function __construct(EntityManagerInterface $entityManager, UrlGeneratorInterface $urlGenerator, CsrfTokenManagerInterface $csrfTokenManager, UserPasswordEncoderInterface $passwordEncoder)
{
$this->entityManager = $entityManager;
$this->urlGenerator = $urlGenerator;
$this->csrfTokenManager = $csrfTokenManager;
$this->passwordEncoder = $passwordEncoder;
}
public function supports(Request $request)
{
return 'app_login' === $request->attributes->get('_route')
&& $request->isMethod('POST');
}
public function getCredentials(Request $request)
{
$credentials = [
'email' => $request->request->get('email'),
'password' => $request->request->get('password'),
'csrf_token' => $request->request->get('_csrf_token'),
];
$request->getSession()->set(
Security::LAST_USERNAME,
$credentials['email']
);
return $credentials;
}
public function getUser($credentials, UserProviderInterface $userProvider)
{
$token = new CsrfToken('authenticate', $credentials['csrf_token']);
if (!$this->csrfTokenManager->isTokenValid($token)) {
throw new InvalidCsrfTokenException();
}
$user = $this->entityManager->getRepository(User::class)->findOneBy(['email' => $credentials['email']]);
if (!$user) {
// fail authentication with a custom error
throw new CustomUserMessageAuthenticationException('Email could not be found.');
}
return $user;
}
public function checkCredentials($credentials, UserInterface $user)
{
return $this->passwordEncoder->isPasswordValid($user, $credentials['password']);
}
public function onAuthenticationSuccess(Request $request, TokenInterface $token, $providerKey)
{
if ($targetPath = $this->getTargetPath($request->getSession(), $providerKey)) {
return new RedirectResponse($targetPath);
}
// For example : return new RedirectResponse($this->urlGenerator->generate('some_route'));
return new RedirectResponse($this->urlGenerator->generate('page_forum'));
}
protected function getLoginUrl()
{
return $this->urlGenerator->generate('app_login');
}
}
在此先感谢,欢迎任何想法
解决方案
roles
要在 Symfony 中手动为用户添加角色,最好的解决方案是将相关用户的数据库列直接更新[]
为["ROLE_ADMIN"]
.
但是,如果您在更新数据库时遇到任何问题,您仍然可以像/givemeadminrole
在任何控制器中一样创建自定义路由,您可以使用它$this->getUser()->addRole("ROLE_ADMIN");
来添加ROLE_ADMIN
到连接的用户。
(当然,这适用于任何角色。)
不要忘记向persist
您的用户保存数据库中的更改。
推荐阅读
- c++ - TFT LTDC 显示 - 像素未写入正确位置
- python - 如何为自定义用户设置 Django 权限?
- asp.net - Visual Studio 2017 在我没有创建的调试中不断添加严格的 CSP
- reactjs - 理解 !打字稿中的运算符
- php - 简单的 URL 路由
- configuration - 如何使用 Charts js v 3.2 在堆积条形图上显示所有数据标签?
- python - 使用 itertools 时如何将字典视为“整体”?
- excel - 自依赖数据验证
- angularjs - 如何避免在 Angular 项目的引导选项卡中使用 routerlink?
- javascript - 在用户输入的屏幕上分隔文本