PHP/Symfony Framework 시큐리티
회원등록 (Registration)
bin/console make:user
composer require symfony/orm-pack symfony/form symfony/security-bundle symfony/validator
// 유저 엔티티
/**
* @ORM\Column(type="string", length=180, unique=true)
* @Assert\NotBlank()
* @Assert\Email()
*/
private $email;
/**
* @ORM\Column(type="json")
*/
private $roles = [];
/**
* @var string The hashed password
* @ORM\Column(type="string")
* @Assert\NotBlank()
* @Assert\Length(max=64)
*/
private $password;
// 폼 타입
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder
->add('email', EmailType::class)
->add('password', RepeatedType::class, [
'type' => PasswordType::class,
'first_options' => array('label' => 'Password'),
'second_options' => array('label' => 'Repeat Password'),
])
->add('save', SubmitType::class, ['label' => 'Register'])
;
}
// 컨트롤러 메소드
$user = new SecurityUser();
$form = $this->createForm(RegisterUserType::class, $user);
$form->handleRequest($request);
if($form->isSubmitted() && $form->isValid()) {
$user->setPassword(
$passwordEncoder->encodePassword($user, $form->get('password')->getData())
);
$user->setEmail($form->get('email')->getData());
$entityManager = $this->getDoctrine()->getManager();
$entityManager->persist($user);
$entityManager->flush();
return $this->redirectToRoute('home');
}
로그인 (Login)
# security.yaml
form_login:
login_path: LOGIN_PATH
check_path: CHECK_PATH
username_parameter: 'email'
password_parameter: 'password'
csrf_token_generator: security.csrf.token_manager
<form method="post">
{% if error %}
<div class="alert alert-danger">{{ error.messageKey|trans(error.messageData, 'security') }}</div>
{% endif %}
<h1 class="h3 mb-3 font-weight-normal">Please sign in</h1>
<label for="inputEmail" class="sr-only">Email</label>
<input type="email" value="{{ last_username }}" name="email" id="inputEmail" class="form-control" placeholder="Email" required autofocus>
<label for="inputPassword" class="sr-only">Password</label>
<input type="password" name="password" id="inputPassword" class="form-control" placeholder="Password" required>
<input type="hidden" name="_csrf_token"
value="{{ csrf_token('authenticate') }}"
>
<button class="btn btn-lg btn-primary" type="submit">
Sign in
</button>
</form>
// 컨트롤러
public function login(AuthenticationUtils $authenticationUtils) {
$error = $authenticationUtils->getLastAuthenticationError();
$lastUsername = $authenticationUtils->getLastUsername();
return $this->render('security/login.html.twig', [
'last_username' => $lastUsername,
'error' => $error
]);
}
로그아웃 (Logout)
# security.yaml
logout:
path: /LOGOUT_PATH
target: /REDIRECT_PATH
{% if app.user %}
<a href="{{ path('logout') }}">LOGOUT</a>
{% endif %}
CSRF
<input type="hidden" name="_csrf_token" value="{{ csrf_token('authenticate') }}" >
# security.yaml
form_login:
csrf_token_generator: security.csrf.token_manager
기억하기 (Remember Me)
# security.yaml
remember_me:
secret: '%kernel.secret%'
lifetime: 604800 # 1 week in seconds
#always_remember_me: true
path: /
: Template
<input type="checkbox" name="_remember_me"> Remember me
인가 (Authorization)
지역 범위
// 컨트롤러 샘플
/**
* @Security("has_role('ROLE_ADMIN')")
*/
public function index(Request $request) {
// 생략
}
전역 범위
# security.yaml
# /admin 으로 시작되면 관리자만 접근 할 수 있다.
access_control:
- { path: ^/admin, roles: ROLE_ADMIN }
도메인 계층
$this->denyAccessUnlessGranted('IS_AUTHENTICATED_FULLY')
$this->denyAccessUnlessGranted('IS_AUTHENTICATED_REMEMBERED')
// 관리자 외 접근 시 예외발생
$this->denyAccessUnlessGranted('ROLE_ADMIN')
웹 계층
{% is_granted('ROLE_ADMIN') %}
{% endif %}
{% is_granted('IS_AUTHENTICATED_FULLY') %}
{% endif %}
...
시큐리티 검사(Security Check)
composer require sensiolabs/security-check
bin/console security:check