Keselamatan


Sistem keselamatan Symfony sangat berkuasa, tetapi ia juga boleh mengelirukan apabila menyediakannya. Dalam bab besar ini, anda akan belajar cara menyediakan keselamatan aplikasi anda langkah demi langkah, daripada mengkonfigurasi tembok api (firewall) dan memuatkan pengguna, kepada menafikan akses dan mendapatkan objek pengguna. Bergantung pada keperluan anda, kadangkala melakukan persediaan awal boleh menyakitkan. Setelah selesai, bagaimanapun, sistem keselamatan Symfony adalah fleksibel dan (mudah-mudahan) menyeronokkan untuk digunakan.

Memandangkan banyak perkara yang perlu diperkatakan, bab ini disusun dalam beberapa bab utama:

  1. Memulakan tetapan security.yml (security.yml 的设置 (authentication/验证 );

  2. 拒绝访问你的程序 (authorization/授权 );

  3. 获取当前的User对象;

它们被细分为许多小块内容(但仍然令人着迷),像是 logging out加密用户密码

1)初始化security.yml的设置 (Authentication/验证) 

security系统在 app/config/security.yml 中进行配置。默认的配置是这样的:

PHP:// app/config/security.php$container->loadFromExtension('security', array(
    'providers' => array(
        'in_memory' => array(
            'memory' => null,
        ),
    ),
    'firewalls' => array(
        'dev' => array(
            'pattern'    => '^/(_(profiler|wdt)|css|images|js)/',
            'security'   => false,
        ),
        'default' => array(
            'anonymous'  => null,
        ),
    ),));
XML:<!-- app/config/security.xml --><?xml version="1.0" encoding="UTF-8"?><srv:container xmlns="http://Symfony.com/schema/dic/security"    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    xmlns:srv="http://Symfony.com/schema/dic/services"    xsi:schemaLocation="http://Symfony.com/schema/dic/services        http://Symfony.com/schema/dic/services/services-1.0.xsd">     <config>
        <provider name="in_memory">
            <memory />
        </provider>         <firewall name="dev"            pattern="^/(_(profiler|wdt)|css|images|js)/"            security="false" />         <firewall name="default">
            <anonymous />
        </firewall>
    </config></srv:container>
YAML:# app/config/security.ymlsecurity:
    providers:
        in_memory:
            memory: ~
    firewalls:
        dev:
            pattern: ^/(_(profiler|wdt)|css|images|js)/
            security: false
        default:
            anonymous: ~

firewalls 键是security配置的 核心dev 防火墙并不重要,它只是确保Symfony开发工具 - 也就是居于 /_profiler/_wdt 之下的那些URL将不会被你的security所阻止。

你也可以针对请求中的其他细节来匹配一个请求(如 host主机)。阅读 如何把防火墙限制在特定请求 以了解更多内容和例程。

所有其他的URL将被 default 防火墙中处理(没有 pattern 键意味着它可以匹配所有 URL)。你可以认为防火墙就是你的security系统,因此通常只有一个主力防火墙就变得有意义了。但这并 意味着每一个URL都需要验证 - anonymous 键可以搞定这个。事实上,如果你现在去首页,是可以访问的,并将看到你以 anon.pengesahan/pengesahan

);

11.pngNafikan akses kepada program anda (

keizinan/keizinan

); Orang ramai terpesona), seperti log keluar

dan menyulitkan kata laluan pengguna
.

1) Mulakan tetapan security.yml (Pengesahan/pengesahan)

sistem keselamatan dalam app Configure dalam /config/security.yml. Konfigurasi lalai adalah seperti ini:
PHP:// app/config/security.php$container->loadFromExtension('security', array(
    // ...
    'firewalls' => array(
        // ...
        'default' => array(
            'anonymous'  => null,
            'http_basic' => null,
        ),
    ),));
XML:<!-- app/config/security.xml --><?xml version="1.0" encoding="UTF-8"?><srv:container xmlns="http://Symfony.com/schema/dic/security"    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    xmlns:srv="http://Symfony.com/schema/dic/services"    xsi:schemaLocation="http://Symfony.com/schema/dic/services        http://Symfony.com/schema/dic/services/services-1.0.xsd">     <config>
        <!-- ... -->         <firewall name="default">
            <anonymous />
            <http-basic />
        </firewall>
    </config></srv:container>
YAML:# app/config/security.ymlsecurity:    # ...
    firewalls:        # ...
        default:
            anonymous: ~
            http_basic: ~
Kuncifirewall ialah konfigurasi keselamatan teras

. Tembok api dev tidak penting, ia hanya memastikan bahawa alat pembangunan Symfony - iaitu, URL di bawah /_profiler dan /_wdt tidak akan Disekat oleh keselamatan anda.
🎜🎜Anda juga boleh memadankan permintaan dengan butiran lain dalam permintaan (seperti hos). Baca Cara Mengehadkan Firewall kepada Permintaan Tertentu🎜 untuk mendapatkan maklumat lanjut dan contoh. 🎜🎜🎜🎜Semua URL lain akan dikendalikan oleh tembok api lalai (tiada kunci corak bermakna ia boleh sepadan dengan 🎜semua 🎜 ​​URL). Anda boleh menganggap firewall sebagai sistem keselamatan anda, jadi biasanya masuk akal untuk mempunyai hanya satu firewall utama. Tetapi ini tidak 🎜🎜 bermakna bahawa setiap URL perlu disahkan - kunci tanpa nama menguruskan perkara ini. Malah, jika anda pergi ke halaman utama sekarang, anda akan mempunyai akses dan akan melihat bahawa anda "disahkan" sebagai non.. Jangan tertipu dengan "Ya" di sebelah Disahkan, anda masih pengguna tanpa nama: 🎜🎜🎜🎜🎜 Kemudian anda akan belajar cara menafikan akses kepada URL atau pengawal tertentu (tindakan di dalamnya). 🎜🎜🎜🎜Keselamatan 🎜sangat🎜 boleh dikonfigurasikan, dan semua pilihan konfigurasi ditunjukkan dalam 🎜Rujukan Konfigurasi Keselamatan🎜, dengan beberapa arahan tambahan. 🎜🎜🎜

A) Konfigurasikan "cara membenarkan pengguna disahkan"

Tugas utama firewall adalah untuk mengkonfigurasi cara membenarkan pengguna anda disahkan. Adakah mereka memerlukan borang log masuk? Atau pengesahan asas HTTP? Atau token API? Atau semua di atas?

Mari mulakan dengan pengesahan asas HTTP (pop timbul lama). Untuk mengaktifkan ciri ini, tambah http_basic pada firewall: http_basic 到firewall下面:

// src/AppBundle/Controller/DefaultController.php
// ... use 
Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;use Symfony\Bundle\FrameworkBundle\Controller\Controller;use Symfony\Component\HttpFoundation\Response; class DefaultController extends Controller{
   /**
     * @Route("/admin")
     */
    public function adminAction()
    {
        return new Response('<html><body>Admin page!</body></html>');
    }}
PHP:// app/config/security.php$container->loadFromExtension('security', array(
    // ...
    'firewalls' => array(
        // ...
        'default' => array(
            // ...
        ),
    ),
   'access_control' => array(
       // require ROLE_ADMIN for /admin*
        array('path' => '^/admin', 'role' => 'ROLE_ADMIN'),
    ),));
XML:<!-- app/config/security.xml --><?xml version="1.0" encoding="UTF-8"?><srv:container xmlns="http://Symfony.com/schema/dic/security"    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    xmlns:srv="http://Symfony.com/schema/dic/services"    xsi:schemaLocation="http://Symfony.com/schema/dic/services        http://Symfony.com/schema/dic/services/services-1.0.xsd">     <config>
        <!-- ... -->         <firewall name="default">
            <!-- ... -->
        </firewall>         <!-- require ROLE_ADMIN for /admin* -->
        <rule path="^/admin" role="ROLE_ADMIN" />
    </config></srv:container>
真简单!要测试效果,你需要让用户登录并看到页面。为了让事情变的有趣,在 /admin 下创建一个新页面 。例如,如果你使用annotations,创建下例代码:
YAML:# app/config/security.ymlsecurity:    # ...
    firewalls:        # ...
        default:            # ...
    access_control:        # require ROLE_ADMIN for /admin*
        - { path: ^/admin, roles: ROLE_ADMIN }

接下来,在 security.yml 中添加一个 access_control 入口,以令用户必先登录方可访问URL:

PHP:// app/config/security.php$container->loadFromExtension('security', array(
    'providers' => array(
        'in_memory' => array(
            'memory' => array(
                'users' => array(
                    'ryan' => array(
                        'password' => 'ryanpass',
                        'roles' => 'ROLE_USER',
                    ),
                    'admin' => array(
                        'password' => 'kitten',
                        'roles' => 'ROLE_ADMIN',
                    ),
                ),
            ),
        ),
    ),
    // ...));
XML:<!-- app/config/security.xml --><?xml version="1.0" encoding="UTF-8"?><srv:container xmlns="http://Symfony.com/schema/dic/security"    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    xmlns:srv="http://Symfony.com/schema/dic/services"    xsi:schemaLocation="http://Symfony.com/schema/dic/services        http://Symfony.com/schema/dic/services/services-1.0.xsd">     <config>
        <provider name="in_memory">
            <memory>
                <user name="ryan" password="ryanpass" roles="ROLE_USER" />
                <user name="admin" password="kitten" roles="ROLE_ADMIN" />
            </memory>
        </provider>
        <!-- ... -->
    </config></srv:container>
YAML:# app/config/security.ymlsecurity:
    providers:
        in_memory:
            memory:
                users:
                    ryan:
                        password: ryanpass
                        roles: 'ROLE_USER'
                    admin:
                        password: kitten
                        roles: 'ROLE_ADMIN'    # ...

你将学到关于 ROLE_ADMIN 以及后面的 2) 拒绝访问, Roles和其他授权 小节中的“拒绝访问”等更多内容。

太好了,如果你去访问 /admin

PHP:// app/config/security.php$container->loadFromExtension('security', array(
    // ...     'encoders' => array(
        'Symfony\Component\Security\Core\User\User' => 'plaintext',
    ),
    // ...));
XML:<!-- app/config/security.xml --><?xml version="1.0" encoding="UTF-8"?><srv:container xmlns="http://Symfony.com/schema/dic/security"    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    xmlns:srv="http://Symfony.com/schema/dic/services"    xsi:schemaLocation="http://Symfony.com/schema/dic/services        http://Symfony.com/schema/dic/services/services-1.0.xsd">     <config>
        <!-- ... -->         <encoder class="Symfony\Component\Security\Core\User\User"            algorithm="plaintext" />
        <!-- ... -->
    </config></srv:container>
YAML:app/config/security.ymlsecurity:    # ...
    encoders:
        Symfony\Component\Security\Core\User\User: plaintext    # ...
Sangat mudah! Untuk menguji kesan, anda perlu meminta pengguna log masuk dan melihat halaman. Untuk menjadikan perkara menarik, buat halaman baharu di bawah /admin. Contohnya, jika anda menggunakan anotasi, buat kod berikut:

PHP:// app/config/security.php$container->loadFromExtension('security', array(
    // ...     'encoders' => array(
        'Symfony\Component\Security\Core\User\User' => array(
            'algorithm' => 'bcrypt',
            'cost' => 12,
        )
    ),
    // ...));

Seterusnya, tambahkan entri access_control dalam security.yml supaya pengguna mesti Log masuk pertama untuk mengakses URL:
222.png

XML:<!-- app/config/security.xml --><?xml version="1.0" encoding="UTF-8"?><srv:container xmlns="http://Symfony.com/schema/dic/security"    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    xmlns:srv="http://Symfony.com/schema/dic/services"    xsi:schemaLocation="http://Symfony.com/schema/dic/services        http://Symfony.com/schema/dic/services/services-1.0.xsd">     <config>        <!-- ... -->         <encoder class="Symfony\Component\Security\Core\User\User"            algorithm="bcrypt"            cost="12" />         <!-- ... -->    </config></srv:container>
YAML:# app/config/security.ymlsecurity:    # ...
    encoders:
        Symfony\Component\Security\Core\User\User:
            algorithm: bcrypt
            cost: 12
1

Anda akan belajar tentang ROLE_ADMIN dan 2) Akses Ditolak, Peranan dan Keizinan Lain
"Akses Ditolak" dan banyak lagi dalam bahagian tersebut.

Bagus, jika anda melawati /admin, anda akan melihat log masuk pop timbul untuk pengesahan Asas HTTP:

Tetapi, sebagai identiti apakah anda log masuk? Dari mana datangnya pengguna (maklumat)?
Nak guna bentuk tradisional? sangat bagus! Lihat

Cara membina borang log masuk tradisional. Apakah kaedah (pengesahan) lain yang disokong? Rujuk Rujukan Konfigurasi

atau
bina sendiri
. 🎜🎜🎜🎜🎜🎜Jika program anda melengkapkan log masuk melalui perkhidmatan pihak ketiga seperti Google, Facebook atau Twitter, sila rujuk kepada himpunan komuniti 🎜HWIOAuthBundle🎜. 🎜🎜🎜

B) Konfigurasikan "cara memuatkan pengguna"

Apabila anda memasukkan nama pengguna, Symfony akan memuatkan maklumat pengguna dari suatu tempat. Ini dipanggil "pembekal pengguna" dan menjadi tanggungjawab anda untuk mengkonfigurasinya. Symfony mempunyai cara terbina dalam untuk memuat pengguna daripada pangkalan data, tetapi ia juga mungkin untuk membuat pembekal pengguna anda sendiri.

Cara paling mudah (tetapi dengan banyak batasan) ialah mengkonfigurasi Symfony untuk memuatkan terus pengguna yang diprogramkan di dalamnya daripada fail security.yml. Ini dipanggil pembekal "dalam memori", tetapi lebih baik menganggapnya sebagai pembekal "dalam konfigurasi" security.yml 文件里直接加载写死在其中的用户。这被称为“in memory” provider,但把它观想为“in configuration” provider更合适些

$  php bin/console security:encode-password
PHP:// app/config/security.php$container->loadFromExtension('security', array(
    // ...     'providers' => array(
        'in_memory' => array(
            'memory' => array(
                'users' => array(
                    'ryan' => array(
                        'password' => 'a$LCY0MefVIEc3TYPHV9SNnuzOfyr2p/AXIGoQJEDs4am4JwhNz/jli',
                        'roles' => 'ROLE_USER',
                    ),
                    'admin' => array(
                        'password' => 'a$cyTWeE9kpq1PjqKFiWUZFuCRPwVyAZwm4XzMZ1qPUFl7/flCM3V0G',
                        'roles' => 'ROLE_ADMIN',
                    ),
                ),
            ),
        ),
    ),
    // ...));
XML:<!-- app/config/security.xml --><?xml version="1.0" encoding="UTF-8"?><srv:container xmlns="http://Symfony.com/schema/dic/security"    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    xmlns:srv="http://Symfony.com/schema/dic/services"    xsi:schemaLocation="http://Symfony.com/schema/dic/services        http://Symfony.com/schema/dic/services/services-1.0.xsd">     <config>
        <!-- ... -->         <provider name="in_memory">
            <memory>
                <user name="ryan" password="a$LCY0MefVIEc3TYPHV9SNnuzOfyr2p/AXIGoQJEDs4am4JwhNz/jli" roles="ROLE_USER" />
                <user name="admin" password="a$cyTWeE9kpq1PjqKFiWUZFuCRPwVyAZwm4XzMZ1qPUFl7/flCM3V0G" roles="ROLE_ADMIN" />
            </memory>
        </provider>
    </config></srv:container>

类似 firewalls,你可以拥有多个 providers ,但你几乎只需要一个。如果你确实 拥有多个,你可以在防火墙的 provider 键(如 provider:in_memory

YAML:# app/config/security.ymlsecurity:    # ...
    providers:
        in_memory:
            memory:
                users:
                    ryan:
                        password: a$LCY0MefVIEc3TYPHV9SNnuzOfyr2p/AXIGoQJEDs4am4JwhNz/jli
                        roles: 'ROLE_USER'
                    admin:
                        password: a$cyTWeE9kpq1PjqKFiWUZFuCRPwVyAZwm4XzMZ1qPUFl7/flCM3V0G
                        roles: 'ROLE_ADMIN'
PHP:// app/config/security.php$container->loadFromExtension('security', array(
    // ...     'firewalls' => array(
        // ...
        'default' => array(
            // ...
        ),
    ),
   'access_control' => array(
       // require ROLE_ADMIN for /admin*
        array('path' => '^/admin', 'role' => 'ROLE_ADMIN'),
    ),));
XML:<!-- app/config/security.xml --><?xml version="1.0" encoding="UTF-8"?><srv:container xmlns="http://Symfony.com/schema/dic/security"    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    xmlns:srv="http://Symfony.com/schema/dic/services"    xsi:schemaLocation="http://Symfony.com/schema/dic/services        http://Symfony.com/schema/dic/services/services-1.0.xsd">     <config>
        <!-- ... -->         <firewall name="default">
            <!-- ... -->
        </firewall>         <!-- require ROLE_ADMIN for /admin* -->
        <rule path="^/admin" role="ROLE_ADMIN" />
    </config></srv:container>
Sama seperti firewall, anda boleh mempunyai berbilang pembekal , tetapi anda hampir hanya memerlukan satu. Jika anda ada

mempunyai lebih daripada satu, anda boleh mengkonfigurasi "yang
satu
untuk digunakan" di bawah kekunci penyedia firewall (cth. provider:in_memory).

Rujukan
Cara menggunakan berbilang Pembekal Pengguna
untuk butiran penuh persediaan berbilang pembekal. 🎜🎜🎜

Cuba log masuk dengan nama pengguna admin dan kata laluan anak kucing. Anda sepatutnya melihat ralat! admin 和密码 kitten 来登录。你应该看到一个错误!

No encoder has been configured for account "SymfonyComponentSecurityCoreUserUser"

要修复此问题 ,添加一个 encoders 健:

YAML:# app/config/security.ymlsecurity:    # ...
    firewalls:        # ...
        default:            # ...
    access_control:        # require ROLE_ADMIN for /admin*
        - { path: ^/admin, roles: ROLE_ADMIN }
PHP:// app/config/security.php$container->loadFromExtension('security', array(
    // ...     'access_control' => array(
        array('path' => '^/admin/users', 'role' => 'ROLE_SUPER_ADMIN'),
        array('path' => '^/admin', 'role' => 'ROLE_ADMIN'),
    ),));
XML:<!-- app/config/security.xml --><?xml version="1.0" encoding="UTF-8"?><srv:container xmlns="http://Symfony.com/schema/dic/security"    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    xmlns:srv="http://Symfony.com/schema/dic/services"    xsi:schemaLocation="http://Symfony.com/schema/dic/services        http://Symfony.com/schema/dic/services/services-1.0.xsd">     <config>
        <!-- ... -->         <rule path="^/admin/users" role="ROLE_SUPER_ADMIN" />
        <rule path="^/admin" role="ROLE_ADMIN" />
    </config></srv:container>

User providers加载用户信息,并将其置于一个 User 对象中。如果你从数据库中加载用户 或者 从其他来源加载,你需要使用自定义的User类。但当你使用“in memory” provider时,它直接给了你一个 SymfonyComponentSecurityCoreUserUser 对象。

无论你使用什么样的User类,你都需要去告诉Symfony它们的密码加密算法是什么。在本例中,密码只是明文的文本,但很快,你要把它改成 bcrypt

如果你现在刷新,你就会登录进来!web除错工具栏会告诉你,你是何人,你的roles(角色)是什么:

4444t.png

由于此URL需要的是 ROLE_ADMIN ,如果你登录的是 ryan 用户,将被拒绝访问。更多内容参考后面的 [URL受到保护的条件(access_control](#catalog9)。

从数据库加载用户 

如果你想通过Doctrine Orm加载用户,很容易!参考 如何从数据库中(Entity Provider)加载Security系统之用户 以了解全部细节。

C) 对用户密码进行加密 

不管用户是存储在 security.yml 里,数据库里还是其他地方,你都需要去加密其密码。堪用的最好算法是 bcrypt

Tiada pengekod telah dikonfigurasikan untuk akaun "SymfonyComponentSecurityCoreUserUser"


Untuk membetulkannya, tambahkan kekunci pengekod
:

YAML:# app/config/security.ymlsecurity:    # ...
    access_control:
        - { path: ^/admin/users, roles: ROLE_SUPER_ADMIN }
        - { path: ^/admin, roles: ROLE_ADMIN }
// ... public function helloAction($name){
    // The second parameter is used to specify on what object the role is tested.
    // 第二个参数用于指定“要将role作用到什么对象之上”
    $this->denyAccessUnlessGranted('ROLE_ADMIN', null, 'Unable to access this page!');     // Old way / 老办法:
    // if (false === $this->get('security.authorization_checker')->isGranted('ROLE_ADMIN')) {
    //     throw $this->createAccessDeniedException('Unable to access this page!');
    // }     // ...}
// ...use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security; /**
 * @Security("has_role('ROLE_ADMIN')")
 */public function helloAction($name){
    // ...}

memasukkan maklumat pengguna untuk menambahnya Diletakkan dalam objek User. Jika anda memuatkan pengguna daripada pangkalan data atau memuatkan daripada sumber lain , anda perlu menggunakan kelas Pengguna tersuai. Tetapi apabila anda menggunakan pembekal "dalam memori", ia memberikan anda objek SymfonyComponentSecurityCoreUserUser secara langsung.


Tidak kira apa kelas Pengguna yang anda gunakan, anda perlu memberitahu Symfony tentang algoritma penyulitan kata laluan mereka. Dalam kes ini, kata laluan hanyalah teks yang jelas, tetapi tidak lama lagi, anda akan mahu menukarnya kepada bcrypt.

Jika anda muat semula sekarang, anda akan dilog masuk! Bar alat penyahpepijat web akan memberitahu anda siapa anda dan apakah peranan anda:
4444t.pngMemandangkan URL ini memerlukan ROLE_ADMIN, jika anda log masuk sebagai pengguna ryan , akses akan dinafikan. Untuk mendapatkan maklumat lanjut, sila rujuk kepada [syarat dilindungi URL (kawalan_akses](#catalog9) berikut.

Muat pengguna daripada pangkalan data

PHP:<?php if ($view['security']->isGranted('ROLE_ADMIN')): ?>
    <a href="...">Delete</a><?php endif ?>
Twig:{% if is_granted('ROLE_ADMIN') %}
    <a href="...">Delete</a>{% endif %}
Jika anda ingin memuatkan pengguna melalui Doctrine Orm, ianya mudah Rujuk Cara memuatkan pengguna sistem Keselamatan daripada pangkalan data (Penyedia Entiti) untuk butiran penuh

C) Sulitkan kata laluan pengguna

Tidak kira. Sama ada pengguna disimpan dalam security.yml, dalam pangkalan data atau di tempat lain, anda perlu menyulitkan kata laluan. Algoritma terbaik yang tersedia ialah bcrypt:
    if (!$this->get('security.authorization_checker')->isGranted('IS_AUTHENTICATED_FULLY')) {
        throw $this->createAccessDeniedException();
    }     // ...}
🎜 Sudah tentu, kata laluan pengguna kini perlu disulitkan oleh algoritma yang ditentukan ini. Bagi pengguna yang telah mengekodkannya (dalam config.yml), anda boleh melakukannya dengan arahan terbina dalam: 🎜🎜🎜🎜🎜🎜🎜🎜
PHP:<?php if ($view['security']->isGranted(new Expression(
    '"ROLE_ADMIN" in roles or (user and user.isSuperAdmin())'))): ?>
    <a href="...">Delete</a><?php endif; ?>
🎜🎜🎜🎜
Twig:{% if is_granted(expression(
    '"ROLE_ADMIN" in roles or (user and user.isSuperAdmin())')) %}
    <a href="...">Delete</a>{% endif %}
🎜🎜🎜🎜🎜🎜

Ia akan membawakan anda sesuatu seperti ini (kata laluan disulitkan):

public function indexAction(){
    if (!$this->get('security.authorization_checker')->isGranted('IS_AUTHENTICATED_FULLY')) {
        throw $this->createAccessDeniedException();
    }     $user = $this->getUser();     // the above is a shortcut for this / 上面的写法是通过以下取法(再进行授权)的快捷方式
    $user = $this->get('security.token_storage')->getToken()->getUser();}
use Symfony\Component\HttpFoundation\Response;
// ... public function indexAction(){
  // ...     return new Response('Well hi there '.$user->getFirstName());}

Sekarang semuanya sama seperti dahulu. Tetapi jika anda mempunyai pengguna dinamik (cth, dalam pangkalan data) yang kata laluannya disulitkan sebelum disimpan dalam pangkalan data, bagaimana anda boleh menyulitkannya secara pemrograman? Jangan risau, rujuk Sulitkan Kata Laluan Secara Manual untuk butiran.

Sama ada algoritma penyulitan ini disokong bergantung pada versi PHP anda, tetapi ia termasuk algoritma yang dikembalikan oleh fungsi hash_algos PHP dan beberapa yang lain (seperti bcrypt) disokong . Lihat kekunci pilihan pengekod dalam Rujukan keselamatan bcrypt)都受到支持。参考 Security参考 中的 encoders sebagai contoh.

Ia juga mungkin menggunakan algoritma yang berbeza untuk pengguna yang berbeza. Rujuk Cara Memilih Algoritma Penyulitan Kata Laluan secara Dinamik untuk butiran lanjut.

D) Konfigurasi selesai!

Tahniah! Kini anda mempunyai "sistem pengesahan" yang berfungsi berdasarkan pengesahan asas HTTP dan memuatkan pengguna daripada fail security.yml. security.yml 文件中加载用户的“验证系统”了。

根据你的设置,尚有后续步骤:

2) 拒绝访问,Roles和其他授权方式 

现在,用户可以通过 http_basic 或者其他方式来登录你的程序。了不起呀!现在你需要学习如何拒绝访问(deny access)并且能与User对象一起工作。这被称为authorization(授权),它的工作是决定用户是否可以访问某些资源(如一个URL、一个model对象、一个被调用的方法等...)。

授权过程分为两个不同的方面:

  1. 用户在登录时收到一组特定的Roles(角色。如 ROLE_ADMIN)。

  2. 你添加代码,以便某个资源(例如url、控制器)需要一个特定“属性”(多数时候就是一个类似 ROLE_ADMIN 的role)才能被访问到。

除了roles(如 ROLE_ADMIN ),你还可以使用其他属性/字符串来(如 EDITBergantung pada tetapan anda, terdapat langkah seterusnya:

atau < a href="/doc/current/security/custom_authentication_provider.html">Sesetengahnya tersuai sepenuhnya
  • 🎜 untuk memuatkan pengguna daripada sumber yang berbeza, seperti Pangkalan Data 🎜 atau sumber lain 🎜; 🎜
  • 🎜 dalam Bahagian Kebenaran🎜 untuk mengetahui cara menafikan akses, memuatkan objek pengguna dan mengendalikan Peranan; 🎜
  • 2) Tolak akses, Peranan dan kaedah kebenaran lain ¶🎜

    🎜Kini, pengguna boleh log masuk ke program anda melalui http_basic atau kaedah lain. Hebat! Kini anda perlu belajar cara menafikan akses dan bekerja dengan objek Pengguna. Ini dipanggil keizinan (keizinan), dan tugasnya adalah untuk menentukan sama ada pengguna boleh mengakses sumber tertentu (seperti URL, objek model, kaedah yang dipanggil, dll...). 🎜🎜Proses kebenaran terbahagi kepada dua aspek berbeza: 🎜
    1. 🎜Pengguna menerima set Peranan tertentu (peranan. Seperti ROLE_ADMIN) semasa log masuk. 🎜
    2. 🎜Anda menambah kod supaya sumber (cth. url, pengawal) memerlukan "atribut" tertentu (kebanyakannya peranan seperti ROLE_ADMIN) sebelum ia boleh diakses tiba. 🎜
    🎜Sebagai tambahan kepada peranan (seperti ROLE_ADMIN ), anda Anda juga boleh menggunakan atribut/rentetan lain (seperti EDIT) untuk melindungi sumber dan menjadikannya berkesan dengan menggunakan pengundi atau sistem ACL Symfony. Ini amat berguna apabila anda perlu menyemak sama ada pengguna A boleh "mengedit" objek B (contohnya, produk dengan id 5). Rujukan 🎜Senarai Kawalan Akses (ACL): Melindungi objek pangkalan data individu🎜. 🎜🎜🎜

    Peranan/peranan

    Apabila pengguna log masuk, mereka akan menerima satu set peranan (seperti ROLE_ADMIN). Dalam contoh di atas, (peranan) ini dikodkan keras menjadi security.yml. Jika anda memuatkan pengguna daripada pangkalan data, mereka harus disimpan dalam lajur jadual. ROLE_ADMIN)。在上例中,这些(roles)都被写死到 security.yml 中了。如果你从数据库中加载用户,它们应该存在了表的某一列中。

    你要分给一个用户的所有roles,一定要以 ROLE_ 前缀开始。否则,它们不会被Symfony的Security系统按常规方式来操作(除非使用高级手段,否则你把 FOO 这样的role分给一个用户,然后像 下面这样 去检查 FOO 是行不通的)。

    roles很简单,而且基本上都是你根据需要自行创造的字符串。例如,如果你打算限制访问你网站博客的admin部分,可以使用ROLE_BLOG_ADMIN 这个role来进行保护。role毋须在其他地方定义-你就可以开始用它了。

    确保每个用户至少有一个 角色,否则他们会被当作未验证之人。常见的做法就是给每个 普通用户一个 ROLE_USER

    你还可以指定role层级,此时,拥有某些roles意味着你同时拥有了其他的roles。

    添加代码以拒绝访问 

    要拒绝访问(deny access)某些东东,有两种方式可以实现:

    通过条件匹配来保护URL(access_control) 

    对程序的某一部分进行保护时的最基本方法是对URL进行完整的条件匹配。之前你已看到,任何匹配了正则表达式 ^/admin 的页面都需要 ROLE_ADMIN

    Semua peranan yang anda ingin berikan kepada pengguna mesti bermula dengan awalan ROLE_ . Jika tidak, ia tidak akan dikendalikan oleh sistem Keselamatan Symfony dengan cara biasa (melainkan anda menggunakan cara lanjutan, jika tidak, anda memberikan peranan seperti FOO kepada pengguna, dan kemudian seperti Yang berikut
    untuk menyemak FOO tidak akan berfungsi).
    peranan sangat mudah, dan pada asasnya adalah rentetan yang anda cipta mengikut keperluan anda. Contohnya, jika anda bercadang untuk menyekat akses kepada bahagian pentadbir blog tapak web anda, anda boleh menggunakan peranan ROLE_BLOG_ADMIN untuk melindunginya. Peranan tidak perlu ditakrifkan di tempat lain - anda boleh mula menggunakannya.
    Pastikan setiap pengguna mempunyai sekurang-kurangnya satu peranan, jika tidak, mereka akan dianggap sebagai tidak diketahui Orang yang mengesahkan. Pendekatan biasa ialah memberi setiap pengguna biasa ROLE_USER.
    🎜Anda juga boleh menentukan tahap peranan Pada masa ini, memiliki peranan tertentu bermakna anda juga memiliki peranan lain. 🎜🎜Tambah kod untuk menafikan akses
    ¶🎜🎜🎜Untuk menafikan akses kepada sesuatu, terdapat dua jenisIni boleh dicapai oleh: 🎜

    Lulus Padanan bersyarat untuk melindungi URL (access_control) ¶🎜

    🎜Kaedah paling asas untuk melindungi bahagian tertentu program adalah untuk melindungi padanan syarat Lengkap URL. Seperti yang anda lihat sebelum ini, mana-mana halaman yang sepadan dengan ungkapan biasa ^/admin memerlukan ROLE_ADMIN: 🎜
    // yay! Use this to see if the user is logged in// 耶!使用这个来查看用户是否已登陆if (!$this->get('security.authorization_checker')->isGranted('IS_AUTHENTICATED_FULLY')) {
        throw $this->createAccessDeniedException();} // boo :(. Never check for the User object to see if they're logged in// 哄!:(. 切勿通过检查User对象来判断用户是否已登陆if ($this->getUser()) { }
    PHP:<?php if ($view['security']->isGranted('IS_AUTHENTICATED_FULLY')): ?>
        <p>Username: <?php echo $app->getUser()->getUsername() ?></p><?php endif; ?>
    🎜🎜🎜🎜🎜
    Twig:{% if is_granted('IS_AUTHENTICATED_FULLY') %}
        <p>Username: {{ app.user.username }}</p>{% endif %}
    🎜🎜🎜🎜🎜

    Ia bagus untuk dapat melindungi seluruh kawasan (yang menjadi milik URL), tetapi anda mungkin juga ingin melindungi tindakan tertentu pengawal.

    Anda boleh menentukan seberapa banyak syarat padanan URL yang anda mahu - setiap syarat ialah ungkapan biasa. tetapi , hanya dan satu akan dipadankan. Symfony akan mula melihat bahagian atas (dalam fail) dan tamat sebaik sahaja ia menemui entri dalam access_control yang sepadan dengan URL. access_control 中的某个入口与URL相匹配,就立即结束。

    PHP:// app/config/security.php$container->loadFromExtension('security', array(
        // ...     'firewalls' => array(
            'secured_area' => array(
                // ...
                'logout' => array('path' => '/logout', 'target' => '/'),
            ),
        ),));
    Twig:<!-- app/config/security.xml --><?xml version="1.0" encoding="UTF-8"?><srv:container xmlns="http://Symfony.com/schema/dic/security"    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    xmlns:srv="http://Symfony.com/schema/dic/services"    xsi:schemaLocation="http://Symfony.com/schema/dic/services        http://Symfony.com/schema/dic/services/services-1.0.xsd">     <config>
            <!-- ... -->         <firewall name="secured_area">
                <!-- ... -->
                <logout path="/logout" target="/" />
            </firewall>
        </config></srv:container>
    YAML:# app/config/security.ymlsecurity:    # ...
        firewalls:
            secured_area:            # ...
                logout:
                    path:   /logout
                    target: /

    在path中加了一个 ^ 是指,仅当URL“按照正则条件那样起头”时,才会匹配到。例如,一个path若只有 /admin(不包含 ^)则会匹配到 /admin/foo 但同时也匹配了 /foo/admin 这种。

    理解access_control是如何工作的

    access_control 部分异常强大,但如果你不明白它的工作原理,它也会很危险(毕竟涉及到安全性)。 access_control 除了匹配URL,还可匹配IP地址、主机名和HTTP method。它也可以用于将用户重定向到 https 版本的URL条件中去。

    要了解这一切,参考 Security的access_control是如何工作的

    保护控制器和代码中的其他部分 

    在控制器中你可以轻松谢绝访问:

    PHP:// app/config/routing.phpuse Symfony\Component\Routing\RouteCollection;use Symfony\Component\Routing\Route; $collection = new RouteCollection();$collection->add('logout', new Route('/logout')); return $collection;

    两种情况下,一个特殊的 AccessDeniedException 会被抛出,这最终触发了Symfony内部的一个403 HTTP响应。

    就是这样!如果是尚未登录的用户,他们会被要求登录(如,重定向到登录页面)。如果他们已经 登录,但不具备 ROLE_ADMIN 角色,则会被显示403拒绝访问页面(此页可以 自定义)。如果他们已登录同时拥有正确的roles,代码就会继续执行。

    多亏了SensioFrameworkExtraBundle,你可以在控制器中使用annotations

    XML:<!-- app/config/routing.xml --><?xml version="1.0" encoding="UTF-8" ?><routes xmlns="http://Symfony.com/schema/routing"    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    xsi:schemaLocation="http://Symfony.com/schema/routing        http://Symfony.com/schema/routing/routing-1.0.xsd">     <route id="logout" path="/logout" /></routes>

    参考 FrameworkExtraBundle 以了解更多。

    模版中的访问控制 

    如果你想在模版中检查当前用户是否具有一个role,可以使用内置的 is_granted()

    YAML:# app/config/routing.ymllogout:
        path: /logout
    PHP:// app/config/security.php$container->loadFromExtension('security', array(
        // ...     'role_hierarchy' => array(
            'ROLE_ADMIN'       => 'ROLE_USER',
            'ROLE_SUPER_ADMIN' => array(
                'ROLE_ADMIN',
                'ROLE_ALLOWED_TO_SWITCH',
            ),
        ),));

    XML:<!-- app/config/security.xml --><?xml version="1.0" encoding="UTF-8"?><srv:container xmlns="http://Symfony.com/schema/dic/security"    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    xmlns:srv="http://Symfony.com/schema/dic/services"    xsi:schemaLocation="http://Symfony.com/schema/dic/services        http://Symfony.com/schema/dic/services/services-1.0.xsd">     <config>
            <!-- ... -->         <role id="ROLE_ADMIN">ROLE_USER</role>
            <role id="ROLE_SUPER_ADMIN">ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH</role>
        </config></srv:container>
    Menambah ^ pada laluan bermakna ia hanya akan sepadan jika URL "bermula mengikut syarat biasa" tiba. Contohnya, jika laluan hanya mengandungi /admin (tanpa ^), ia akan sepadan dengan /admin/foo tetapi juga /. foo/admin Jenis ini. #🎜🎜#

    Fahami cara access_control berfungsi

    # The 🎜 Bahagian 🎜#access_control sangat berkuasa, tetapi ia juga boleh berbahaya jika anda tidak memahami cara ia berfungsi (selepas semua itu keselamatan terlibat). access_control Selain URL yang sepadan, ia juga boleh memadankan alamat IP, nama hos dan kaedah HTTP. Ia juga boleh digunakan untuk mengubah hala pengguna ke versi https bagi syarat URL. #🎜🎜##🎜🎜#Untuk memahami semua ini, rujuk Cara kawalan_akses Keselamatan berfungsi#🎜🎜#. #🎜🎜##🎜🎜##🎜🎜#

    Lindungi pengawal dan bahagian lain kod ¶#🎜🎜##🎜🎜#Dalam pengawal anda boleh menafikan akses dengan mudah: #🎜🎜#
    YAML:# app/config/security.ymlsecurity:    # ...
        role_hierarchy:
            ROLE_ADMIN:       ROLE_USER
            ROLE_SUPER_ADMIN: [ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH]
    #🎜🎜#Dalam kedua-dua kes,
    AccessDeniedException#🎜🎜# akan dilemparkan, yang akhirnya mencetuskan tindak balas HTTP Symfony A 403 dalaman.
    #🎜🎜##🎜🎜#Itu sahaja! Jika pengguna belum log masuk lagi, mereka akan diminta untuk log masuk (cth., diubah hala ke halaman log masuk). Jika mereka sudah log masuk tetapi tidak mempunyai peranan ROLE_ADMIN, mereka akan ditunjukkan halaman 403 Access Denied (halaman ini boleh
    custom #🎜🎜#). Jika mereka log masuk dan mempunyai peranan yang betul, kod akan terus dilaksanakan. #🎜🎜##🎜🎜# Terima kasih kepada SensioFrameworkExtraBundle, anda boleh menggunakan anotasi dalam pengawal#🎜🎜#rrreee#🎜🎜#RujukanFrameworkExtraBundle#🎜🎜# untuk mengetahui lebih lanjut.
    #🎜🎜#

    Kawalan akses dalam templat ¶#🎜🎜#

    #🎜🎜#Jika anda Jika anda ingin menyemak sama ada pengguna semasa mempunyai peranan dalam templat, anda boleh menggunakan fungsi pembantu is_granted() terbina dalam: #🎜🎜#rrreee#🎜🎜#rrreee#🎜🎜#

    Lindungi perkhidmatan lain

    Jika anda menulis beberapa kod yang serupa seperti "Protect Controller", di mana-mana sahaja di Symfony boleh dilindungi. Katakan anda mempunyai perkhidmatan (iaitu kelas php) untuk menghantar e-mel. Anda boleh mengehadkan penggunaan kelas ini - tidak kira di mana ia digunakan - kepada pengguna tertentu sahaja.

    Rujuk Cara melindungi perkhidmatan dan kaedah dalam program untuk mengetahui lebih lanjut.

    Semak sama ada pengguna telah log masuk (IS_AUTHENTICATED_FULLY)

    Setakat ini, anda telah menyemak akses berasaskan peranan - rentetan tersebut bermula dengan awalan ROLE_ yang diberikan kepada pengguna. Walau bagaimanapun, jika anda ROLE_ 前缀开头的字符串,被分配给了用户。但是,如果你 想检查用户是否登录(并不关心什么role不role的),那么你可以使用 IS_AUTHENTICATED_FULLY// ... public function helloAction($name){

    rrreee

    你当然也可以使用在 access_control 中使用它。

    IS_AUTHENTICATED_FULLY 不是一个role,但是它的某些行为又像是role,并且每个成功登录的用户都有这么一个。事实上,类似的特殊属性共有三个: