16/06/2017 - SYMFONY
API şeklinde dizayn edilen bu uygulamada, Basic Auth authentication kullanıyoruz ayrıca, login veya logout fonksiyonlarıda mevcut değil. Kullanıcılar sadece izinli oldukları adreslere girebilirler, aksi takdirde "401 Unauthorised" hatası alırlar. Kullanıcılar veritabanında tutuluyor.
GET /1/students
: ROLE_STUDENT, ROLE_LECTURER, ROLE_ADMINPOST /1/students
: ROLE_ADMINGET /1/lecturers
: ROLE_LECTURER, ROLE_ADMINPOST /1/lecturers
: ROLE_ADMINGET /1/admins
: ROLE_ADMINPOST /1/admins
: ROLE_ADMINİletişim hakkı alan kullanıcı, sadece JSON istek gönderir ve sonuç olarak ya JSON ya da XML formatında cevap alabilir. Format istekteki adresin uzantısına students.json|.xml
bakılarak karar verilir. Eğer uzantı belirtilmemişse, varsayılan olarak JSON kullanılır.
security:
encoders:
Api\SchoolBundle\Entity\User:
algorithm: bcrypt
cost: 12
role_hierarchy:
ROLE_STUDENT: ROLE_USER
ROLE_LECTURER: ROLE_USER
ROLE_ADMIN: ROLE_USER
providers:
user:
entity:
class: ApiSchoolBundle:User
property: username
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
secured:
pattern: ^/.*
stateless: true
http_basic:
realm: "School API"
provider: user
api_school:
resource: "@ApiSchoolBundle/Controller/"
prefix: /1/
type: annotation
namespace Api\SchoolBundle\Controller;
use Api\SchoolBundle\Util\ApiUser;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
/**
* @Route("/students", service="api_school.controller.student")
*/
class StudentController
{
private $apiUser;
public function __construct(ApiUser $apiUser)
{
$this->apiUser = $apiUser;
}
/**
* @param string $format
*
* @Security("has_role('ROLE_USER')")
* @Method({"GET"})
* @Route(".{format}", requirements={"format"="json|xml"}, defaults={"format"="json"})
*
* @return Response
*/
public function getAllAction($format)
{
$user = $this->apiUser->get();
return new Response(json_encode(['roles' => $user->getRoles(), 'response' => $format]));
}
/**
* @param string $format
* @param Request $request
*
* @Security("has_role('ROLE_ADMIN')")
* @Method({"POST"})
* @Route(".{format}", requirements={"format"="json|xml"}, defaults={"format"="json"})
*
* @return Response
*/
public function createOneAction(Request $request, $format)
{
$user = $this->apiUser->get();
return new Response(json_encode(['roles' => $user->getRoles(), 'response' => $format]));
}
}
namespace Api\SchoolBundle\Controller;
use Api\SchoolBundle\Util\ApiUser;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
/**
* @Route("/lecturers", service="api_school.controller.lecturer")
*/
class LecturerController
{
private $apiUser;
public function __construct(ApiUser $apiUser)
{
$this->apiUser = $apiUser;
}
/**
* @param string $format
*
* @Security("has_role('ROLE_LECTURER')")
* @Method({"GET"})
* @Route(".{format}", requirements={"format"="json|xml"}, defaults={"format"="json"})
*
* @return Response
*/
public function getAllAction($format)
{
$user = $this->apiUser->get();
return new Response(json_encode(['roles' => $user->getRoles(), 'response' => $format]));
}
/**
* @param string $format
* @param Request $request
*
* @Security("has_role('ROLE_ADMIN')")
* @Method({"POST"})
* @Route(".{format}", requirements={"format"="json|xml"}, defaults={"format"="json"})
*
* @return Response
*/
public function createOneAction(Request $request, $format)
{
$user = $this->apiUser->get();
return new Response(json_encode(['roles' => $user->getRoles(), 'response' => $format]));
}
}
namespace Api\SchoolBundle\Controller;
use Api\SchoolBundle\Util\ApiUser;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
/**
* @Route("/admins", service="api_school.controller.admin")
*/
class AdminController
{
private $apiUser;
public function __construct(ApiUser $apiUser)
{
$this->apiUser = $apiUser;
}
/**
* @param string $format
*
* @Security("has_role('ROLE_ADMIN')")
* @Method({"GET"})
* @Route(".{format}", requirements={"format"="json|xml"}, defaults={"format"="json"})
*
* @return Response
*/
public function getAllAction($format)
{
$user = $this->apiUser->get();
return new Response(json_encode(['roles' => $user->getRoles(), 'response' => $format]));
}
/**
* @param string $format
* @param Request $request
*
* @Security("has_role('ROLE_ADMIN')")
* @Method({"POST"})
* @Route(".{format}", requirements={"format"="json|xml"}, defaults={"format"="json"})
*
* @return Response
*/
public function createOneAction(Request $request, $format)
{
$user = $this->apiUser->get();
return new Response(json_encode(['roles' => $user->getRoles(), 'response' => $format]));
}
}
services:
api_school.controller.student:
class: Api\SchoolBundle\Controller\StudentController
arguments:
- "@api_school.util.api_user"
api_school.controller.lecturer:
class: Api\SchoolBundle\Controller\LecturerController
arguments:
- "@api_school.util.api_user"
api_school.controller.admin:
class: Api\SchoolBundle\Controller\AdminController
arguments:
- "@api_school.util.api_user"
namespace Api\SchoolBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Serializable;
use Symfony\Component\Security\Core\User\UserInterface;
/**
* @ORM\Table(name="user",
* uniqueConstraints={
* @ORM\UniqueConstraint(name="username_unq", columns={"username"}),
* @ORM\UniqueConstraint(name="email_unq", columns={"email"})
* }
* )
* @ORM\Entity(repositoryClass="Api\SchoolBundle\Repository\UserRepository")
*/
class User implements UserInterface, Serializable
{
/**
* @ORM\Column(type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @ORM\Column(name="username", type="string", length=100)
*/
private $username;
/**
* @ORM\Column(name="password", type="string", length=100)
*/
private $password;
/**
* @ORM\Column(name="email", type="string", length=100)
*/
private $email;
/**
* @ORM\Column(name="roles", type="array")
*/
private $roles;
/**
* @ORM\Column(name="is_active", type="boolean")
*/
private $isActive = true;
/**
* @return integer
*/
public function getId()
{
return $this->id;
}
public function getUsername()
{
return $this->username;
}
public function setUsername($username)
{
$this->username = $username;
return $this;
}
public function getPassword()
{
return $this->password;
}
public function setPassword($password)
{
$this->password = $password;
return $this;
}
public function getEmail()
{
return $this->email;
}
public function setEmail($email)
{
$this->email = $email;
return $this;
}
public function getIsActive()
{
return $this->isActive;
}
public function setIsActive($isActive)
{
$this->isActive = $isActive;
return $this;
}
public function getRoles()
{
return $this->roles;
}
public function setRoles(array $roles)
{
return $this->roles = $roles;
}
public function getSalt()
{
return null;
}
public function eraseCredentials()
{
}
public function serialize()
{
return serialize([$this->id, $this->username, $this->password]);
}
public function unserialize($serialized)
{
list ($this->id, $this->username, $this->password) = unserialize($serialized);
}
}
Veritabanındaki görüntü aşağıdaki gibidir.
CREATE TABLE IF NOT EXISTS `user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(100) COLLATE utf8_unicode_ci NOT NULL,
`password` varchar(100) COLLATE utf8_unicode_ci NOT NULL,
`email` varchar(100) COLLATE utf8_unicode_ci NOT NULL,
`is_active` tinyint(1) NOT NULL,
`roles` longtext COLLATE utf8_unicode_ci NOT NULL COMMENT '(DC2Type:array)',
PRIMARY KEY (`id`),
UNIQUE KEY `username_unq` (`username`),
UNIQUE KEY `email_unq` (`email`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=1 ;
namespace Api\SchoolBundle\Repository;
use Doctrine\ORM\EntityRepository;
class UserRepository extends EntityRepository
{
}
services:
api_school.repository.user:
class: Api\SchoolBundle\Repository\UserRepository
factory: ["@doctrine.orm.entity_manager", "getRepository"]
arguments:
- Api\SchoolBundle\Entity\User
API'ye gönderilen her istek için aşağıdaki sorgu çalıştırılır. Eğer sadece username
alanı değilde, onun haricinde farklı alanlar da kullanmak isterseniz, kendi sorgunuzu oluşturmanız gerekecektir. Daha fazla bilgi için Using a Custom Query to Load the User adresini ziyaret edin.
SELECT id, username, password, email, roles, is_active FROM user WHERE username = ? LIMIT 1 ["admin"] []
namespace Api\SchoolBundle\Util;
use Api\SchoolBundle\Entity\User;
use Api\SchoolBundle\Exception\ApiException;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
class ApiUser
{
private $tokenStorage;
public function __construct(
TokenStorageInterface $tokenStorage
) {
$this->tokenStorage = $tokenStorage;
}
/**
* @return User
*/
public function get()
{
$user = $this->tokenStorage->getToken()->getUser();
if (!$user instanceof User) {
throw new ApiException('API user cannot be found.');
}
return $user;
}
}
services:
api_school.util.api_user:
class: Api\SchoolBundle\Util\ApiUser
arguments:
- "@security.token_storage"
This is the command we use to create users.
namespace Api\SchoolBundle\Command;
use Api\SchoolBundle\Entity\User;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
class CreateUserCommand extends Command
{
private $entityManager;
private $userPasswordEncoder;
public function __construct(
EntityManagerInterface $entityManager,
UserPasswordEncoderInterface $userPasswordEncoder
) {
parent::__construct();
$this->entityManager = $entityManager;
$this->userPasswordEncoder = $userPasswordEncoder;
}
protected function configure()
{
$this
->setName('school:create-user')
->addOption(
'username',
null,
InputOption::VALUE_REQUIRED,
'The username of the user.'
)
->addOption(
'email',
null,
InputOption::VALUE_REQUIRED,
'The email of the user.'
)
->addOption(
'roles',
null,
InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY,
'The roles of the user.'
);
}
protected function execute(InputInterface $input, OutputInterface $output)
{
$password = bin2hex(random_bytes(16));
$this->createUser($input, $password);
$this->outputCredentials($output, $input->getOption('username'), $password);
}
private function createUser(InputInterface $input, $password)
{
$user = new User();
$user->setUsername($input->getOption('username'));
$user->setEmail($input->getOption('email'));
$user->setRoles($input->getOption('roles'));
$password = $this->userPasswordEncoder->encodePassword($user, $password);
$user->setPassword($password);
$this->entityManager->persist($user);
$this->entityManager->flush();
}
private function outputCredentials(OutputInterface $output, $username, $password)
{
$output->writeln(PHP_EOL.'CREDENTIALS');
$output->writeln('-----------');
$output->writeln('Username: '.$username);
$output->writeln('Password: '.$password.PHP_EOL);
}
}
services:
api_school.command.create_user:
class: Api\SchoolBundle\Command\CreateUserCommand
arguments:
- "@doctrine.orm.entity_manager"
- "@security.password_encoder"
tags:
- { name: console.command }
Kullanıcılarımızı yaratalım.
$ app/console school:create-user --username="student" --email="s@s.com" --roles="ROLE_USER" --roles="ROLE_STUDENT"
CREDENTIALS
-----------
Username: student
Password: 7bac6226bc57bed59559853cc2769f0a
$ app/console school:create-user --username="lecturer" --email="l@l.com" --roles="ROLE_USER" --roles="ROLE_LECTURER"
CREDENTIALS
-----------
Username: lecturer
Password: 68e31a9c7f47de3f1bd95d04f19dd935
$ app/console school:create-user --username="admin" --email="a@a.com" --roles="ROLE_USER" --roles="ROLE_STUDENT" --roles="ROLE_LECTURER" --roles="ROLE_ADMIN"
CREDENTIALS
-----------
Username: admin
Password: 52bb7533ef8bcd523ca7dc09d6c8cd3d
İsterseniz yukarıdaki kullanıcı adı ve şifrelerini kullanırsınız, isterseniz de Authorization
kafa ekini kullanabilirsiniz. Aşağıdaki ekleri kontrol edebilirsiniz.
curl -v -X GET -u "student:7bac6226bc57bed59559853cc2769f0a" "http://192.168.50.10:8083/app_dev.php/1/students.xml"
curl -v -X GET -H "Authorization: Basic c3R1ZGVudDo3YmFjNjIyNmJjNTdiZWQ1OTU1OTg1M2NjMjc2OWYwYQ==" "http://192.168.50.10:8083/app_dev.php/1/students.xml"
curl -v -X POST -u "admin:52bb7533ef8bcd523ca7dc09d6c8cd3d" -H "Content-Type: application/json" -d '{"key_1": "value", "key_1": "value"}' "http://192.168.50.10:8083/app_dev.php/1/students.xml"
curl -v -X POST -H "Authorization: Basic YWRtaW46NTJiYjc1MzNlZjhiY2Q1MjNjYTdkYzA5ZDZjOGNkM2Q=" "Content-Type: application/json" -d '{"key_1": "value", "key_1": "value"}' "http://192.168.50.10:8083/app_dev.php/1/students.xml"