(Security)如何去搭建一个传统的登录表单

注意:如果你需要为存储在某种数据库中的用户做一个登录表单,那么你应该考虑使用FOSUserBundle,这有助于你建立你的User对象,还为您提供了常见的登录、注册、忘记密码的路由和控制器。

在此文章中,将构建一个传统的登录表单。当然,当用户登录时,你可以从数据库或者任何地方加载用户。

本章假设您已经遵循了security章节并且http_basic 认证正常工作。

首先,启用防火墙下表单登录

这个login_path和check_path也可以是路由名称(但不能有强制通配符例如 /login/{foo})这里foo没有默认值

现在,当安全系统启动认证过程,它会让用户跳转到登录表单 /login。你的工作是实现这个登录表单视觉。首先,创建一个新的SecurityController在bundle中:

下一步创建两个路由:分别是刚才form_login下的设置的两个路径(/login和/login_check):

annotations

 

非常好!下一步,你要去添加loginAction的逻辑,并把需要的渲染到login表单:

 这个security.authentication_utils服务和AuthenticationUtils类在symfony2.6都有介绍。

不要让这个控制器迷惑你。你看到当用户提交表单的这一刻,security系统会自动处理表单提交到这个控制器。如果用户提交了一个无效的用户名和密码,该控制器可以从security系统中读出表单提交的错误,以便把他显示给用户。

换句话说,你的工作是显示登录表单和任何可能发生的登录错误,但是security系统本身负责检查提交的用户名和密码并认证用户。

最后,创建模版:

这个传入到模版的错误变量是一个AuthenticationException它包含很多信息-一些敏感信息-关于认证失败信息,所以你要明智的使用它。

要实现这些东西,要注意这几个要求:

  • 该表单必须提交到/login_check,因为你在security.yml的form_login健中配置的
  • 这个用户名一定要name为_username并且password一定要name为_password。

其实所有的这些都可以配置到form_login健下,请查看 form登录配置

此登录表单目前没有使用CSRF攻击。如果需要请阅读 Using CSRF Protection in the Login Form 

就是这样!当您提交表单,security系统会自动检查用户的凭证,验证用户或向用户发送错误信息在登陆表单。

回顾整个过程:

1.用户试图访问被保护的资源。

2.防火期启用认证过程将用户重定向到登录表单(/login)

3.这个例子中,通过路由(route)和控制器(controller)来显示登录表单。

4.用户提交登录表单到 /login_check;

5.security系统截取请求,检查用户提交的凭据,验证他们是否正确,如果他不是系统允许的,页面会重新跳转到表单。

 

成功后,重定向

如果提交的凭证是正确的,该用户会被重新定向到请求的原始页面(如/admin/foo)。如果用户最初直接进入登录页面,它需要跳转到首页。这些都是可以设定的,并且允许你指定到一个指定的url上。

更多细节,请参阅 How to Customize your Form Login

 

避免常见问错误

在设置表单时应该注意一些常见的陷阱。

1.创建正确的路由

首先,确保你已经定义了正确的/login和/login_check,他们应该和你配置的login_path和check_path是一样的。如果你配置错误他会重定向到一个404页面,而不是登录页面,或者会出现提交表单不执行任何操作(你会一遍又一遍的看到登录表单)。

2.确保登录页面可以访问

此外,要确保登录页面匿名用户可以访问。例如,下面的配置-ROLE_ADMIN角色用于所有的URL(包括 /login),将会出现重定向循环:

添加access_control中添加一个 /login/*,并且指定一个任何身份都可以进入的角色。

另外,如果您的防火墙没有允许匿名用户(没有anonymous 键),你需要去创建一个特殊的防火墙,允许匿名用户登录:

 3.确保 /login_check 位于防火墙的后面

确保你的check_path的url(如 /login_check)在表单登录防火墙里(例如本例,单一的防火墙匹配所有URL,包含/login_check)。如果/login_check不匹配路由,你会收到一个Unable to find the controller for path “/login_check”的异常。

4.多个防火墙不共享相同的Security内容

如果你使用多个防火墙并且你进行认证了一个防火墙,其他的防火墙就不会对此做自动认证了。不同的防火墙,就像不同的安全系统。要做到这一点,你就必须要明确指定不同防火墙下相同的 Firewall Context  。但大多数应用,有一个主要的防火墙就足够了。

5.路由错误不受防火墙限制

Security已经把路由里的404页面设置成了不受防火墙限制。这意味着在这些页面上,你不能检测Security甚至访问用户对象。请查看 How to Customize Error Pages

2 Comments

发表评论