説明が皆無なのでかなり不親切です。超絶自分用まとめ。もしくはある程度解る人用。
「/」以下をフロント、「/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('!');
}]);
}();
こんな感じでベースが完成。
めでたしめでたし。