8000 symfony-docs/security.rst at 053cee723bf308ed6afac3eb185b09ec44209a6d · symfony/symfony-docs · GitHub
[go: up one dir, main page]

Skip to content
{"payload":{"allShortcutsEnabled":false,"fileTree":{"":{"items":[{"name":".github","path":".github","contentType":"directory"},{"name":".platform","path":".platform","contentType":"directory"},{"name":"_build","path":"_build","contentType":"directory"},{"name":"_images","path":"_images","contentType":"directory"},{"name":"_includes","path":"_includes","contentType":"directory"},{"name":"assetic","path":"assetic","contentType":"directory"},{"name":"best_practices","path":"best_practices","contentType":"directory"},{"name":"bundles","path":"bundles","contentType":"directory"},{"name":"components","path":"components","contentType":"directory"},{"name":"configuration","path":"configuration","contentType":"directory"},{"name":"console","path":"console","contentType":"directory"},{"name":"contributing","path":"contributing","contentType":"directory"},{"name":"controller","path":"controller","contentType":"directory"},{"name":"create_framework","path":"create_framework","contentType":"directory"},{"name":"debug","path":"debug","contentType":"directory"},{"name":"deployment","path":"deployment","contentType":"directory"},{"name":"doctrine","path":"doctrine","contentType":"directory"},{"name":"email","path":"email","contentType":"directory"},{"name":"event_dispatcher","path":"event_dispatcher","contentType":"directory"},{"name":"form","path":"form","contentType":"directory"},{"name":"frontend","path":"frontend","contentType":"directory"},{"name":"getting_started","path":"getting_started","contentType":"directory"},{"name":"http_cache","path":"http_cache","contentType":"directory"},{"name":"introduction","path":"introduction","contentType":"directory"},{"name":"logging","path":"logging","contentType":"directory"},{"name":"profiler","path":"profiler","contentType":"directory"},{"name":"quick_tour","path":"quick_tour","contentType":"directory"},{"name":"reference","path":"reference","contentType":"directory"},{"name":"request","path":"request","contentType":"directory"},{"name":"routing","path":"routing","contentType":"directory"},{"name":"security","path":"security","contentType":"directory"},{"name":"serializer","path":"serializer","contentType":"directory"},{"name":"service_container","path":"service_container","contentType":"directory"},{"name":"session","path":"session","contentType":"directory"},{"name":"setup","path":"setup","contentType":"directory"},{"name":"templating","path":"templating","contentType":"directory"},{"name":"testing","path":"testing","contentType":"directory"},{"name":"translation","path":"translation","contentType":"directory"},{"name":"validation","path":"validation","contentType":"directory"},{"name":".editorconfig","path":".editorconfig","contentType":"file"},{"name":".gitignore","path":".gitignore","contentType":"file"},{"name":".platform.app.yaml","path":".platform.app.yaml","contentType":"file"},{"name":".travis.yml","path":".travis.yml","contentType":"file"},{"name":"README.markdown","path":"README.markdown","contentType":"file"},{"name":"assetic.rst","path":"assetic.rst","contentType":"file"},{"name":"bundles.rst","path":"bundles.rst","contentType":"file"},{"name":"changelog.rst","path":"changelog.rst","contentType":"file"},{"name":"configuration.rst","path":"configuration.rst","contentType":"file"},{"name":"console.rst","path":"console.rst","contentType":"file"},{"name":"controller.rst","path":"controller.rst","contentType":"file"},{"name":"debug.rst","path":"debug.rst","contentType":"file"},{"name":"deployment.rst","path":"deployment.rst","contentType":"file"},{"name":"doctrine.rst","path":"doctrine.rst","contentType":"file"},{"name":"email.rst","path":"email.rst","contentType":"file"},{"name":"event_dispatcher.rst","path":"event_dispatcher.rst","contentType":"file"},{"name":"expressions.rst","path":"expressions.rst","contentType":"file"},{"name":"forms.rst","path":"forms.rst","contentType":"file"},{"name":"frontend.rst","path":"frontend.rst","contentType":"file"},{"name":"http_cache.rst","path":"http_cache.rst","contentType":"file"},{"name":"index.rst","path":"index.rst","contentType":"file"},{"name":"logging.rst","path":"logging.rst","contentType":"file"},{"name":"page_creation.rst","path":"page_creation.rst","contentType":"file"},{"name":"performance.rst","path":"performance.rst","contentType":"file"},{"name":"profiler.rst","path":"profiler.rst","contentType":"file"},{"name":"request.rst","path":"request.rst","contentType":"file"},{"name":"requirements.txt","path":"requirements.txt","contentType":"file"},{"name":"routing.rst","path":"routing.rst","contentType":"file"},{"name":"security.rst","path":"security.rst","contentType":"file"},{"name":"serializer.rst","path":"serializer.rst","contentType":"file"},{"name":"service_container.rst","path":"service_container.rst","contentType":"file"},{"name":"session.rst","path":"session.rst","contentType":"file"},{"name":"setup.rst","path":"setup.rst","contentType":"file"},{"name":"templating.rst","path":"templating.rst","contentType":"file"},{"name":"testing.rst","path":"testing.rst","contentType":"file"},{"name":"translation.rst","path":"translation.rst","contentType":"file"},{"name":"validation.rst","path":"validation.rst","contentType":"file"}],"totalCount":76}},"fileTreeProcessingTime":52.972118,"foldersToFetch":[],"incompleteFileTree":false,"repo":{"id":521583,"defaultBranch":"7.3","name":"symfony-docs","ownerLogin":"symfony","currentUserCanPush":false,"isFork":false,"isEmpty":false,"createdAt":"2010-02-17T08:43:51.000Z","ownerAvatar":"https://avatars.githubusercontent.com/u/143937?v=4","public":true,"private":false,"isOrgOwned":true},"codeLineWrapEnabled":false,"symbolsExpanded":false,"treeExpanded":true,"refInfo":{"name":"053cee723bf308ed6afac3eb185b09ec44209a6d","listCacheKey":"v0:1748857018.0","canEdit":false,"refType":"tree","currentOid":"053cee723bf308ed6afac3eb185b09ec44209a6d"},"path":"security.rst","currentUser":null,"blob":{"rawLines":null,"stylingDirectives":null,"colorizedLines":null,"csv":null,"csvError":null,"dependabotInfo":{"showConfigurationBanner":false,"configFilePath":null,"networkDependabotPath":"/symfony/symfony-docs/network/updates","dismissConfigurationNoticePath":"/settings/dismiss-notice/dependabot_configuration_notice","configurationNoticeDismissed":null},"displayName":"security.rst","displayUrl":"https://github.com/symfony/symfony-docs/blob/053cee723bf308ed6afac3eb185b09ec44209a6d/security.rst?raw=true","headerInfo":{"blobSize":"43.9 KB","deleteTooltip":"You must be signed in to make or propose changes","editTooltip":"You must be signed in to make or propose changes","ghDesktopPath":null,"isGitLfs":false,"onBranch":false,"shortPath":"00ed80f","siteNavLoginPath":"/login?return_to=https%3A%2F%2Fgithub.com%2Fsymfony%2Fsymfony-docs%2Fblob%2F053cee723bf308ed6afac3eb185b09ec44209a6d%2Fsecurity.rst","isCSV":false,"isRichtext":true,"toc":[{"level":2,"text":"Security","anchor":"security","htmlText":"Security"},{"level":3,"text":"1) Initial security.yml Setup (Authentication)","anchor":"1-initial-securityyml-setup-authentication","htmlText":"1) Initial security.yml Setup (Authentication)"},{"level":4,"text":"A) Configuring how your Users will Authenticate","anchor":"a-configuring-how-your-users-will-authenticate","htmlText":"A) Configuring how your Users will Authenticate"},{"level":4,"text":"B) Configuring how Users are Loaded","anchor":"b-configuring-how-users-are-loaded","htmlText":"B) Configuring how Users are Loaded"},{"level":5,"text":"Loading Users from the Database","anchor":"loading-users-from-the-database","htmlText":"Loading Users from the Database"},{"level":4,"text":"C) Encoding the User's Password","anchor":"c-encoding-the-users-password","htmlText":"C) Encoding the User's Password"},{"level":4,"text":"D) Configuration Done!","anchor":"d-configuration-done","htmlText":"D) Configuration Done!"},{"level":3,"text":"2) Denying Access, Roles and other Authorization","anchor":"2-denying-access-roles-and-other-authorization","htmlText":"2) Denying Access, Roles and other Authorization"},{"level":4,"text":"Roles","anchor":"roles","htmlText":"Roles"},{"level":4,"text":"Add Code to Deny Access","anchor":"add-code-to-deny-access","htmlText":"Add Code to Deny Access"},{"level":5,"text":"Securing URL patterns (access_control)","anchor":"securing-url-patterns-access_control","htmlText":"Securing URL patterns (access_control)"},{"level":5,"text":"Securing Controllers and other Code","anchor":"securing-controllers-and-other-code","htmlText":"Securing Controllers and other Code"},{"level":5,"text":"Access Control in Templates","anchor":"access-control-in-templates","htmlText":"Access Control in Templates"},{"level":5,"text":"Securing other Services","anchor":"securing-other-services","htmlText":"Securing other Services"},{"level":4,"text":"Checking to see if a User is Logged In (IS_AUTHENTICATED_FULLY)","anchor":"checking-to-see-if-a-user-is-logged-in-is_authenticated_fully","htmlText":"Checking to see if a User is Logged In (IS_AUTHENTICATED_FULLY)"},{"level":4,"text":"Access Control Lists (ACLs): Securing individual Database Objects","anchor":"access-control-lists-acls-securing-individual-database-objects","htmlText":"Access Control Lists (ACLs): Securing individual Database Objects"},{"level":3,"text":"Retrieving the User Object","anchor":"retrieving-the-user-object","htmlText":"Retrieving the User Object"},{"level":4,"text":"Always Check if the User is Logged In","anchor":"always-check-if-the-user-is-logged-in","htmlText":"Always Check if the User is Logged In"},{"level":4,"text":"Retrieving the User in a Template","anchor":"retrieving-the-user-in-a-template","htmlText":"Retrieving the User in a Template"},{"level":3,"text":"Logging Out","anchor":"logging-out","htmlText":"Logging Out"},{"level":3,"text":"Hierarchical Roles","anchor":"hierarchical-roles","htmlText":"Hierarchical Roles"},{"level":3,"text":"Final Words","anchor":"final-words","htmlText":"Final Words"},{"level":3,"text":"Learn More","anchor":"learn-more","htmlText":"Learn More"},{"level":4,"text":"Authentication (Identifying/Logging in the User)","anchor":"authentication-identifyinglogging-in-the-user","htmlText":"Authentication (Identifying/Logging in the User)"},{"level":4,"text":"Authorization (Denying Access)","anchor":"authorization-denying-access","htmlText":"Authorization (Denying Access)"},{"level":4,"text":"Other Security Related Topics","anchor":"other-security-related-topics","htmlText":"Other Security Related Topics"}],"lineInfo":{"truncatedLoc":"1335","truncatedSloc":"991"},"mode":"file"},"image":false,"isCodeownersFile":null,"isPlain":false,"isValidLegacyIssueTemplate":false,"issueTemplate":null,"discussionTemplate":null,"language":"reStructuredText","languageID":419,"large":false,"planSupportInfo":{"repoIsFork":null,"repoOwnedByCurrentUser":null,"requestFullPath":"/symfony/symfony-docs/blob/053cee723bf308ed6afac3eb185b09ec44209a6d/security.rst","showFreeOrgGatedFeatureMessage":null,"showPlanSupportBanner":null,"upgradeDataAttributes":null,"upgradePath":null},"publishBannersInfo":{"dismissActionNoticePath":"/settings/dismiss-notice/publish_action_from_dockerfile","releasePath":"/symfony/symfony-docs/releases/new?marketplace=true","showPublishActionBanner":false},"rawBlobUrl":"https://github.com/symfony/symfony-docs/raw/053cee723bf308ed6afac3eb185b09ec44209a6d/security.rst","renderImageOrRaw":false,"richText":"\u003carticle class=\"markdown-body entry-content container-lg\" itemprop=\"text\"\u003e\u003cpre\u003e.. index::\n single: Security\n\n\u003c/pre\u003e\n\u003ca name=\"user-content-security\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch2 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eSecurity\u003c/h2\u003e\u003ca id=\"user-content-security\" class=\"anchor\" aria-label=\"Permalink: Security\" href=\"#security\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eSymfony's security system is incredibly powerful, but it can also be confusing\nto set up. In this article, you'll learn how to set up your application's security\nstep-by-step, from configuring your firewall and how you load users to denying\naccess and fetching the User object. Depending on what you need, sometimes\nthe initial setup can be tough. But once it's done, Symfony's security system\nis both flexible and (hopefully) fun to work with.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eSince there's a lot to talk about, this article is organized into a few big\nsections:\u003c/p\u003e\n\u003col dir=\"auto\"\u003e\n\u003cli\u003eInitial \u003ccode\u003esecurity.yml\u003c/code\u003e setup (\u003cem\u003eauthentication\u003c/em\u003e);\u003c/li\u003e\n\u003cli\u003eDenying access to your app (\u003cem\u003eauthorization\u003c/em\u003e);\u003c/li\u003e\n\u003cli\u003eFetching the current User object.\u003c/li\u003e\n\u003c/ol\u003e\n\u003cp dir=\"auto\"\u003eThese are followed by a number of small (but still captivating) sections,\nlike \u003ca href=\"#id1\"\u003e\u003cspan id=\"user-content-id2\"\u003e:ref:`logging out \u0026lt;security-logging-out\u0026gt;`\u003c/span\u003e\u003c/a\u003e and\n\u003ca href=\"#id3\"\u003e\u003cspan id=\"user-content-id4\"\u003e:doc:`encoding user passwords \u0026lt;/security/password_encoding\u0026gt;`\u003c/span\u003e\u003c/a\u003e.\u003c/p\u003e\n\u003ca name=\"user-content-initial-security-yml-setup-authentication\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003e1) Initial security.yml Setup (Authentication)\u003c/h3\u003e\u003ca id=\"user-content-1-initial-securityyml-setup-authentication\" class=\"anchor\" aria-label=\"Permalink: 1) Initial security.yml Setup (Authentication)\" href=\"#1-initial-securityyml-setup-authentication\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eThe security system is configured in \u003ccode\u003eapp/config/security.yml\u003c/code\u003e. The default\nconfiguration looks like this:\u003c/p\u003e\n\u003cpre\u003e.. configuration-block::\n\n .. code-block:: yaml\n\n # app/config/security.yml\n security:\n providers:\n in_memory:\n memory: ~\n\n firewalls:\n dev:\n pattern: ^/(_(profiler|wdt)|css|images|js)/\n security: false\n\n default:\n anonymous: ~\n\n .. code-block:: xml\n\n \u0026lt;!-- app/config/security.xml --\u0026gt;\n \u0026lt;?xml version=\"1.0\" encoding=\"UTF-8\"?\u0026gt;\n \u0026lt;srv:container xmlns=\"http://symfony.com/schema/dic/security\"\n xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n xmlns:srv=\"http://symfony.com/schema/dic/services\"\n xsi:schemaLocation=\"http://symfony.com/schema/dic/services\n http://symfony.com/schema/dic/services/services-1.0.xsd\"\u0026gt;\n\n \u0026lt;config\u0026gt;\n \u0026lt;provider name=\"in_memory\"\u0026gt;\n \u0026lt;memory /\u0026gt;\n \u0026lt;/provider\u0026gt;\n\n \u0026lt;firewall name=\"dev\"\n pattern=\"^/(_(profiler|wdt)|css|images|js)/\"\n security=\"false\" /\u0026gt;\n\n \u0026lt;firewall name=\"default\"\u0026gt;\n \u0026lt;anonymous /\u0026gt;\n \u0026lt;/firewall\u0026gt;\n \u0026lt;/config\u0026gt;\n \u0026lt;/srv:container\u0026gt;\n\n .. code-block:: php\n\n // app/config/security.php\n $container-\u0026gt;loadFromExtension('security', array(\n 'providers' =\u0026gt; array(\n 'in_memory' =\u0026gt; array(\n 'memory' =\u0026gt; null,\n ),\n ),\n 'firewalls' =\u0026gt; array(\n 'dev' =\u0026gt; array(\n 'pattern' =\u0026gt; '^/(_(profiler|wdt)|css|images|js)/',\n 'security' =\u0026gt; false,\n ),\n 'default' =\u0026gt; array(\n 'anonymous' =\u0026gt; null,\n ),\n ),\n ));\n\n\u003c/pre\u003e\n\u003cp dir=\"auto\"\u003eThe \u003ccode\u003efirewalls\u003c/code\u003e key is the \u003cem\u003eheart\u003c/em\u003e of your security configuration. The\n\u003ccode\u003edev\u003c/code\u003e firewall isn't important, it just makes sure that Symfony's development\ntools - which live under URLs like \u003ccode\u003e/_profiler\u003c/code\u003e and \u003ccode\u003e/_wdt\u003c/code\u003e aren't blocked\nby your security.\u003c/p\u003e\n\u003cdiv dir=\"auto\"\u003e\n\u003cp dir=\"auto\"\u003eTip\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eYou can also match a request against other details of the request (e.g. host). For more\ninformation and examples read \u003ca href=\"#id5\"\u003e\u003cspan id=\"user-content-id6\"\u003e:doc:`/security/firewall_restriction`\u003c/span\u003e\u003c/a\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eAll other URLs will be handled by the \u003ccode\u003edefault\u003c/code\u003e firewall (no \u003ccode\u003epattern\u003c/code\u003e\nkey means it matches \u003cem\u003eall\u003c/em\u003e URLs). You can think of the firewall like your\nsecurity system, and so it usually makes sense to have just one main firewall.\nBut this does \u003cem\u003enot\u003c/em\u003e mean that every URL requires authentication - the \u003ccode\u003eanonymous\u003c/code\u003e\nkey takes care of this. In fact, if you go to the homepage right now, you'll\nhave access and you'll see that you're \"authenticated\" as \u003ccode\u003eanon.\u003c/code\u003e. Don't\nbe fooled by the \"Yes\" next to Authenticated, you're just an anonymous user:\u003c/p\u003e\n\u003cp dir=\"auto\"\u003e\u003ca target=\"_blank\" rel=\"noopener noreferrer\" href=\"/symfony/symfony-docs/blob/053cee723bf308ed6afac3eb185b09ec44209a6d/_images/security/anonymous_wdt.png\"\u003e\u003cimg alt=\"/_images/security/anonymous_wdt.png\" src=\"/symfony/symfony-docs/raw/053cee723bf308ed6afac3eb185b09ec44209a6d/_images/security/anonymous_wdt.png\" style=\"max-width: 100%;\"\u003e\u003c/a\u003e\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eYou'll learn later how to deny access to certain URLs or controllers.\u003c/p\u003e\n\u003cdiv dir=\"auto\"\u003e\n\u003cp dir=\"auto\"\u003eTip\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eSecurity is \u003cem\u003ehighly\u003c/em\u003e configurable and there's a\n\u003ca href=\"#id7\"\u003e\u003cspan id=\"user-content-id8\"\u003e:doc:`Security Configuration Reference \u0026lt;/reference/configuration/security\u0026gt;`\u003c/span\u003e\u003c/a\u003e\nthat shows all of the options with some extra explanation.\u003c/p\u003e\n\u003c/div\u003e\n\u003ca name=\"user-content-a-configuring-how-your-users-will-authenticate\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch4 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eA) Configuring how your Users will Authenticate\u003c/h4\u003e\u003ca id=\"user-content-a-configuring-how-your-users-will-authenticate\" class=\"anchor\" aria-label=\"Permalink: A) Configuring how your Users will Authenticate\" href=\"#a-configuring-how-your-users-will-authenticate\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eThe main job of a firewall is to configure \u003cem\u003ehow\u003c/em\u003e your users will authenticate.\nWill they use a login form? HTTP basic authentication? An API token? All of the above?\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eLet's start with HTTP basic authentication (the old-school prompt) and work up from there.\nTo activate this, add the \u003ccode\u003ehttp_basic\u003c/code\u003e key under your firewall:\u003c/p\u003e\n\u003cpre\u003e.. configuration-block::\n\n .. code-block:: yaml\n\n # app/config/security.yml\n security:\n # ...\n\n firewalls:\n # ...\n default:\n anonymous: ~\n http_basic: ~\n\n .. code-block:: xml\n\n \u0026lt;!-- app/config/security.xml --\u0026gt;\n \u0026lt;?xml version=\"1.0\" encoding=\"UTF-8\"?\u0026gt;\n \u0026lt;srv:container xmlns=\"http://symfony.com/schema/dic/security\"\n xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n xmlns:srv=\"http://symfony.com/schema/dic/services\"\n xsi:schemaLocation=\"http://symfony.com/schema/dic/services\n http://symfony.com/schema/dic/services/services-1.0.xsd\"\u0026gt;\n\n \u0026lt;config\u0026gt;\n \u0026lt;!-- ... --\u0026gt;\n\n \u0026lt;firewall name=\"default\"\u0026gt;\n \u0026lt;anonymous /\u0026gt;\n \u0026lt;http-basic /\u0026gt;\n \u0026lt;/firewall\u0026gt;\n \u0026lt;/config\u0026gt;\n \u0026lt;/srv:container\u0026gt;\n\n .. code-block:: php\n\n // app/config/security.php\n $container-\u0026gt;loadFromExtension('security', array(\n // ...\n 'firewalls' =\u0026gt; array(\n // ...\n 'default' =\u0026gt; array(\n 'anonymous' =\u0026gt; null,\n 'http_basic' =\u0026gt; null,\n ),\n ),\n ));\n\n\u003c/pre\u003e\n\u003cp dir=\"auto\"\u003eSimple! To try this, you need to require the user to be logged in to see\na page. To make things interesting, create a new page at \u003ccode\u003e/admin\u003c/code\u003e. For\nexample, if you use annotations, create something like this:\u003c/p\u003e\n\u003cpre\u003e// src/AppBundle/Controller/DefaultController.php\n// ...\n\nuse Sensio\\Bundle\\FrameworkExtraBundle\\Configuration\\Route;\nuse Symfony\\Bundle\\FrameworkBundle\\Controller\\Controller;\nuse Symfony\\Component\\HttpFoundation\\Response;\n\nclass DefaultController extends Controller\n{\n /**\n * @Route(\"/admin\")\n */\n public function adminAction()\n {\n return new Response('\u0026lt;html\u0026gt;\u0026lt;body\u0026gt;Admin page!\u0026lt;/body\u0026gt;\u0026lt;/html\u0026gt;');\n }\n}\n\u003c/pre\u003e\n\u003cp dir=\"auto\"\u003eNext, add an \u003ccode\u003eaccess_control\u003c/code\u003e entry to \u003ccode\u003esecurity.yml\u003c/code\u003e that requires the\nuser to be logged in to access this URL:\u003c/p\u003e\n\u003cpre\u003e.. configuration-block::\n\n .. code-block:: yaml\n\n # app/config/security.yml\n security:\n # ...\n firewalls:\n # ...\n default:\n # ...\n\n access_control:\n # require ROLE_ADMIN for /admin*\n - { path: ^/admin, roles: ROLE_ADMIN }\n\n .. code-block:: xml\n\n \u0026lt;!-- app/config/security.xml --\u0026gt;\n \u0026lt;?xml version=\"1.0\" encoding=\"UTF-8\"?\u0026gt;\n \u0026lt;srv:container xmlns=\"http://symfony.com/schema/dic/security\"\n xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n xmlns:srv=\"http://symfony.com/schema/dic/services\"\n xsi:schemaLocation=\"http://symfony.com/schema/dic/services\n http://symfony.com/schema/dic/services/services-1.0.xsd\"\u0026gt;\n\n \u0026lt;config\u0026gt;\n \u0026lt;!-- ... --\u0026gt;\n\n \u0026lt;firewall name=\"default\"\u0026gt;\n \u0026lt;!-- ... --\u0026gt;\n \u0026lt;/firewall\u0026gt;\n\n \u0026lt;!-- require ROLE_ADMIN for /admin* --\u0026gt;\n \u0026lt;rule path=\"^/admin\" role=\"ROLE_ADMIN\" /\u0026gt;\n \u0026lt;/config\u0026gt;\n \u0026lt;/srv:container\u0026gt;\n\n .. code-block:: php\n\n // app/config/security.php\n $container-\u0026gt;loadFromExtension('security', array(\n // ...\n 'firewalls' =\u0026gt; array(\n // ...\n 'default' =\u0026gt; array(\n // ...\n ),\n ),\n 'access_control' =\u0026gt; array(\n // require ROLE_ADMIN for /admin*\n array('path' =\u0026gt; '^/admin', 'role' =\u0026gt; 'ROLE_ADMIN'),\n ),\n ));\n\n\u003c/pre\u003e\n\u003cdiv dir=\"auto\"\u003e\n\u003cp dir=\"auto\"\u003eNote\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eYou'll learn more about this \u003ccode\u003eROLE_ADMIN\u003c/code\u003e thing and denying access\nlater in the \u003ca href=\"#id9\"\u003e\u003cspan id=\"user-content-id10\"\u003e:ref:`security-authorization`\u003c/span\u003e\u003c/a\u003e section.\u003c/p\u003e\n\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eGreat! Now, if you go to \u003ccode\u003e/admin\u003c/code\u003e, you'll see the HTTP basic auth prompt:\u003c/p\u003e\n\u003cp dir=\"auto\"\u003e\u003ca target=\"_blank\" rel=\"noopener noreferrer\" href=\"/symfony/symfony-docs/blob/053cee723bf308ed6afac3eb185b09ec44209a6d/_images/security/http_basic_popup.png\"\u003e\u003cimg alt=\"/_images/security/http_basic_popup.png\" src=\"/symfony/symfony-docs/raw/053cee723bf308ed6afac3eb185b09ec44209a6d/_images/security/http_basic_popup.png\" style=\"max-width: 100%;\"\u003e\u003c/a\u003e\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eBut who can you login as? Where do users come from?\u003c/p\u003e\n\u003cdiv id=\"user-content-security-form-login\" dir=\"auto\"\u003e\n\u003cp dir=\"auto\"\u003eTip\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eWant to use a traditional login form? Great! See \u003ca href=\"#id11\"\u003e\u003cspan id=\"user-content-id12\"\u003e:doc:`/security/form_login_setup`\u003c/span\u003e\u003c/a\u003e.\nWhat other methods are supported? See the \u003ca href=\"#id13\"\u003e\u003cspan id=\"user-content-id14\"\u003e:doc:`Configuration Reference \u0026lt;/reference/configuration/security\u0026gt;`\u003c/span\u003e\u003c/a\u003e\nor \u003ca href=\"#id15\"\u003e\u003cspan id=\"user-content-id16\"\u003e:doc:`build your own \u0026lt;/security/custom_authentication_provider\u0026gt;`\u003c/span\u003e\u003c/a\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv dir=\"auto\"\u003e\n\u003cp dir=\"auto\"\u003eTip\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eIf your application logs users in via a third-party service such as Google,\nFacebook or Twitter, check out the \u003ca href=\"https://github.com/hwi/HWIOAuthBundle\"\u003eHWIOAuthBundle\u003c/a\u003e community bundle.\u003c/p\u003e\n\u003c/div\u003e\n\u003ca name=\"user-content-b-configuring-how-users-are-loaded\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch4 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eB) Configuring how Users are Loaded\u003c/h4\u003e\u003ca id=\"user-content-b-configuring-how-users-are-loaded\" class=\"anchor\" aria-label=\"Permalink: B) Configuring how Users are Loaded\" href=\"#b-configuring-how-users-are-loaded\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eWhen you type in your username, Symfony needs to load that user's information\nfrom somewhere. This is called a \"user provider\", and you're in charge of\nconfiguring it. Symfony has a built-in way to\n\u003ca href=\"#id17\"\u003e\u003cspan id=\"user-content-id18\"\u003e:doc:`load users from the database \u0026lt;/security/entity_provider\u0026gt;`\u003c/span\u003e\u003c/a\u003e,\nor you can \u003ca href=\"#id19\"\u003e\u003cspan id=\"user-content-id20\"\u003e:doc:`create your own user provider \u0026lt;/security/custom_provider\u0026gt;`\u003c/span\u003e\u003c/a\u003e.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eThe easiest (but most limited) way, is to configure Symfony to load hardcoded\nusers directly from the \u003ccode\u003esecurity.yml\u003c/code\u003e file itself. This is called an \"in memory\"\nprovider, but it's better to think of it as an \"in configuration\" provider:\u003c/p\u003e\n\u003cpre\u003e.. configuration-block::\n\n .. code-block:: yaml\n\n # app/config/security.yml\n security:\n providers:\n in_memory:\n memory:\n users:\n ryan:\n password: ryanpass\n roles: 'ROLE_USER'\n admin:\n password: kitten\n roles: 'ROLE_ADMIN'\n # ...\n\n .. code-block:: xml\n\n \u0026lt;!-- app/config/security.xml --\u0026gt;\n \u0026lt;?xml version=\"1.0\" encoding=\"UTF-8\"?\u0026gt;\n \u0026lt;srv:container xmlns=\"http://symfony.com/schema/dic/security\"\n xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n xmlns:srv=\"http://symfony.com/schema/dic/services\"\n xsi:schemaLocation=\"http://symfony.com/schema/dic/services\n http://symfony.com/schema/dic/services/services-1.0.xsd\"\u0026gt;\n\n \u0026lt;config\u0026gt;\n \u0026lt;provider name=\"in_memory\"\u0026gt;\n \u0026lt;memory\u0026gt;\n \u0026lt;user name=\"ryan\" password=\"ryanpass\" roles=\"ROLE_USER\" /\u0026gt;\n \u0026lt;user name=\"admin\" password=\"kitten\" roles=\"ROLE_ADMIN\" /\u0026gt;\n \u0026lt;/memory\u0026gt;\n \u0026lt;/provider\u0026gt;\n \u0026lt;!-- ... --\u0026gt;\n \u0026lt;/config\u0026gt;\n \u0026lt;/srv:container\u0026gt;\n\n .. code-block:: php\n\n // app/config/security.php\n $container-\u0026gt;loadFromExtension('se 8000 curity', array(\n 'providers' =\u0026gt; array(\n 'in_memory' =\u0026gt; array(\n 'memory' =\u0026gt; array(\n 'users' =\u0026gt; array(\n 'ryan' =\u0026gt; array(\n 'password' =\u0026gt; 'ryanpass',\n 'roles' =\u0026gt; 'ROLE_USER',\n ),\n 'admin' =\u0026gt; array(\n 'password' =\u0026gt; 'kitten',\n 'roles' =\u0026gt; 'ROLE_ADMIN',\n ),\n ),\n ),\n ),\n ),\n // ...\n ));\n\n\u003c/pre\u003e\n\u003cp dir=\"auto\"\u003eLike with \u003ccode\u003efirewalls\u003c/code\u003e, you can have multiple \u003ccode\u003eproviders\u003c/code\u003e, but you'll\nprobably only need one. If you \u003cem\u003edo\u003c/em\u003e have multiple, you can configure which\n\u003cem\u003eone\u003c/em\u003e provider to use for your firewall under its \u003ccode\u003eprovider\u003c/code\u003e key (e.g.\n\u003ccode\u003eprovider: in_memory\u003c/code\u003e).\u003c/p\u003e\n\u003cpre\u003e.. seealso::\n\n See :doc:`/security/multiple_user_providers` for\n all the details about multiple providers setup.\n\n\u003c/pre\u003e\n\u003cp dir=\"auto\"\u003eTry to login using username \u003ccode\u003eadmin\u003c/code\u003e and password \u003ccode\u003ekitten\u003c/code\u003e. You should\nsee an error!\u003c/p\u003e\n\u003cblockquote\u003e\nNo encoder has been configured for account \"Symfony\\Component\\Security\\Core\\User\\User\"\u003c/blockquote\u003e\n\u003cp dir=\"auto\"\u003eTo fix this, add an \u003ccode\u003eencoders\u003c/code\u003e key:\u003c/p\u003e\n\u003cpre\u003e.. configuration-block::\n\n .. code-block:: yaml\n\n # app/config/security.yml\n security:\n # ...\n\n encoders:\n Symfony\\Component\\Security\\Core\\User\\User: plaintext\n # ...\n\n .. code-block:: xml\n\n \u0026lt;!-- app/config/security.xml --\u0026gt;\n \u0026lt;?xml version=\"1.0\" encoding=\"UTF-8\"?\u0026gt;\n \u0026lt;srv:container xmlns=\"http://symfony.com/schema/dic/security\"\n xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n xmlns:srv=\"http://symfony.com/schema/dic/services\"\n xsi:schemaLocation=\"http://symfony.com/schema/dic/services\n http://symfony.com/schema/dic/services/services-1.0.xsd\"\u0026gt;\n\n \u0026lt;config\u0026gt;\n \u0026lt;!-- ... --\u0026gt;\n\n \u0026lt;encoder class=\"Symfony\\Component\\Security\\Core\\User\\User\"\n algorithm=\"plaintext\" /\u0026gt;\n \u0026lt;!-- ... --\u0026gt;\n \u0026lt;/config\u0026gt;\n \u0026lt;/srv:container\u0026gt;\n\n .. code-block:: php\n\n // app/config/security.php\n $container-\u0026gt;loadFromExtension('security', array(\n // ...\n\n 'encoders' =\u0026gt; array(\n 'Symfony\\Component\\Security\\Core\\User\\User' =\u0026gt; 'plaintext',\n ),\n // ...\n ));\n\n\u003c/pre\u003e\n\u003cp dir=\"auto\"\u003eUser providers load user information and put it into a \u003ccode\u003eUser\u003c/code\u003e object. If\nyou \u003ca href=\"#id21\"\u003e\u003cspan id=\"user-content-id22\"\u003e:doc:`load users from the database \u0026lt;/security/entity_provider\u0026gt;`\u003c/span\u003e\u003c/a\u003e\nor \u003ca href=\"#id23\"\u003e\u003cspan id=\"user-content-id24\"\u003e:doc:`some other source \u0026lt;/security/custom_provider\u0026gt;`\u003c/span\u003e\u003c/a\u003e, you'll\nuse your own custom User class. But when you use the \"in memory\" provider,\nit gives you a \u003ccode\u003eSymfony\\Component\\Security\\Core\\User\\User\u003c/code\u003e object.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eWhatever your User class is, you need to tell Symfony what algorithm was\nused to encode the passwords. In this case, the passwords are just plaintext,\nbut in a second, you'll change this to use \u003ccode\u003ebcrypt\u003c/code\u003e.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eIf you refresh now, you'll be logged in! The web debug toolbar even tells\nyou who you are and what roles you have:\u003c/p\u003e\n\u003cp dir=\"auto\"\u003e\u003ca target=\"_blank\" rel=\"noopener noreferrer\" href=\"/symfony/symfony-docs/blob/053cee723bf308ed6afac3eb185b09ec44209a6d/_images/security/symfony_loggedin_wdt.png\"\u003e\u003cimg alt=\"/_images/security/symfony_loggedin_wdt.png\" src=\"/symfony/symfony-docs/raw/053cee723bf308ed6afac3eb185b09ec44209a6d/_images/security/symfony_loggedin_wdt.png\" style=\"max-width: 100%;\"\u003e\u003c/a\u003e\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eBecause this URL requires \u003ccode\u003eROLE_ADMIN\u003c/code\u003e, if you had logged in as \u003ccode\u003eryan\u003c/code\u003e,\nthis would deny you access. More on that later (\u003ca href=\"#id25\"\u003e\u003cspan id=\"user-content-id26\"\u003e:ref:`security-authorization-access-control`\u003c/span\u003e\u003c/a\u003e).\u003c/p\u003e\n\u003ca name=\"user-content-loading-users-from-the-database\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch5 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eLoading Users from the Database\u003c/h5\u003e\u003ca id=\"user-content-loading-users-from-the-database\" class=\"anchor\" aria-label=\"Permalink: Loading Users from the Database\" href=\"#loading-users-from-the-database\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eIf you'd like to load your users via the Doctrine ORM, that's easy! See\n\u003ca href=\"#id27\"\u003e\u003cspan id=\"user-content-id28\"\u003e:doc:`/security/entity_provider`\u003c/span\u003e\u003c/a\u003e for all the details.\u003c/p\u003e\n\u003ca name=\"user-content-c-encoding-the-user-s-password\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch4 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eC) Encoding the User's Password\u003c/h4\u003e\u003ca id=\"user-content-c-encoding-the-users-password\" class=\"anchor\" aria-label=\"Permalink: C) Encoding the User's Password\" href=\"#c-encoding-the-users-password\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eWhether your users are stored in \u003ccode\u003esecurity.yml\u003c/code\u003e, in a database or somewhere\nelse, you'll want to encode their passwords. The best algorithm to use is\n\u003ccode\u003ebcrypt\u003c/code\u003e:\u003c/p\u003e\n\u003cpre\u003e.. configuration-block::\n\n .. code-block:: yaml\n\n # app/config/security.yml\n security:\n # ...\n\n encoders:\n Symfony\\Component\\Security\\Core\\User\\User:\n algorithm: bcrypt\n cost: 12\n\n .. code-block:: xml\n\n \u0026lt;!-- app/config/security.xml --\u0026gt;\n \u0026lt;?xml version=\"1.0\" encoding=\"UTF-8\"?\u0026gt;\n \u0026lt;srv:container xmlns=\"http://symfony.com/schema/dic/security\"\n xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n xmlns:srv=\"http://symfony.com/schema/dic/services\"\n xsi:schemaLocation=\"http://symfony.com/schema/dic/services\n http://symfony.com/schema/dic/services/services-1.0.xsd\"\u0026gt;\n\n \u0026lt;config\u0026gt;\n \u0026lt;!-- ... --\u0026gt;\n\n \u0026lt;encoder class=\"Symfony\\Component\\Security\\Core\\User\\User\"\n algorithm=\"bcrypt\"\n cost=\"12\" /\u0026gt;\n\n \u0026lt;!-- ... --\u0026gt;\n \u0026lt;/config\u0026gt;\n \u0026lt;/srv:container\u0026gt;\n\n .. code-block:: php\n\n // app/config/security.php\n $container-\u0026gt;loadFromExtension('security', array(\n // ...\n\n 'encoders' =\u0026gt; array(\n 'Symfony\\Component\\Security\\Core\\User\\User' =\u0026gt; array(\n 'algorithm' =\u0026gt; 'bcrypt',\n 'cost' =\u0026gt; 12,\n )\n ),\n // ...\n ));\n\n\u003c/pre\u003e\n\u003cp dir=\"auto\"\u003eOf course, your users' passwords now need to be encoded with this exact algorithm.\nFor hardcoded users, since 2.7 you can use the built-in command:\u003c/p\u003e\n\u003cpre lang=\"terminal\"\u003e$ php app/console security:encode-password\n\u003c/pre\u003e\n\u003cp dir=\"auto\"\u003eIt will give you something like this:\u003c/p\u003e\n\u003cpre\u003e.. configuration-block::\n\n .. code-block:: yaml\n\n # app/config/security.yml\n security:\n # ...\n\n providers:\n in_memory:\n memory:\n users:\n ryan:\n password: $2a$12$LCY0MefVIEc3TYPHV9SNnuzOfyr2p/AXIGoQJEDs4am4JwhNz/jli\n roles: 'ROLE_USER'\n admin:\n password: $2a$12$cyTWeE9kpq1PjqKFiWUZFuCRPwVyAZwm4XzMZ1qPUFl7/flCM3V0G\n roles: 'ROLE_ADMIN'\n\n .. code-block:: xml\n\n \u0026lt;!-- app/config/security.xml --\u0026gt;\n \u0026lt;?xml version=\"1.0\" encoding=\"UTF-8\"?\u0026gt;\n \u0026lt;srv:container xmlns=\"http://symfony.com/schema/dic/security\"\n xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n xmlns:srv=\"http://symfony.com/schema/dic/services\"\n xsi:schemaLocation=\"http://symfony.com/schema/dic/services\n http://symfony.com/schema/dic/services/services-1.0.xsd\"\u0026gt;\n\n \u0026lt;config\u0026gt;\n \u0026lt;!-- ... --\u0026gt;\n\n \u0026lt;provider name=\"in_memory\"\u0026gt;\n \u0026lt;memory\u0026gt;\n \u0026lt;user name=\"ryan\" password=\"$2a$12$LCY0MefVIEc3TYPHV9SNnuzOfyr2p/AXIGoQJEDs4am4JwhNz/jli\" roles=\"ROLE_USER\" /\u0026gt;\n \u0026lt;user name=\"admin\" password=\"$2a$12$cyTWeE9kpq1PjqKFiWUZFuCRPwVyAZwm4XzMZ1qPUFl7/flCM3V0G\" roles=\"ROLE_ADMIN\" /\u0026gt;\n \u0026lt;/memory\u0026gt;\n \u0026lt;/provider\u0026gt;\n \u0026lt;/config\u0026gt;\n \u0026lt;/srv:container\u0026gt;\n\n .. code-block:: php\n\n // app/config/security.php\n $container-\u0026gt;loadFromExtension('security', array(\n // ...\n\n 'providers' =\u0026gt; array(\n 'in_memory' =\u0026gt; array(\n 'memory' =\u0026gt; array(\n 'users' =\u0026gt; array(\n 'ryan' =\u0026gt; array(\n 'password' =\u0026gt; '$2a$12$LCY0MefVIEc3TYPHV9SNnuzOfyr2p/AXIGoQJEDs4am4JwhNz/jli',\n 'roles' =\u0026gt; 'ROLE_USER',\n ),\n 'admin' =\u0026gt; array(\n 'password' =\u0026gt; '$2a$12$cyTWeE9kpq1PjqKFiWUZFuCRPwVyAZwm4XzMZ1qPUFl7/flCM3V0G',\n 'roles' =\u0026gt; 'ROLE_ADMIN',\n ),\n ),\n ),\n ),\n ),\n // ...\n ));\n\n\u003c/pre\u003e\n\u003cp dir=\"auto\"\u003eEverything will now work exactly like before. But if you have dynamic users\n(e.g. from a database), how can you programmatically encode the password\nbefore inserting them into the database? Don't worry, see\n\u003ca href=\"#id29\"\u003e\u003cspan id=\"user-content-id30\"\u003e:doc:`/security/password_encoding`\u003c/span\u003e\u003c/a\u003e for details.\u003c/p\u003e\n\u003cdiv dir=\"auto\"\u003e\n\u003cp dir=\"auto\"\u003eTip\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eSupported algorithms for this method depend on your PHP version, but\ninclude the algorithms returned by the PHP function \u003ca href=\"#id31\"\u003e\u003cspan id=\"user-content-id32\"\u003e:phpfunction:`hash_algos`\u003c/span\u003e\u003c/a\u003e\nas well as a few others (e.g. bcrypt). See the \u003ccode\u003eencoders\u003c/code\u003e key in the\n\u003ca href=\"#id33\"\u003e\u003cspan id=\"user-content-id34\"\u003e:doc:`Security Reference Section \u0026lt;/reference/configuration/security\u0026gt;`\u003c/span\u003e\u003c/a\u003e\nfor examples.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eIt's also possible to use different hashing algorithms on a user-by-user\nbasis. See \u003ca href=\"#id35\"\u003e\u003cspan id=\"user-content-id36\"\u003e:doc:`/security/named_encoders`\u003c/span\u003e\u003c/a\u003e for more details.\u003c/p\u003e\n\u003c/div\u003e\n\u003ca name=\"user-content-d-configuration-done\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch4 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eD) Configuration Done!\u003c/h4\u003e\u003ca id=\"user-content-d-configuration-done\" class=\"anchor\" aria-label=\"Permalink: D) Configuration Done!\" href=\"#d-configuration-done\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eCongratulations! You now have a working authentication system that uses HTTP\nbasic auth and loads users right from the \u003ccode\u003esecurity.yml\u003c/code\u003e file.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eYour next steps depend on your setup:\u003c/p\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003eConfigure a different way for your users to login, like a \u003ca href=\"#id37\"\u003e\u003cspan id=\"user-content-id38\"\u003e:ref:`login form \u0026lt;security-form-login\u0026gt;`\u003c/span\u003e\u003c/a\u003e\nor \u003ca href=\"#id39\"\u003e\u003cspan id=\"user-content-id40\"\u003e:doc:`something completely custom \u0026lt;/security/custom_authentication_provider\u0026gt;`\u003c/span\u003e\u003c/a\u003e;\u003c/li\u003e\n\u003cli\u003eLoad users from a different source, like the \u003ca href=\"#id41\"\u003e\u003cspan id=\"user-content-id42\"\u003e:doc:`database \u0026lt;/security/entity_provider\u0026gt;`\u003c/span\u003e\u003c/a\u003e\nor \u003ca href=\"#id43\"\u003e\u003cspan id=\"user-content-id44\"\u003e:doc:`some other source \u0026lt;/security/custom_provider\u0026gt;`\u003c/span\u003e\u003c/a\u003e;\u003c/li\u003e\n\u003cli\u003eLearn how to deny access, load the User object and deal with roles in the\n\u003ca href=\"#id45\"\u003e\u003cspan id=\"user-content-id46\"\u003e:ref:`Authorization \u0026lt;security-authorization\u0026gt;`\u003c/span\u003e\u003c/a\u003e section.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ca name=\"user-content-denying-access-roles-and-other-authorization\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003e2) Denying Access, Roles and other Authorization\u003c/h3\u003e\u003ca id=\"user-content-2-denying-access-roles-and-other-authorization\" class=\"anchor\" aria-label=\"Permalink: 2) Denying Access, Roles and other Authorization\" href=\"#2-denying-access-roles-and-other-authorization\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eUsers can now login to your app using \u003ccode\u003ehttp_basic\u003c/code\u003e or some other method.\nGreat! Now, you need to learn how to deny access and work with the User object.\nThis is called \u003cstrong\u003eauthorization\u003c/strong\u003e, and its job is to decide if a user can\naccess some resource (a URL, a model object, a method call, ...).\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eThe process of authorization has two different sides:\u003c/p\u003e\n\u003col dir=\"auto\"\u003e\n\u003cli\u003eThe user receives a specific set of roles when logging in (e.g. \u003ccode\u003eROLE_ADMIN\u003c/code\u003e).\u003c/li\u003e\n\u003cli\u003eYou add code so that a resource (e.g. URL, controller) requires a specific\n\"attribute\" (most commonly a role like \u003ccode\u003eROLE_ADMIN\u003c/code\u003e) in order to be\naccessed.\u003c/li\u003e\n\u003c/ol\u003e\n\u003cdiv dir=\"auto\"\u003e\n\u003cp dir=\"auto\"\u003eTip\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eIn addition to roles (e.g. \u003ccode\u003eROLE_ADMIN\u003c/code\u003e), you can protect a resource\nusing other attributes/strings (e.g. \u003ccode\u003eEDIT\u003c/code\u003e) and use voters or Symfony's\nACL system to give these meaning. This might come in handy if you need\nto check if user A can \"EDIT\" some object B (e.g. a Product with id 5).\nSee \u003ca href=\"#id47\"\u003e\u003cspan id=\"user-content-id48\"\u003e:ref:`security-secure-objects`\u003c/span\u003e\u003c/a\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003ca name=\"user-content-roles\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch4 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eRoles\u003c/h4\u003e\u003ca id=\"user-content-roles\" class=\"anchor\" aria-label=\"Permalink: Roles\" href=\"#roles\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eWhen a user logs in, they receive a set of roles (e.g. \u003ccode\u003eROLE_ADMIN\u003c/code\u003e). In\nthe example above, these are hardcoded into \u003ccode\u003esecurity.yml\u003c/code\u003e. If you're\nloading users from the database, these are probably stored on a column\nin your table.\u003c/p\u003e\n\u003cdiv dir=\"auto\"\u003e\n\u003cp dir=\"auto\"\u003eCaution!\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eAll roles you assign to a user \u003cstrong\u003emust\u003c/strong\u003e begin with the \u003ccode\u003eROLE_\u003c/code\u003e prefix.\nOtherwise, they won't be handled by Symfony's security system in the\nnormal way (i.e. unless you're doing something advanced, assigning a\nrole like \u003ccode\u003eFOO\u003c/code\u003e to a user and then checking for \u003ccode\u003eFOO\u003c/code\u003e as described\n\u003ca href=\"#id49\"\u003e\u003cspan id=\"user-content-id50\"\u003e:ref:`below \u0026lt;security-role-authorization\u0026gt;`\u003c/span\u003e\u003c/a\u003e will not work).\u003c/p\u003e\n\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eRoles are simple, and are basically strings that you invent and use as needed.\nFor example, if you need to start limiting access to the blog admin section\nof your website, you could protect that section using a \u003ccode\u003eROLE_BLOG_ADMIN\u003c/code\u003e\nrole. This role doesn't need to be defined anywhere - you can just start using\nit.\u003c/p\u003e\n\u003cdiv dir=\"auto\"\u003e\n\u003cp dir=\"auto\"\u003eTip\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eMake sure every user has at least \u003cem\u003eone\u003c/em\u003e role, or your user will look\nlike they're not authenticated. A common convention is to give \u003cem\u003eevery\u003c/em\u003e\nuser \u003ccode\u003eROLE_USER\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eYou can also specify a \u003ca href=\"#id51\"\u003e\u003cspan id=\"user-content-id52\"\u003e:ref:`role hierarchy \u0026lt;security-role-hierarchy\u0026gt;`\u003c/span\u003e\u003c/a\u003e where\nsome roles automatically mean that you also have other roles.\u003c/p\u003e\n\u003ca name=\"user-content-add-code-to-deny-access\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch4 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eAdd Code to Deny Access\u003c/h4\u003e\u003ca id=\"user-content-add-code-to-deny-access\" class=\"anchor\" aria-label=\"Permalink: Add Code to Deny Access\" href=\"#add-code-to-deny-access\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eThere are \u003cstrong\u003etwo\u003c/strong\u003e ways to deny access to something:\u003c/p\u003e\n\u003col dir=\"auto\"\u003e\n\u003cli\u003e\u003ca href=\"#id53\"\u003e\u003cspan id=\"user-content-id54\"\u003e:ref:`access_control in security.yml \u0026lt;security-authorization-access-control\u0026gt;`\u003c/span\u003e\u003c/a\u003e\nallows you to protect URL patterns (e.g. \u003ccode\u003e/admin/*\u003c/code\u003e). This is easy,\nbut less flexible;\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"#id55\"\u003e\u003cspan id=\"user-content-id56\"\u003e:ref:`in your code via the security.authorization_checker service \u0026lt;security-securing-controller\u0026gt;`\u003c/span\u003e\u003c/a\u003e.\u003c/li\u003e\n\u003c/ol\u003e\n\u003ca name=\"user-content-securing-url-patterns-access-control\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch5 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eSecuring URL patterns (access_control)\u003c/h5\u003e\u003ca id=\"user-content-securing-url-patterns-access_control\" class=\"anchor\" aria-label=\"Permalink: Securing URL patterns (access_control)\" href=\"#securing-url-patterns-access_control\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eThe most basic way to secure part of your application is to secure an entire\nURL pattern. You saw this earlier, where anything matching the regular expression\n\u003ccode\u003e^/admin\u003c/code\u003e requires the \u003ccode\u003eROLE_ADMIN\u003c/code\u003e role:\u003c/p\u003e\n\u003cpre\u003e.. configuration-block::\n\n .. code-block:: yaml\n\n # app/config/security.yml\n security:\n # ...\n\n firewalls:\n # ...\n default:\n # ...\n\n access_control:\n # require ROLE_ADMIN for /admin*\n - { path: ^/admin, roles: ROLE_ADMIN }\n\n .. code-block:: xml\n\n \u0026lt;!-- app/config/security.xml --\u0026gt;\n \u0026lt;?xml version=\"1.0\" encoding=\"UTF-8\"?\u0026gt;\n \u0026lt;srv:container xmlns=\"http://symfony.com/schema/dic/security\"\n xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n xmlns:srv=\"http://symfony.com/schema/dic/services\"\n xsi:schemaLocation=\"http://symfony.com/schema/dic/services\n http://symfony.com/schema/dic/services/services-1.0.xsd\"\u0026gt;\n\n \u0026lt;config\u0026gt;\n \u0026lt;!-- ... --\u0026gt;\n\n \u0026lt;firewall name=\"default\"\u0026gt;\n \u0026lt;!-- ... --\u0026gt;\n \u0026lt;/firewall\u0026gt;\n\n \u0026lt;!-- require ROLE_ADMIN for /admin* --\u0026gt;\n \u0026lt;rule path=\"^/admin\" role=\"ROLE_ADMIN\" /\u0026gt;\n \u0026lt;/config\u0026gt;\n \u0026lt;/srv:container\u0026gt;\n\n .. code-block:: php\n\n // app/config/security.php\n $container-\u0026gt;loadFromExtension('security', array(\n // ...\n\n 'firewalls' =\u0026gt; array(\n // ...\n 'default' =\u0026gt; array(\n // ...\n ),\n ),\n 'access_control' =\u0026gt; array(\n // require ROLE_ADMIN for /admin*\n array('path' =\u0026gt; '^/admin', 'role' =\u0026gt; 'ROLE_ADMIN'),\n ),\n ));\n\n\u003c/pre\u003e\n\u003cp dir=\"auto\"\u003eThis is great for securing entire sections, but you'll also probably want\nto \u003ca href=\"#id57\"\u003e\u003cspan id=\"user-content-id58\"\u003e:ref:`secure your individual controllers \u0026lt;security-securing-controller\u0026gt;`\u003c/span\u003e\u003c/a\u003e\nas well.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eYou can define as many URL patterns as you need - each is a regular expression.\n\u003cstrong\u003eBUT\u003c/strong\u003e, only \u003cstrong\u003eone\u003c/strong\u003e will be matched. Symfony will look at each starting\nat the top, and stop as soon as it finds one \u003ccode\u003eaccess_control\u003c/code\u003e entry that\nmatches the URL.\u003c/p\u003e\n\u003cpre\u003e.. configuration-block::\n\n .. code-block:: yaml\n\n # app/config/security.yml\n security:\n # ...\n\n access_control:\n - { path: ^/admin/users, roles: ROLE_SUPER_ADMIN }\n - { path: ^/admin, roles: ROLE_ADMIN }\n\n .. code-block:: xml\n\n \u0026lt;!-- app/config/security.xml --\u0026gt;\n \u0026lt;?xml version=\"1.0\" encoding=\"UTF-8\"?\u0026gt;\n \u0026lt;srv:container xmlns=\"http://symfony.com/schema/dic/security\"\n xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n xmlns:srv=\"http://symfony.com/schema/dic/services\"\n xsi:schemaLocation=\"http://symfony.com/schema/dic/services\n http://symfony.com/schema/dic/services/services-1.0.xsd\"\u0026gt;\n\n \u0026lt;config\u0026gt;\n \u0026lt;!-- ... --\u0026gt;\n\n \u0026lt;rule path=\"^/admin/users\" role=\"ROLE_SUPER_ADMIN\" /\u0026gt;\n \u0026lt;rule path=\"^/admin\" role=\"ROLE_ADMIN\" /\u0026gt;\n \u0026lt;/config\u0026gt;\n \u0026lt;/srv:container\u0026gt;\n\n .. code-block:: php\n\n // app/config/security.php\n $container-\u0026gt;loadFromExtension('security', array(\n // ...\n\n 'access_control' =\u0026gt; array(\n array('path' =\u0026gt; '^/admin/users', 'role' =\u0026gt; 'ROLE_SUPER_ADMIN'),\n array('path' =\u0026gt; '^/admin', 'role' =\u0026gt; 'ROLE_ADMIN'),\n ),\n ));\n\n\u003c/pre\u003e\n\u003cp dir=\"auto\"\u003ePrepending the path with \u003ccode\u003e^\u003c/code\u003e means that only URLs \u003cem\u003ebeginning\u003c/em\u003e with the\npattern are matched. For example, a path of simply \u003ccode\u003e/admin\u003c/code\u003e (without\nthe \u003ccode\u003e^\u003c/code\u003e) would match \u003ccode\u003e/admin/foo\u003c/code\u003e but would also match URLs like \u003ccode\u003e/foo/admin\u003c/code\u003e.\u003c/p\u003e\n\u003cdiv id=\"user-content-security-access-control-explanation\" dir=\"auto\"\u003e\n\u003cp dir=\"auto\"\u003eUnderstanding how \u003ccode\u003eaccess_control\u003c/code\u003e Works\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eThe \u003ccode\u003eaccess_control\u003c/code\u003e section is very powerful, but it can also be dangerous\n(because it involves security) if you don't understand \u003cem\u003ehow\u003c/em\u003e it works.\nIn addition to the URL, the \u003ccode\u003eaccess_control\u003c/code\u003e can match on IP address,\nhost name and HTTP methods. It can also be used to redirect a user to\nthe \u003ccode\u003ehttps\u003c/code\u003e version of a URL pattern.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eTo learn about all of this, see \u003ca href=\"#id59\"\u003e\u003cspan id=\"user-content-id60\"\u003e:doc:`/security/access_control`\u003c/span\u003e\u003c/a\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003ca name=\"user-content-securing-controllers-and-other-code\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch5 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eSecuring Controllers and other Code\u003c/h5\u003e\u003ca id=\"user-content-securing-controllers-and-other-code\" class=\"anchor\" aria-label=\"Permalink: Securing Controllers and other Code\" href=\"#securing-controllers-and-other-code\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0 8000 l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eYou can easily deny access from inside a controller:\u003c/p\u003e\n\u003cpre\u003e// ...\n\npublic function helloAction($name)\n{\n // The second parameter is used to specify on what object the role is tested.\n $this-\u0026gt;denyAccessUnlessGranted('ROLE_ADMIN', null, 'Unable to access this page!');\n\n // Old way :\n // if (false === $this-\u0026gt;get('security.authorization_checker')-\u0026gt;isGranted('ROLE_ADMIN')) {\n // throw $this-\u0026gt;createAccessDeniedException('Unable to access this page!');\n // }\n\n // ...\n}\n\u003c/pre\u003e\n\u003cpre\u003e.. versionadded:: 2.6\n The ``denyAccessUnlessGranted()`` method was introduced in Symfony 2.6. Previously (and\n still now), you could check access directly and throw the ``AccessDeniedException`` as shown\n in the example above).\n\n\u003c/pre\u003e\n\u003cpre\u003e.. versionadded:: 2.6\n The ``security.authorization_checker`` service was introduced in Symfony 2.6. Prior\n to Symfony 2.6, you had to use the ``isGranted()`` method of the ``security.context`` service.\n\n\u003c/pre\u003e\n\u003cp dir=\"auto\"\u003eIn both cases, a special\n\u003ca href=\"#id61\"\u003e\u003cspan id=\"user-content-id62\"\u003e:class:`Symfony\\\\Component\\\\Security\\\\Core\\\\Exception\\\\AccessDeniedException`\u003c/span\u003e\u003c/a\u003e\nis thrown, which ultimately triggers a 403 HTTP response inside Symfony.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eThat's it! If the user isn't logged in yet, they will be asked to login (e.g.\nredirected to the login page). If they \u003cem\u003eare\u003c/em\u003e logged in, but do \u003cem\u003enot\u003c/em\u003e have the\n\u003ccode\u003eROLE_ADMIN\u003c/code\u003e role, they'll be shown the 403 access denied page (which you can\n\u003ca href=\"#id63\"\u003e\u003cspan id=\"user-content-id64\"\u003e:ref:`customize \u0026lt;controller-error-pages-by-status-code\u0026gt;`\u003c/span\u003e\u003c/a\u003e). If they are logged in\nand have the correct roles, the code will be executed.\u003c/p\u003e\n\u003cp id=\"user-content-security-securing-controller-annotations\" dir=\"auto\"\u003eThanks to the SensioFrameworkExtraBundle, you can also secure your controller\nusing annotations:\u003c/p\u003e\n\u003cpre\u003e// ...\nuse Sensio\\Bundle\\FrameworkExtraBundle\\Configuration\\Security;\n\n/**\n * @Security(\"has_role('ROLE_ADMIN')\")\n */\npublic function helloAction($name)\n{\n // ...\n}\n\u003c/pre\u003e\n\u003cp dir=\"auto\"\u003eFor more information, see the \u003ca href=\"https://symfony.com/doc/current/bundles/SensioFrameworkExtraBundle/index.html\" rel=\"nofollow\"\u003eFrameworkExtraBundle documentation\u003c/a\u003e.\u003c/p\u003e\n\u003ca name=\"user-content-access-control-in-templates\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch5 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eAccess Control in Templates\u003c/h5\u003e\u003ca id=\"user-content-access-control-in-templates\" class=\"anchor\" aria-label=\"Permalink: Access Control in Templates\" href=\"#access-control-in-templates\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eIf you want to check if the current user has a role inside a template, use\nthe built-in helper function:\u003c/p\u003e\n\u003cpre\u003e.. configuration-block::\n\n .. code-block:: html+twig\n\n {% if is_granted('ROLE_ADMIN') %}\n \u0026lt;a href=\"...\"\u0026gt;Delete\u0026lt;/a\u0026gt;\n {% endif %}\n\n .. code-block:: html+php\n\n \u0026lt;?php if ($view['security']-\u0026gt;isGranted('ROLE_ADMIN')): ?\u0026gt;\n \u0026lt;a href=\"...\"\u0026gt;Delete\u0026lt;/a\u0026gt;\n \u0026lt;?php endif ?\u0026gt;\n\n\u003c/pre\u003e\n\u003cp dir=\"auto\"\u003eIf you use this function and you are \u003cem\u003enot\u003c/em\u003e behind a firewall, an exception will\nbe thrown. Again, it's almost always a good idea to have a main firewall that\ncovers all URLs (as shown before in this article).\u003c/p\u003e\n\u003cdiv dir=\"auto\"\u003e\n\u003cp dir=\"auto\"\u003eCaution!\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eBe careful with this in your base layout or on your error pages! Because of\nsome internal Symfony details, to avoid broken error pages in the \u003ccode\u003eprod\u003c/code\u003e\nenvironment, wrap calls in these templates with a check for \u003ccode\u003eapp.user\u003c/code\u003e:\u003c/p\u003e\n\u003cpre lang=\"html+twig\"\u003e{% if app.user and is_granted('ROLE_ADMIN') %}\n\u003c/pre\u003e\n\u003c/div\u003e\n\u003ca name=\"user-content-securing-other-services\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch5 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eSecuring other Services\u003c/h5\u003e\u003ca id=\"user-content-securing-other-services\" class=\"anchor\" aria-label=\"Permalink: Securing other Services\" href=\"#securing-other-services\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eAnything in Symfony can be protected by doing something similar to the code\nused to secure a controller. For example, suppose you have a service (i.e. a\nPHP class) whose job is to send emails. You can restrict use of this class - no\nmatter where it's being used from - to only certain users.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eFor more information see \u003ca href=\"#id65\"\u003e\u003cspan id=\"user-content-id66\"\u003e:doc:`/security/securing_services`\u003c/span\u003e\u003c/a\u003e.\u003c/p\u003e\n\u003ca name=\"user-content-checking-to-see-if-a-user-is-logged-in-is-authenticated-fully\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch4 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eChecking to see if a User is Logged In (IS_AUTHENTICATED_FULLY)\u003c/h4\u003e\u003ca id=\"user-content-checking-to-see-if-a-user-is-logged-in-is_authenticated_fully\" class=\"anchor\" aria-label=\"Permalink: Checking to see if a User is Logged In (IS_AUTHENTICATED_FULLY)\" href=\"#checking-to-see-if-a-user-is-logged-in-is_authenticated_fully\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eSo far, you've checked access based on roles - those strings that start with\n\u003ccode\u003eROLE_\u003c/code\u003e and are assigned to users. But if you \u003cem\u003eonly\u003c/em\u003e want to check if a\nuser is logged in (you don't care about roles), then you can use\n\u003ccode\u003eIS_AUTHENTICATED_FULLY\u003c/code\u003e:\u003c/p\u003e\n\u003cpre\u003e// ...\n\npublic function helloAction($name)\n{\n if (!$this-\u0026gt;get('security.authorization_checker')-\u0026gt;isGranted('IS_AUTHENTICATED_FULLY')) {\n throw $this-\u0026gt;createAccessDeniedException();\n }\n\n // ...\n}\n\u003c/pre\u003e\n\u003cdiv dir=\"auto\"\u003e\n\u003cp dir=\"auto\"\u003eTip\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eYou can of course also use this in \u003ccode\u003eaccess_control\u003c/code\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e\u003ccode\u003eIS_AUTHENTICATED_FULLY\u003c/code\u003e isn't a role, but it kind of acts like one, and every\nuser that has successfully logged in will have this. In fact, there are three\nspecial attributes like this:\u003c/p\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003e\u003ccode\u003eIS_AUTHENTICATED_REMEMBERED\u003c/code\u003e: \u003cem\u003eAll\u003c/em\u003e logged in users have this, even\nif they are logged in because of a \"remember me cookie\". Even if you don't\nuse the \u003ca href=\"#id67\"\u003e\u003cspan id=\"user-content-id68\"\u003e:doc:`remember me functionality \u0026lt;/security/remember_me\u0026gt;`\u003c/span\u003e\u003c/a\u003e,\nyou can use this to check if the user is logged in.\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eIS_AUTHENTICATED_FULLY\u003c/code\u003e: This is similar to \u003ccode\u003eIS_AUTHENTICATED_REMEMBERED\u003c/code\u003e,\nbut stronger. Users who are logged in only because of a \"remember me cookie\"\nwill have \u003ccode\u003eIS_AUTHENTICATED_REMEMBERED\u003c/code\u003e but will not have \u003ccode\u003eIS_AUTHENTICATED_FULLY\u003c/code\u003e.\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eIS_AUTHENTICATED_ANONYMOUSLY\u003c/code\u003e: \u003cem\u003eAll\u003c/em\u003e users (even anonymous ones) have\nthis - this is useful when \u003cem\u003ewhitelisting\u003c/em\u003e URLs to guarantee access - some\ndetails are in \u003ca href=\"#id69\"\u003e\u003cspan id=\"user-content-id70\"\u003e:doc:`/security/access_control`\u003c/span\u003e\u003c/a\u003e.\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp id=\"user-content-security-template-expression\" dir=\"auto\"\u003eYou can also use expressions inside your templates:\u003c/p\u003e\n\u003cpre\u003e.. configuration-block::\n\n .. code-block:: html+jinja\n\n {% if is_granted(expression(\n '\"ROLE_ADMIN\" in roles or (user and user.isSuperAdmin())'\n )) %}\n \u0026lt;a href=\"...\"\u0026gt;Delete\u0026lt;/a\u0026gt;\n {% endif %}\n\n .. code-block:: html+php\n\n \u0026lt;?php if ($view['security']-\u0026gt;isGranted(new Expression(\n '\"ROLE_ADMIN\" in roles or (user and user.isSuperAdmin())'\n ))): ?\u0026gt;\n \u0026lt;a href=\"...\"\u0026gt;Delete\u0026lt;/a\u0026gt;\n \u0026lt;?php endif; ?\u0026gt;\n\n\u003c/pre\u003e\n\u003cp dir=\"auto\"\u003eFor more details on expressions and security, see \u003ca href=\"#id71\"\u003e\u003cspan id=\"user-content-id72\"\u003e:ref:`expressions-security`\u003c/span\u003e\u003c/a\u003e.\u003c/p\u003e\n\u003ca name=\"user-content-access-control-lists-acls-securing-individual-database-objects\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch4 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eAccess Control Lists (ACLs): Securing individual Database Objects\u003c/h4\u003e\u003ca id=\"user-content-access-control-lists-acls-securing-individual-database-objects\" class=\"anchor\" aria-label=\"Permalink: Access Control Lists (ACLs): Securing individual Database Objects\" href=\"#access-control-lists-acls-securing-individual-database-objects\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eImagine you are designing a blog where users can comment on your posts. You\nalso want a user to be able to edit their own comments, but not those of\nother users. Also, as the admin user, you yourself want to be able to edit\n\u003cem\u003eall\u003c/em\u003e comments.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eTo accomplish this you have 2 options:\u003c/p\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003e\u003ca href=\"#id73\"\u003e\u003cspan id=\"user-content-id74\"\u003e:doc:`Voters \u0026lt;/security/voters\u0026gt;`\u003c/span\u003e\u003c/a\u003e allow you to write own business logic\n(e.g. the user can edit this post because they were the creator) to determine\naccess. You'll probably want this option - it's flexible enough to solve the\nabove situation.\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"#id75\"\u003e\u003cspan id=\"user-content-id76\"\u003e:doc:`ACLs \u0026lt;/security/acl\u0026gt;`\u003c/span\u003e\u003c/a\u003e allow you to create a database structure\nwhere you can assign \u003cem\u003eany\u003c/em\u003e arbitrary user \u003cem\u003eany\u003c/em\u003e access (e.g. EDIT, VIEW)\nto \u003cem\u003eany\u003c/em\u003e object in your system. Use this if you need an admin user to be\nable to grant customized access across your system via some admin interface.\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp dir=\"auto\"\u003eIn both cases, you'll still deny access using methods similar to what was\nshown above.\u003c/p\u003e\n\u003ca name=\"user-content-retrieving-the-user-object\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eRetrieving the User Object\u003c/h3\u003e\u003ca id=\"user-content-retrieving-the-user-object\" class=\"anchor\" aria-label=\"Permalink: Retrieving the User Object\" href=\"#retrieving-the-user-object\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cpre\u003e.. versionadded:: 2.6\n The ``security.token_storage`` service was introduced in Symfony 2.6. Prior\n to Symfony 2.6, you had to use the ``getToken()`` method of the ``security.context`` service.\n\n\u003c/pre\u003e\n\u003cp dir=\"auto\"\u003eAfter authentication, the \u003ccode\u003eUser\u003c/code\u003e object of the current user can be accessed\nvia the \u003ccode\u003esecurity.token_storage\u003c/code\u003e service. From inside a controller, this will\nlook like:\u003c/p\u003e\n\u003cpre\u003epublic function indexAction()\n{\n if (!$this-\u0026gt;get('security.authorization_checker')-\u0026gt;isGranted('IS_AUTHENTICATED_FULLY')) {\n throw $this-\u0026gt;createAccessDeniedException();\n }\n\n $user = $this-\u0026gt;getUser();\n\n // the above is a shortcut for this\n $user = $this-\u0026gt;get('security.token_storage')-\u0026gt;getToken()-\u0026gt;getUser();\n}\n\u003c/pre\u003e\n\u003cdiv dir=\"auto\"\u003e\n\u003cp dir=\"auto\"\u003eTip\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eThe user will be an object and the class of that object will depend on\nyour \u003ca href=\"#id77\"\u003e\u003cspan id=\"user-content-id78\"\u003e:ref:`user provider \u0026lt;security-user-providers\u0026gt;`\u003c/span\u003e\u003c/a\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eNow you can call whatever methods are on \u003cem\u003eyour\u003c/em\u003e User object. For example,\nif your User object has a \u003ccode\u003egetFirstName()\u003c/code\u003e method, you could use that:\u003c/p\u003e\n\u003cpre\u003euse Symfony\\Component\\HttpFoundation\\Response;\n// ...\n\npublic function indexAction()\n{\n // ...\n\n return new Response('Well hi there '.$user-\u0026gt;getFirstName());\n}\n\u003c/pre\u003e\n\u003ca name=\"user-content-always-check-if-the-user-is-logged-in\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch4 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eAlways Check if the User is Logged In\u003c/h4\u003e\u003ca id=\"user-content-always-check-if-the-user-is-logged-in\" class=\"anchor\" aria-label=\"Permalink: Always Check if the User is Logged In\" href=\"#always-check-if-the-user-is-logged-in\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eIt's important to check if the user is authenticated first. If they're not,\n\u003ccode\u003e$user\u003c/code\u003e will either be \u003ccode\u003enull\u003c/code\u003e or the string \u003ccode\u003eanon.\u003c/code\u003e. Wait, what? Yes,\nthis is a quirk. If you're not logged in, the user is technically the string\n\u003ccode\u003eanon.\u003c/code\u003e, though the \u003ccode\u003egetUser()\u003c/code\u003e controller shortcut converts this to\n\u003ccode\u003enull\u003c/code\u003e for convenience.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eThe point is this: always check to see if the user is logged in before using\nthe User object, and use the \u003ccode\u003eisGranted()\u003c/code\u003e method (or\n\u003ca href=\"#id79\"\u003e\u003cspan id=\"user-content-id80\"\u003e:ref:`access_control \u0026lt;security-authorization-access-control\u0026gt;`\u003c/span\u003e\u003c/a\u003e) to do this:\u003c/p\u003e\n\u003cpre\u003e// yay! Use this to see if the user is logged in\nif (!$this-\u0026gt;get('security.authorization_checker')-\u0026gt;isGranted('IS_AUTHENTICATED_FULLY')) {\n throw $this-\u0026gt;createAccessDeniedException();\n}\n\n// boo :(. Never check for the User object to see if they're logged in\nif ($this-\u0026gt;getUser()) {\n\n}\n\u003c/pre\u003e\n\u003ca name=\"user-content-retrieving-the-user-in-a-template\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch4 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eRetrieving the User in a Template\u003c/h4\u003e\u003ca id=\"user-content-retrieving-the-user-in-a-template\" class=\"anchor\" aria-label=\"Permalink: Retrieving the User in a Template\" href=\"#retrieving-the-user-in-a-template\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eIn a Twig Template this object can be accessed via the \u003ca href=\"#id81\"\u003e\u003cspan id=\"user-content-id82\"\u003e:ref:`app.user \u0026lt;reference-twig-global-app\u0026gt;`\u003c/span\u003e\u003c/a\u003e\nkey:\u003c/p\u003e\n\u003cpre\u003e.. configuration-block::\n\n .. code-block:: html+twig\n\n {% if is_granted('IS_AUTHENTICATED_FULLY') %}\n \u0026lt;p\u0026gt;Username: {{ app.user.username }}\u0026lt;/p\u0026gt;\n {% endif %}\n\n .. code-block:: html+php\n\n \u0026lt;?php if ($view['security']-\u0026gt;isGranted('IS_AUTHENTICATED_FULLY')): ?\u0026gt;\n \u0026lt;p\u0026gt;Username: \u0026lt;?php echo $app-\u0026gt;getUser()-\u0026gt;getUsername() ?\u0026gt;\u0026lt;/p\u0026gt;\n \u0026lt;?php endif; ?\u0026gt;\n\n\u003c/pre\u003e\n\u003ca name=\"user-content-logging-out\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eLogging Out\u003c/h3\u003e\u003ca id=\"user-content-logging-out\" class=\"anchor\" aria-label=\"Permalink: Logging Out\" href=\"#logging-out\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cdiv dir=\"auto\"\u003e\n\u003cp dir=\"auto\"\u003eCaution!\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eNotice that when using http-basic authenticated firewalls, there is no\nreal way to log out : the only way to \u003cem\u003elog out\u003c/em\u003e is to have the browser\nstop sending your name and password on every request. Clearing your\nbrowser cache or restarting your browser usually helps. Some web developer\ntools might be helpful here too.\u003c/p\u003e\n\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eUsually, you'll also want your users to be able to log out. Fortunately,\nthe firewall can handle this automatically for you when you activate the\n\u003ccode\u003elogout\u003c/code\u003e config parameter:\u003c/p\u003e\n\u003cpre\u003e.. configuration-block::\n\n .. code-block:: yaml\n\n # app/config/security.yml\n security:\n # ...\n\n firewalls:\n secured_area:\n # ...\n logout:\n path: /logout\n target: /\n\n .. code-block:: xml\n\n \u0026lt;!-- app/config/security.xml --\u0026gt;\n \u0026lt;?xml version=\"1.0\" encoding=\"UTF-8\"?\u0026gt;\n \u0026lt;srv:container xmlns=\"http://symfony.com/schema/dic/security\"\n xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n xmlns:srv=\"http://symfony.com/schema/dic/services\"\n xsi:schemaLocation=\"http://symfony.com/schema/dic/services\n http://symfony.com/schema/dic/services/services-1.0.xsd\"\u0026gt;\n\n \u0026lt;config\u0026gt;\n \u0026lt;!-- ... --\u0026gt;\n\n \u0026lt;firewall name=\"secured_area\"\u0026gt;\n \u0026lt;!-- ... --\u0026gt;\n \u0026lt;logout path=\"/logout\" target=\"/\" /\u0026gt;\n \u0026lt;/firewall\u0026gt;\n \u0026lt;/config\u0026gt;\n \u0026lt;/srv:container\u0026gt;\n\n .. code-block:: php\n\n // app/config/security.php\n $container-\u0026gt;loadFromExtension('security', array(\n // ...\n\n 'firewalls' =\u0026gt; array(\n 'secured_area' =\u0026gt; array(\n // ...\n 'logout' =\u0026gt; array('path' =\u0026gt; '/logout', 'target' =\u0026gt; '/'),\n ),\n ),\n ));\n\n\u003c/pre\u003e\n\u003cp dir=\"auto\"\u003eNext, you'll need to create a route for this URL (but not a controller):\u003c/p\u003e\n\u003cpre\u003e.. configuration-block::\n\n .. code-block:: yaml\n\n # app/config/routing.yml\n logout:\n path: /logout\n\n .. code-block:: xml\n\n \u0026lt;!-- app/config/routing.xml --\u0026gt;\n \u0026lt;?xml version=\"1.0\" encoding=\"UTF-8\" ?\u0026gt;\n \u0026lt;routes xmlns=\"http://symfony.com/schema/routing\"\n xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n xsi:schemaLocation=\"http://symfony.com/schema/routing\n http://symfony.com/schema/routing/routing-1.0.xsd\"\u0026gt;\n\n \u0026lt;route id=\"logout\" path=\"/logout\" /\u0026gt;\n \u0026lt;/routes\u0026gt;\n\n .. code-block:: php\n\n // app/config/routing.php\n use Symfony\\Component\\Routing\\RouteCollection;\n use Symfony\\Component\\Routing\\Route;\n\n $collection = new RouteCollection();\n $collection-\u0026gt;add('logout', new Route('/logout'));\n\n return $collection;\n\n\u003c/pre\u003e\n\u003cp dir=\"auto\"\u003eAnd that's it! By sending a user to \u003ccode\u003e/logout\u003c/code\u003e (or whatever you configure\nthe \u003ccode\u003epath\u003c/code\u003e to be), Symfony will un-authenticate the current user.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eOnce the user has been logged out, they will be redirected to whatever path\nis defined by the \u003ccode\u003etarget\u003c/code\u003e parameter above (e.g. the \u003ccode\u003ehomepage\u003c/code\u003e).\u003c/p\u003e\n\u003cdiv dir=\"auto\"\u003e\n\u003cp dir=\"auto\"\u003eTip\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eIf you need to do something more interesting after logging out, you can\nspecify a logout success handler by adding a \u003ccode\u003esuccess_handler\u003c/code\u003e key\nand pointing it to a service id of a class that implements\n\u003ca href=\"#id83\"\u003e\u003cspan id=\"user-content-id84\"\u003e:class:`Symfony\\\\Component\\\\Security\\\\Http\\\\Logout\\\\LogoutSuccessHandlerInterface`\u003c/span\u003e\u003c/a\u003e.\nSee \u003ca href=\"#id85\"\u003e\u003cspan id=\"user-content-id86\"\u003e:doc:`Security Configuration Reference \u0026lt;/reference/configuration/security\u0026gt;`\u003c/span\u003e\u003c/a\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003ca name=\"user-content-hierarchical-roles\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eHierarchical Roles\u003c/h3\u003e\u003ca id=\"user-content-hierarchical-roles\" class=\"anchor\" aria-label=\"Permalink: Hierarchical Roles\" href=\"#hierarchical-roles\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eInstead of associating many roles to users, you can define role inheritance\nrules by creating a role hierarchy:\u003c/p\u003e\n\u003cpre\u003e.. configuration-block::\n\n .. code-block:: yaml\n\n # app/config/security.yml\n security:\n # ...\n\n role_hierarchy:\n ROLE_ADMIN: ROLE_USER\n ROLE_SUPER_ADMIN: [ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH]\n\n .. code-block:: xml\n\n \u0026lt;!-- app/config/security.xml --\u0026gt;\n \u0026lt;?xml version=\"1.0\" encoding=\"UTF-8\"?\u0026gt;\n \u0026lt;srv:container xmlns=\"http://symfony.com/schema/dic/security\"\n xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n xmlns:srv=\"http://symfony.com/schema/dic/services\"\n xsi:schemaLocation=\"http://symfony.com/schema/dic/services\n http://symfony.com/schema/dic/services/services-1.0.xsd\"\u0026gt;\n\n \u0026lt;config\u0026gt;\n \u0026lt;!-- ... --\u0026gt;\n\n \u0026lt;role id=\"ROLE_ADMIN\"\u0026gt;ROLE_USER\u0026lt;/role\u0026gt;\n \u0026lt;role id=\"ROLE_SUPER_ADMIN\"\u0026gt;ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH\u0026lt;/role\u0026gt;\n \u0026lt;/config\u0026gt;\n \u0026lt;/srv:container\u0026gt;\n\n .. code-block:: php\n\n // app/config/security.php\n $container-\u0026gt;loadFromExtension('security', array(\n // ...\n\n 'role_hierarchy' =\u0026gt; array(\n 'ROLE_ADMIN' =\u0026gt; 'ROLE_USER',\n 'ROLE_SUPER_ADMIN' =\u0026gt; array(\n 'ROLE_ADMIN',\n 'ROLE_ALLOWED_TO_SWITCH',\n ),\n ),\n ));\n\n\u003c/pre\u003e\n\u003cp dir=\"auto\"\u003eIn the above configuration, users with \u003ccode\u003eROLE_ADMIN\u003c/code\u003e role will also have the\n\u003ccode\u003eROLE_USER\u003c/code\u003e role. The \u003ccode\u003eROLE_SUPER_ADMIN\u003c/code\u003e role has \u003ccode\u003eROLE_ADMIN\u003c/code\u003e, \u003ccode\u003eROLE_ALLOWED_TO_SWITCH\u003c/code\u003e\nand \u003ccode\u003eROLE_USER\u003c/code\u003e (inherited from \u003ccode\u003eROLE_ADMIN\u003c/code\u003e).\u003c/p\u003e\n\u003ca name=\"user-content-final-words\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eFinal Words\u003c/h3\u003e\u003ca id=\"user-content-final-words\" class=\"anchor\" aria-label=\"Permalink: Final Words\" href=\"#final-words\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 488B 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eWoh! Nice work! You now know more than the basics of security. The hardest\nparts are when you have custom requirements: like a custom authentication\nstrategy (e.g. API tokens), complex authorization logic and many other things\n(because security is complex!).\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eFortunately, there are a lot of articles aimed at describing many of these\nsituations. Also, see the \u003ca href=\"#id87\"\u003e\u003cspan id=\"user-content-id88\"\u003e:doc:`Security Reference Section \u0026lt;/reference/configuration/security\u0026gt;`\u003c/span\u003e\u003c/a\u003e.\nMany of the options don't have specific details, but seeing the full possible\nconfiguration tree may be useful.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eGood luck!\u003c/p\u003e\n\u003ca name=\"user-content-learn-more\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eLearn More\u003c/h3\u003e\u003ca id=\"user-content-learn-more\" class=\"anchor\" aria-label=\"Permalink: Learn More\" href=\"#learn-more\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003ca name=\"user-content-authentication-identifying-logging-in-the-user\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch4 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eAuthentication (Identifying/Logging in the User)\u003c/h4\u003e\u003ca id=\"user-content-authentication-identifyinglogging-in-the-user\" class=\"anchor\" aria-label=\"Permalink: Authentication (Identifying/Logging in the User)\" href=\"#authentication-identifyinglogging-in-the-user\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cpre\u003e.. toctree::\n :maxdepth: 1\n\n security/form_login_setup\n security/entity_provider\n security/remember_me\n security/impersonating_user\n security/form_login\n security/custom_provider\n security/custom_password_authenticator\n security/api_key_authentication\n security/custom_authentication_provider\n security/pre_authenticated\n security/target_path\n security/csrf_in_login_form\n security/named_encoders\n security/multiple_user_providers\n security/firewall_restriction\n security/host_restriction\n\n\u003c/pre\u003e\n\u003ca name=\"user-content-authorization-denying-access\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch4 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eAuthorization (Denying Access)\u003c/h4\u003e\u003ca id=\"user-content-authorization-denying-access\" class=\"anchor\" aria-label=\"Permalink: Authorization (Denying Access)\" href=\"#authorization-denying-access\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cpre\u003e.. toctree::\n :maxdepth: 1\n\n security/voters\n security/acl\n security/acl_advanced\n security/force_https\n security/securing_services\n security/access_control\n security/access_denied_handler\n\n\u003c/pre\u003e\n\u003ca name=\"user-content-other-security-related-topics\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch4 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eOther Security Related Topics\u003c/h4\u003e\u003ca id=\"user-content-other-security-related-topics\" class=\"anchor\" aria-label=\"Permalink: Other Security Related Topics\" href=\"#other-security-related-topics\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cpre\u003e.. toctree::\n :maxdepth: 1\n\n security/password_encoding\n security/security_checker\n\n\u003c/pre\u003e\n\n\u003c/article\u003e","renderedFileInfo":null,"shortPath":null,"symbolsEnabled":true,"tabSize":8,"topBannersInfo":{"overridingGlobalFundingFile":false,"globalPreferredFundingPath":"/symfony/.github/blob/6f2ca452c856184a28812bb364b4e34ed50309da/FUNDING.yml","showInvalidCitationWarning":false,"citationHelpUrl":"https://docs.github.com/github/creating-cloning-and-archiving-repositories/creating-a-repository-on-github/about-citation-files","actionsOnboardingTip":null},"truncated":false,"viewable":true,"workflowRedirectUrl":null,"symbols":null},"copilotInfo":null,"copilotAccessAllowed":false,"modelsAccessAllowed":false,"modelsRepoIntegrationEnabled":false,"csrf_tokens":{"/symfony/symfony-docs/branches":{"post":"kfaOMDv4N7D-6n3uGQ59ZrBNgdyqYjbgiCLsxvm6_kkZvQvyKreg7w3Dccn0TsfNSO9NbTVn9sC8KxZIdrLoCQ"},"/repos/preferences":{"post":"WjLNnY25oj5-GPBXAS1K09CFxUNcmfS1nfdczneN4KMB3-3thssY5jCJdVY1tiujSVFsk-Dzp5yAfx6qkrkRiA"}}},"title":"symfony-docs/security.rst at 053cee723bf308ed6afac3eb185b09ec44209a6d · symfony/symfony-docs","appPayload":{"helpUrl":"https://docs.github.com","findFileWorkerPath":"/assets-cdn/worker/find-file-worker-263cab1760dd.js","findInFileWorkerPath":"/assets-cdn/worker/find-in-file-worker-1b17b3e7786a.js","githubDevUrl":null,"enabled_features":{"code_nav_ui_events":false,"react_blob_overlay":false,"accessible_code_button":true}}}
0