我将Symfony2应用程序分为2个捆绑包:API为BackendBundle
,AngularJS为"客户端"为FrontendBundle
。一切都在防火墙下工作。
BackendBundle
有实体,处理API路由; FrontendBundle
具有Angular视图,路由等,并且只有一个带通配符的控制器:
class AngularController extends Controller {
/**
* @Route("/{route}", name="angular_index_all_unmatched_routes", requirements={"route" = ".*"})
* @Template("FrontendBundle::index.html.twig")
*/
public function angularIndexAction($route) {
return ['route' => $route];
}
}
FrontendBundle
路由被定义为app/config/routing.yml
中的最后一个资源,仅当任何其他路由未匹配时才会被调用。多亏了它,它可以处理Angular HTML5模式路由,如果它们可以直接访问(例如复制粘贴) - 并且它可以正常工作。
我想要做的是,定义防火墙和/或访问控制,以便匿名用户可以访问所有这些不匹配的路由(由AngularController::angularIndexAction()
处理)。
为什么?我想打开一些API路由(通过前端代理)以供非用户访问(例如通过电子邮件发送的确认网址,并向用户发送一些消息)。
我不想为每个匿名的用户编码访问控制列表" Angular"路线,我想只为API路线做。最后,那些不匹配的路由应该打开Angular的索引,该索引应该知道用户是否已登录(用于显示完整或简化的布局)并且应该处理Angular路由并显示某种类型的"访问被拒绝"请求失败的消息(有Symfony监听器和Angular的$provide
拦截器)。
有什么建议吗?
编辑:@Security
上的AngularController::angularIndexAction()
注释不起作用,它仍会重定向到防火墙入口点。
Edit2 :这是security.yml
firewalls:
unsecured:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
anonymous: true
secured:
pattern: '^.*$'
form_login:
login_path: /our-provider/login
check_path: /our-provider/callback/
anonymous: true
entry_point: our_provider.entry_point
access_control:
- { path: '^/our-provider/(login(/[a-zA-Z]+)?|logout|redirect|callback)', roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: '^/', roles: ROLE_USER }
我知道如果用户没有登录,{ path: '^/', roles: ROLE_USER }
会将所有路由重定向到登录页面。我认为它显而易见并且没有提到它。我想要的是强制ROLE_USER
用于匹配的路由,让IS_AUTHENTICATED_ANONYMOUSLY
用于那些无法匹配的路由,而不是明确定义每个前端" proxy-route"。在我的情况下,没有404 Symfony页面,因为一切都进入angular_index_all_unmatched_routes
路由,并且Angular路由定义决定是否有事情需要处理。
答案 0 :(得分:0)
我没有尝试过,我无法在security.yml
中开始猜测您现有的安全/路由设置,但我想您可以使用IS_AUTHENTICATED_ANONYMOUSLY
将该方法列入白名单。来自Symfony docs:
所有用户(甚至是匿名用户)都有此功能 - 这在将URL列入白名单以保证访问权限时非常有用 - 某些详细信息位于How Does the Security access_control Work?。
因此,例如,如果您使用@Security
注释,则可以执行类似(未测试)的操作:
class AngularController extends Controller {
/**
* @Route("/{route}", name="route", requirements={"route" = ".*"})
* @Template("FrontendBundle::index.html.twig")
* @Security("has_role('IS_AUTHENTICATED_ANONYMOUSLY')")
*/
public function angularIndexAction($route) {
return ['route' => $route];
}
}
有关@Security
注释here的更多信息。
希望这会有所帮助:)
修改强>
所有这一切,当你在access_control
security.yml
下定义/限制你的路线时,匹配过程在第一场比赛时停止。我假设您有一些角色限制路径,您应该明确定义 - 并将它们放在第一位,这样如果它们与流程停止匹配。
否则,您应该能够添加由角色IS_AUTHENTICATED_ANONYMOUSLY
强制执行的全能路由。由于路由的路径定义是正则表达式,因此^/
之类的内容应该捕获未明确定义的任何内容。只需确保在限制路径定义之后将其放置。
在这种情况下,您不需要@Security
注释。
修改2
我尝试使用干净的实例和HTTP BasicAuth来模拟这个,但我想要实现的是以下内容,我理解这与您的用例类似:
/
和/api/
的后端控制器并触发HTTP BasicAuth身份验证弹出窗口/{route}
的前端控制器,该控制器将匹配其他所有内容并进行匿名身份验证。我的firewall
和access_control
配置如下所示:
security:
encoders:
# encoder config here
providers:
# provider config here
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
secured:
anonymous: ~
http_basic: ~
access_control:
- { path: ^/$, roles: ROLE_USER }
- { path: ^/api/, roles: ROLE_USER }
- { path: ^/, roles: IS_AUTHENTICATED_ANONYMOUSLY }
访问控制路径是正则表达式,因此^/$
和^/
不一样。前者只与路线/
完全匹配。后者将匹配以/
开头的任何路线;例如:/home
,/products
,/contact
等。
实际上,后者将匹配并匿名验证/api
,但它不会与/api/
或/api/1
等匹配,因为这些已明确定义并限制为ROLE_USER
因此,一般的想法是明确地和(如果可能的话)与您想要限制的路线完全匹配,并首先声明这些路线。最后一个声明^/
应该公开抓住任何其他路线。