説明が皆無なのでかなり不親切です。超絶自分用まとめ。もしくはある程度解る人用。
「/」以下をフロント、「/admin」以下を管理画面(要ログイン)とする、よくあるアプリケーションの構築テンプレート。
□□サーバーサイド
■SecurityController.php
namespace Hoge\FugaBundle\Controller; use Symfony\Bundle\FrameworkBundle\Controller\Controller; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; use Symfony\Component\Security\Core\Exception\AccessDeniedException; use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken; use Symfony\Component\Security\Core\Authentication\Token\AnonymousToken; use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method; use Hoge\FugaBundle\Entity\User; /** * @Route("api") */ class SecurityController extends Controller { protected function getUserManager() { return $this->get('fos_user.user_manager'); } protected function loginUser(User $user) { $security = $this->get('security.context'); $providerKey = $this->container->getParameter('fos_user.firewall_name'); $roles = $user->getRoles(); $token = new UsernamePasswordToken($user, null, $providerKey, $roles); $security->setToken($token); } protected function logoutUser() { $security = $this->get('security.context'); $token = new AnonymousToken(null, new User()); $security->setToken($token); $this->get('session')->invalidate(); } protected function checkUser() { $security = $this->get('security.context'); if ($token = $security->getToken()) { $user = $token->getUser(); if ($user instanceof User) { return $user; } } return false; } protected function checkUserPassword(User $user, $password) { $factory = $this->get('security.encoder_factory'); $encoder = $factory->getEncoder($user); if(!$encoder){ return false; } return $encoder->isPasswordValid($user->getPassword(), $password, $user->getSalt()); } /** * @Route("/login.{_format}", name="hoge_fuga_admin_api_security_login", defaults={"_format" = "json"}) * @Method("POST") */ public function loginAction() { $request = $this->getRequest(); $username = $request->get('username'); $password = $request->get('password'); $um = $this->getUserManager(); $user = $um->findUserByUsername($username); if(!$user){ $user = $um->findUserByEmail($username); } if(!$user instanceof User){ throw new NotFoundHttpException('ユーザーIDが存在しません'); } if(!$this->checkUserPassword($user, $password)){ throw new AccessDeniedException('パスワードが不正です'); } $this->loginUser($user); return [ 'success' => true, 'user' => $user ]; } /** * @Route("/logout.{_format}", name="hoge_fuga_admin_api_security_logout", defaults={"_format" = "json"}) * @Method("POST") */ public function logoutAction() { $this->logoutUser(); return [ 'success' => true ]; } /** * @Route("/loginCheck.{_format}", name="hoge_fuga_admin_api_security_login_check", defaults={"_format" = "json"}) * @Method("POST") */ public function loginCheckAction() { if ($user = $this->checkUser()) { return [ 'success' => true, 'user' => $user ]; } else { throw new AccessDeniedException(); } } }
■app/config/config.yml
fos_user: db_driver: orm firewall_name: admin_area user_class: Hoge\FugaBundle\Entity\User fos_rest: view: view_response_listener: force force_redirects: html: true formats: jsonp: true json: true xml: true rss: false failed_validation: HTTP_BAD_REQUEST default_engine: twig
■app/config/security.yml
security: encoders: Symfony\Component\Security\Core\User\User: plaintext FOS\UserBundle\Model\UserInterface: sha512 role_hierarchy: ROLE_ADMIN: ROLE_USER ROLE_SUPER_ADMIN: [ ROLE_USER, ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH ] providers: in_memory: memory: users: user: { password: userpass, roles: [ 'ROLE_USER' ] } admin: { password: adminpass, roles: [ 'ROLE_ADMIN' ] } fos_userbundle: id: fos_user.user_provider.username_email firewalls: dev: pattern: ^/(_(profiler|wdt)|css|images|js)/ security: false admin_area: pattern: ^/admin anonymous: ~ form_login: login_path: /admin/login check_path: /admin/login_check access_control: - { path: ^/admin/login$, roles: IS_AUTHENTICATED_ANONYMOUSLY } - { path: ^/admin/api/login.*$, roles: IS_AUTHENTICATED_ANONYMOUSLY } - { path: ^/admin, roles: [ ROLE_ADMIN ] }
■app/config/routing.yml
※FOSUserBundleのインストールに必要
fos_user: resource: "@FOSUserBundle/Resources/config/routing/all.xml"
■src/Hoge/FugaBundle/Resources/config/routing.yml
hoge_fuga_admin_index: resource: "@HogeFugaBundle/Controller/DefaultController.php" type: annotation prefix: /admin hoge_fuga_admin_security: resource: "@HogeFugaBundle/Controller/SecurityController.php" type: annotation prefix: /admin
■DefaultController.php
namespace Hoge\FugaBundle\Controller; use Symfony\Bundle\FrameworkBundle\Controller\Controller; use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method; class DefaultController extends Controller { /** * @Route("") * @Route("/{_all}", name="affiliate_cms_admin_index_all", requirements={"_all" = "^(?!.*(api)).*$"}) * @Method("GET") */ public function indexAction() { return $this->render('HogeFugaBundle:Default:index.html.twig'); } }
「api」を含まないURLを全てDefaultControllerのIndexActionで拾い、あとはAngularのルーターに任せる。
□□フロントサイド
■adminLoginController.js(ログイン画面で用いるコントローラー)
void function() { var adminLoginController = function(securityResource, $state, UserService) { var that = this; this.data = {}; this.loginFailure = false; this.login = function() { securityResource.save({action: 'login.json'}, { username: that.data.username, password: that.data.password }, function(response) { UserService.setUser(response.user); $state.go('admin.main.dashboard'); }, function(response) { if (response.status >= 400) { that.loginFailure = true; } }); } } angular .module('hogeControllers') .controller('adminLoginController', ['securityResource', '$state', 'UserService', adminLoginController]) ; }();
■adminController.js(ログイン画面を含むログイン後の全てのコントローラーが継承している基底コントローラー)
void function() { var adminController = function(securityResource, $state, UserService) { this.user = null; var that = this; this.logout = function() { securityResource.save({action: 'logout.json'}, {}, function() { UserService.clear(); $state.go('admin.login'); }); } this.initUser = function() { that.user = UserService.getUser(); if (!that.user) { securityResource.save({action: 'loginCheck.json'}, {}, function(response) { that.user = response.user; }, function() { UserService.clear(); $state.go('admin.login'); }); } } } angular .module('hogeControllers') .controller('adminController', ['securityResource', '$state', 'UserService', adminController]) ; }();
■SecurityResource.js
void function() { angular .module('hogeResources') .factory('securityResource', ['$resource', function($resource) { return $resource('/admin/api/:action', { action: '@action', }, { } )}]) ; }();
■UserService.js
void function() { var UserService = function() { this.user = null; this.getUser = function() { return this.user; } this.setUser = function(user) { this.user = user; } this.clear = function() { this.user = null; } } angular .module('hogeServices') .service('UserService', [UserService]) ; }();
■app.js
void function() { angular.module('hogeApp', [ // コア 'ngAnimate', 'ngResource', 'ngSanitize', 'ngTouch', // 必要に応じて 'ui', 'ui.utils', 'ui.router', 'ui.bootstrap', 'ui.bootstrap.datetimepicker', 'kendo.directives', 'ngCookies', 'angular-loading-bar', 'angularFileUpload', 'cgNotify', // 自分のやつら 'hogeConstants', 'hogeControllers', 'hogeDirectives', 'hogeFactories', 'hogeFilters', 'hogeResources', 'hogeServices' ]); angular.module('hogeConstants', []); angular.module('hogeControllers', []); angular.module('hogeDirectives', []); angular.module('hogeFactories', []); angular.module('hogeFilters', []); angular.module('hogeResources', []); angular.module('hogeServices', []); /** * config section */ angular .module('hogeApp') .config(['$urlRouterProvider', '$stateProvider', '$locationProvider', function($urlRouterProvider, $stateProvider, $locationProvider) { $stateProvider /** * admin */ .state('admin', { url: '/admin', views: { main: { templateUrl: '/admin.html', controller: 'adminController', controllerAs: 'admin' } } }) /** * admin login */ .state('admin.login', { url: '/login', views: { main: { templateUrl: '/login.html', controller: 'adminLoginController', controllerAs: 'adminLogin' } } }) /** * admin main (base template) */ .state('admin.main', { url: '/', views: { main: { templateUrl: '/main.html', controller: 'adminMainController', controllerAs: 'adminMain' } } }) /** * admin main dashboard */ .state('admin.main.dashboard', { url: 'dashboard', views: { main: { templateUrl: '/dashboard/index.html', controller: 'adminMainDashboardController', controllerAs: 'adminMainDashboard' } } }) ; $urlRouterProvider.otherwise('/admin/dashboard'); $locationProvider.html5Mode(true).hashPrefix('!'); }]); }();
こんな感じでベースが完成。
めでたしめでたし。