在我的应用程序中,我在 routes.php 文件中定义了 before()
挂钩:
$app->before(function(Request $request) use($app) {
$authAnon = $app['security']->isGranted('IS_AUTHENTICATED_ANONYMOUSLY');
if(!$request->getSession()->get('username') && $authAnon) {
if($request->isXmlHttpRequest()) {
// return 401/HTTP_UNAUTHORIZED response
$response = new Response();
$response->setStatusCode(Response::HTTP_UNAUTHORIZED);
$response->headers->set('Reason', 'SESSION_EXPIRED');
$response->headers->set('WWW-Authenticate', 'MyAuthScheme realm="app:login"');
return $response;
}
return new RedirectResponse('login', 301);
}
}
但这会导致 $app['security']
无法找到/定义:
Container.php第96行中的InvalidArgumentException :未定义标识符“security”。
我的安全设置如下所示:
$app->register(new Silex\Provider\SecurityServiceProvider(), array(
'security.firewalls' => array(
'login' => array(
'pattern' => '^/login$',
),
'secured' => array(
'pattern' => '^.*$',
'form' => array('login_path' => '/login', 'check_path' => '/login_check'),
'logout' => array('logout_path' => '/logout', 'invalidate_session' => true),
'users' => array(
'admin' => array('ROLE_ADMIN', 'hashed_pwd'),
'user' => array('ROLE_USER', 'hashed_pwd'),
),
),
)
));
$app['security.role_hierarchy'] = array(
'ROLE_ADMIN' => array('ROLE_USER'),
);
$app['security.access_rules'] = array(
array('^/admin', 'ROLE_ADMIN'),
array('^.*$', ['ROLE_USER']),
);
会话的顺序&安全提供商的注册情况如下:
$config_path = __DIR__.'/../app/config/';
require_once $config_path.'session.php';
require_once $config_path.'security.php';
require_once $config_path.'routes/routes.php';
$app->run();
我做错了什么?
修改
请看下面的答案,看看我最终得到了什么。
答案 0 :(得分:1)
{@ 1}}服务已弃用,将从Silex 2.0中删除。如果要检查用户的角色,则需要security
服务。
security.authorization_checker
由于您使用的是$authAnon = $app['security.authorization_checker']->isGranted('IS_AUTHENTICATED_ANONYMOUSLY');
(不稳定)版本,因此您需要注意这些事情,或者使用稳定版本。
答案 1 :(得分:1)
我的猜测是您现在正在使用Symfony安全组件的版本> = 2.6+,因此根据Silex docs,您无法直接使用服务安全性(如在$app['security']
),您必须使用授权检查程序服务($app['security.authorization_checker']
):
<?php
$app->before(function(Request $request) use($app) {
// This won't work with Symfony Security Component < 2.6
// $authAnon = $app['security']->isGranted('IS_AUTHENTICATED_ANONYMOUSLY');
// Under Symfony 2.6+
$authAnon = $app['security.authorization_checker']->isGranted('IS_AUTHENTICATED_ANONYMOUSLY');
// ...
}
答案 2 :(得分:0)
这是我最终想出的:
if($request->headers->has('XHR-Request')) {
$isAuthFully = $app['security.authorization_checker']->isGranted('IS_AUTHENTICATED_FULLY');
if(!$isAuthFully and $request->get('_route') !== 'login') {
$response = new Response();
$response->setStatusCode(Response::HTTP_UNAUTHORIZED);
$response->headers->set('Login-Redirect', '');
$response->headers->set('WWW-Authenticate', 'AppAuthScheme realm="application:login"');
return $response;
}
}
我在客户端添加了自定义XHR-Request
标头:
angular.module('documentsCatalogApp', []).config(httpConfig);
httpConfig.$inject = ['$httpProvider'];
function httpConfig($httpProvider) {
$httpProvider.defaults.headers.common['XHR-Request'] = '';
}
Symfony的 getRequest()->isXmlHttpRequest()
依赖于 X-Requested-With
标头,可能会被浏览器删除,至少我看过关于 Firefox 的报告。
然后我添加了拦截器:
// mount the config / interceptor to your Angular application
// .config(xhrLoginRedirectInterceptorConfig)
// .factory('xhrLoginRedirectInterceptor', xhrLoginRedirectInterceptor)
xhrLoginRedirectInterceptorConfig.$inject = ['$httpProvider'];
function xhrLoginRedirectInterceptorConfig($httpProvider) {
$httpProvider.interceptors.push('xhrLoginRedirectInterceptor');
}
xhrLoginRedirectInterceptor.$inject = ['$q', '$window'];
function xhrLoginRedirectInterceptor($q, $window) {
return {
request: function(request) { return request; },
response: function(response) { return response; },
responseError: function(response) {
var headersList = response.headers();
var loginRequired = headersList && headersList.hasOwnProperty('Login-Redirect');
if(response.status === 401 && loginRequired) {
var url = "http://" + $window.location.host + baseUrl + "/login";
$window.location.href = url;
}
return $q.reject(response);
}
}
}
<强>参考强>