<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Symfony中文教程 &#187; AccessDeniedException</title>
	<atom:link href="http://www.newlifeclan.com/symfony/archives/tag/accessdeniedexception/feed" rel="self" type="application/rss+xml" />
	<link>http://www.newlifeclan.com/symfony</link>
	<description>站在巨人肩膀上的phpweb框架</description>
	<lastBuildDate>Fri, 12 Dec 2025 00:58:27 +0000</lastBuildDate>
	<language>zh-CN</language>
		<sy:updatePeriod>hourly</sy:updatePeriod>
		<sy:updateFrequency>1</sy:updateFrequency>
	<generator>https://wordpress.org/?v=4.0.38</generator>
	<item>
		<title>KU案例2之07拒绝访问：AccessDeniedException</title>
		<link>http://www.newlifeclan.com/symfony/archives/416</link>
		<comments>http://www.newlifeclan.com/symfony/archives/416#comments</comments>
		<pubDate>Mon, 06 Apr 2015 06:36:37 +0000</pubDate>
		<dc:creator><![CDATA[napoleon]]></dc:creator>
				<category><![CDATA[实战教程]]></category>
		<category><![CDATA[AccessDeniedException]]></category>

		<guid isPermaLink="false">http://www.newlifeclan.com/symfony/?p=416</guid>
		<description><![CDATA[<p>让我们的用户再次登录并访问/new。他有ROLE_USER角色，我们允许他进入。现在我们改变Security. [&#8230;]</p>
<p><a rel="nofollow" href="http://www.newlifeclan.com/symfony/archives/416">KU案例2之07拒绝访问：AccessDeniedException</a>，首发于<a rel="nofollow" href="http://www.newlifeclan.com/symfony">Symfony中文教程</a>。</p>
]]></description>
				<content:encoded><![CDATA[<p>让我们的用户再次登录并访问/new。他有ROLE_USER角色，我们允许他进入。现在我们改变Security.yml里的access_control里面的角色为ROLE_ADMIN并刷新页面：</p>
<p><span id="more-416"></span></p><pre class="crayon-plain-tag"># app/config/security.yml
security:
    # ...
    access_control:
        - { path: ^/new, roles: ROLE_ADMIN }
        # ...</pre><p>这个页面遭到了拒绝。这意味着我们的角色，不具备了访问权限。当然在symfony的生产环境，我们就可以自定义。下面我们将讨论如何自定义错误页面。</p>
<p>综上所述在Security.yml里的access_control是控制访问的最简单方法，但也是最不灵活的。将access_control还改回ROLE_USER并且注释他们。后面，我们从控制器来限制他们的访问：</p><pre class="crayon-plain-tag"># app/config/security.yml
security:
    # ...
    access_control:
        # - { path: ^/new, roles: ROLE_USER }
        # - { path: ^/create, roles: ROLE_USER }</pre><p></p>
<h2>从Controller中限制访问：AccessDeniedException</h2>
<p>找到EventController里的newAction。我们需要get这个“security context”，去获取这个服务。isGranted方法去检查现有用户是否有角色。</p>
<p>如何判断这个用户有ROLE_ADMIN角色可以使用如下代码：</p><pre class="crayon-plain-tag">// src/Yoda/EventBundle/Controller/EventController.php
// ...

public function newAction()
{
    $securityContext = $this-&gt;container-&gt;get('security.context');
    if (!$securityContext-&gt;isGranted('ROLE_ADMIN')) {
        // panic?
    }

    // ...
}</pre><p>如果这个用户没有ROLE_ADMIN，会抛出一个非常特别的异常：被称为<span class="pre"><a class="reference external" title="Symfony\Component\Security\Core\Exception\AccessDeniedException" href="http://api.symfony.com/2.4/Symfony/Component/Security/Core/Exception/AccessDeniedException.html">AccessDeniedException</a>。首先添加一个use声明，然后在if块中实例化这个异常。并添加一个消息，只有开发者才能够看到。</span></p><pre class="crayon-plain-tag">// src/Yoda/EventBundle/Controller/EventController.php
// ...

use Symfony\Component\Security\Core\Exception\AccessDeniedException;
// ...

public function newAction()
{
    $securityContext = $this-&gt;container-&gt;get('security.context');
    if (!$securityContext-&gt;isGranted('ROLE_ADMIN')) {
        throw new AccessDeniedException('Only an admin can do this!!!!')
    }

    // ...
}</pre><p>在symfony2.5或更高版本，有一种快捷方式，就是用事件createAccessDeniedException来替换之前的代码：</p><pre class="crayon-plain-tag">// src/Yoda/EventBundle/Controller/EventController.php
// ...

if (!$securityContext-&gt;isGranted('ROLE_ADMIN')) {
    // in Symfony 2.5
    throw $this-&gt;createAccessDeniedException('message!');
}</pre><p>现在刷新，可以看到一个拒绝访问的页面。但是如果用户有admin角色，他就能够继续看到一个正常的页面。</p>
<h2>AccessDeniedException异常：在security的特别类</h2>
<p>通常情况下，如果你抛出一个异常，他会变成一个500错误页面。但是AccessDeniedException异常就很特殊。首先，如果我们还没有登录时，它仍然会把我们重定向到登录页面。但是如果我们处于登录状态，它会显示拒绝访问的403页面。所以在这里我们就不用关心用户是否登录。</p>
<p>哦，security真的很难，但是现在，你已经很认真的了解了，几乎所有你需要的知识。现在你只需要关心真正的难点，例如这种情况，你需要创建一个自定义的认证系统时，需要通过一个api键，而不是一个登录表单来验证用户。在这种情况下，你需要阅读symfony2的cookbookd的<a href="http://symfony.com/doc/current/cookbook/security/api_key_authentication.html" target="_blank">How to Authenticate Users with API Keys</a>。这是symfony2.4的新功能，你可能在老的文章中无法发现它。</p>
<p>好，我们在控制器中创建一个名为enforceUserSecurity的私有函数并复制我们的安全检测代码到这个函数中：</p><pre class="crayon-plain-tag">private function enforceUserSecurity()
{
    $securityContext = $this-&gt;container-&gt;get('security.context');
    if (!$securityContext-&gt;isGranted('ROLE_USER')) {
        throw new AccessDeniedException('Need ROLE_USER!');
    }
}</pre><p>现在，我们在newAction, createAction, editAction, updateAction and deleteAction里面使用：</p><pre class="crayon-plain-tag">public function newAction()
{
    $this-&gt;enforceUserSecurity();

    // ...
}

public function createAction(Request $request)
{
    $this-&gt;enforceUserSecurity();

    // ...
}</pre><p>你可以看到，这种方式更加灵活，使用access_control很简单。你可以选择最适合你的方式来工作。</p>
<blockquote><p>提示：你也可以使用annotations的方式！请查看<em><span style="text-decoration: underline"><span style="color: #ff0000"><a class="reference external" style="color: #ff0000;text-decoration: underline" href="http://symfony.com/doc/current/bundles/SensioFrameworkExtraBundle/annotations/security.html">SensioFrameworkExtraBundle</a>。</span></span></em></p></blockquote>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p><a rel="nofollow" href="http://www.newlifeclan.com/symfony/archives/416">KU案例2之07拒绝访问：AccessDeniedException</a>，首发于<a rel="nofollow" href="http://www.newlifeclan.com/symfony">Symfony中文教程</a>。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.newlifeclan.com/symfony/archives/416/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
