使用表單登錄來(lái)處理 Symfony 的驗(yàn)證是一件非常常見(jiàn)并且靈活的方法。幾乎表單登錄的每個(gè)方面都可以進(jìn)行自定義,所有的默認(rèn)配置都將在下一節(jié)中進(jìn)行介紹。
如果想要查看完整表單登錄參考配置,請(qǐng)參考 [SecurityBundle 配置 ("安全")]( http://symfony.com/doc/current/reference/configuration/security.html)。如下列舉了一些更有趣的解釋選項(xiàng)。
當(dāng)使用不同的配置選項(xiàng)登錄成功以后,您就可以改變重定向的登錄表單。在默認(rèn)的情況下,表單會(huì)重定向到用戶(hù)請(qǐng)求的 URL(即觸發(fā)顯示登錄窗體的 URL)。比如,如果用戶(hù)請(qǐng)求 http://www.example.com/admin/post/18/edit,當(dāng)用戶(hù)成功的登錄以后,頁(yè)面最終會(huì)重定向到 http://www.example.com/admin/post/18。這是通過(guò)把用戶(hù)請(qǐng)求的頁(yè)面存儲(chǔ)到 session 實(shí)現(xiàn)的。如果 session 中沒(méi)有存儲(chǔ)一個(gè) URL(比如用戶(hù)直接訪(fǎng)問(wèn)的登錄頁(yè)),那么當(dāng)用戶(hù)成功登錄以后,系統(tǒng)就會(huì)給用戶(hù)展示默認(rèn)頁(yè)。你可以通過(guò)很多種方式來(lái)改變這種模式。
就像前面提到的,在默認(rèn)情況下,顯示的頁(yè)面將會(huì)被重定向到用戶(hù)最初請(qǐng)求的頁(yè)面。有時(shí)候,也會(huì)出現(xiàn)一些問(wèn)題,就像后臺(tái)的 Ajax 請(qǐng)求“看起來(lái)”像是最后訪(fǎng)問(wèn)的 URL,導(dǎo)致用戶(hù)訪(fǎng)問(wèn)的頁(yè)面被重定向到這里,有關(guān)控制此行為的信息,請(qǐng)參閱如何更改默認(rèn)目標(biāo)路徑。
首先,默認(rèn)頁(yè)是可以設(shè)置的(即如果沒(méi)有在 session 中存儲(chǔ)以前的頁(yè)面路徑,就會(huì)將頁(yè)面重定向到默認(rèn)的頁(yè)面)。請(qǐng)使用以下配置來(lái)設(shè)置 default_security_target(默認(rèn)安全目標(biāo)) 路徑:
YAML:
# app/config/security.yml
security:
firewalls:
main:
form_login:
# ...
default_target_path: default_security_target
XML:
<!-- app/config/security.xml -->
<config>
<firewall>
<form-login
default_target_path="default_security_target"
/>
</firewall>
</config>
PHP:
// app/config/security.php
$container->loadFromExtension('security', array(
'firewalls' => array(
'main' => array(
// ...
'form_login' => array(
// ...
'default_target_path' => 'default_security_target',
),
),
),
));
現(xiàn)在,當(dāng) session 中沒(méi)有存儲(chǔ) URL,用戶(hù)所瀏覽的頁(yè)面將會(huì)轉(zhuǎn)到 default_security_target 中的路徑。
您可以通過(guò)設(shè)置 always_use_default_target_path 選項(xiàng)的值設(shè)定為真,這樣的話(huà),不管用戶(hù)請(qǐng)求了什么 URL ,其訪(fǎng)問(wèn)的頁(yè)面最終都會(huì)被重定向到默認(rèn)頁(yè)。
YAML:
# app/config/security.yml
security:
firewalls:
main:
form_login:
# ...
always_use_default_target_path: true
XML:
<!-- app/config/security.xml -->
<config>
<firewall>
<form-login
always_use_default_target_path="true"
/>
</firewall>
</config>
PHP:
// app/config/security.php
$container->loadFromExtension('security', array(
'firewalls' => array(
'main' => array(
// ...
'form_login' => array(
// ...
'always_use_default_target_path' => true,
),
),
),
));
為了防止以前的 URL 沒(méi)有被存儲(chǔ)在 session 中,您不妨試試改用 HTTP_REFERER 屬性,因?yàn)檫@往往會(huì)達(dá)到相同的效果。您可以通過(guò)把 setting use_referer 屬性的值改為 true(默認(rèn)是false):
YAML:
# app/config/security.yml
security:
firewalls:
main:
form_login:
# ...
use_referer: true
XML:
<!-- app/config/security.xml -->
<config>
<firewall>
<form-login
use_referer="true"
/>
</firewall>
</config>
PHP:
// app/config/security.php
$container->loadFromExtension('security', array(
'firewalls' => array(
'main' => array(
// ...
'form_login' => array(
// ...
'use_referer' => true,
),
),
),
));
您還可以通過(guò)包含一個(gè)名叫 _target_path 的隱藏字段來(lái)重寫(xiě)用戶(hù)通過(guò)表單本身重定向的 URL。例如,可以通過(guò)以下的程序來(lái)重定向到一些賬戶(hù)路由定義的 URL:
Twig:
{# src/Acme/SecurityBundle/Resources/views/Security/login.html.twig #}
{% if error %}
<div>{{ error.message }}</div>
{% endif %}
<form action="{{ path('login_check') }}" method="post">
<label for="username">Username:</label>
<input type="text" id="username" name="_username" value="{{ last_username }}" />
<label for="password">Password:</label>
<input type="password" id="password" name="_password" />
<input type="hidden" name="_target_path" value="account" />
<input type="submit" name="login" />
</form>
PHP:
<!-- src/Acme/SecurityBundle/Resources/views/Security/login.html.php -->
<?php if ($error): ?>
<div><?php echo $error->getMessage() ?></div>
<?php endif ?>
<form action="<?php echo $view['router']->generate('login_check') ?>" method="post">
<label for="username">Username:</label>
<input type="text" id="username" name="_username" value="<?php echo $last_username ?>" />
<label for="password">Password:</label>
<input type="password" id="password" name="_password" />
<input type="hidden" name="_target_path" value="account" />
<input type="submit" name="login" />
</form>
現(xiàn)在,用戶(hù)訪(fǎng)問(wèn)頁(yè)面將會(huì)被重定向到隱藏表單字段的值。這個(gè)值的屬性可以是相對(duì)路徑,也可以是絕對(duì)的 URL 路徑,也可以是路由的名稱(chēng)。您甚至可以通過(guò)把 target_path_parameter 選項(xiàng)的值改為另一個(gè)值來(lái)更改隱藏表單字段的名稱(chēng)。
YAML:
# app/config/security.yml
security:
firewalls:
main:
form_login:
target_path_parameter: redirect_url
XML:
<!-- app/config/security.xml -->
<config>
<firewall>
<form-login
target_path_parameter="redirect_url"
/>
</firewall>
</config>
PHP:
// app/config/security.php
$container->loadFromExtension('security', array(
'firewalls' => array(
'main' => array(
'form_login' => array(
'target_path_parameter' => redirect_url,
),
),
),
));
除了可以將用戶(hù)成功登錄后的頁(yè)面進(jìn)行重定向,您也可以設(shè)置當(dāng)用戶(hù)登錄失敗后的重定向頁(yè)面(例如用戶(hù)提交了無(wú)效的用戶(hù)名或密碼) 。在默認(rèn)情況下,用戶(hù)訪(fǎng)問(wèn)的頁(yè)面會(huì)重定向到登錄表單頁(yè)面,您也可以通過(guò)修改下面的屬性來(lái)進(jìn)行改變路徑:
YAML:
# app/config/security.yml
security:
firewalls:
main:
form_login:
# ...
failure_path: login_failure
XML:
<!-- app/config/security.xml -->
<config>
<firewall>
<form-login
failure_path="login_failure"
/>
</firewall>
</config>
PHP:
// app/config/security.php
$container->loadFromExtension('security', array(
'firewalls' => array(
'main' => array(
// ...
'form_login' => array(
// ...
'failure_path' => 'login_failure',
),
),
),
));