在 Forge - 验证 Rails 应用程序
上个月,我们开始关注 OpenID,这是一种用于互联网分布式身份验证的开放标准。OpenID 允许您拥有一个用户配置文件,该配置文件已针对您信任的提供商进行身份验证,并在许多不同的网站和互联网应用程序中使用该配置文件。OpenID 在最初由博客公司 LiveJournal 开发和使用后,在过去几年中越来越受欢迎。从那时起,它已成为一种更流行和开放的标准,现在受到许多网站以及所有流行的编程语言的支持。
我曾希望使用本月的专栏来展示使 Web 应用程序符合 OpenID 标准是多么容易——或者用 OpenID 术语来说,使其成为 OpenID 消费者。事实证明,添加 OpenID 功能实际上并不复杂或困难,特别是对于像 Ruby on Rails 这样流行的框架,它有许多已建立的插件。
然而,我还发现 Rails 的 OpenID 插件与名为 acts_as_authenticated 的插件配合得特别好。此插件为 Rails 应用程序提供了一个简单、安全且高度可定制的身份验证系统。因此,本月,我们稍微绕道,看看如何在 Rails 应用程序中使用 acts_as_authenticated。在此过程中,我们可以了解如何下载和使用 Rails 插件,这是使用 Rails 进行 Web 开发的重要组成部分。下个月,我们将以我们创建的内容为基础,为我们的应用程序添加 OpenID,为我们的用户提供一套真正灵活的登录选项。
尽管 Rails 为开发人员提供了大量功能,但它提供的应用程序级功能却很少。相反,它的大部分功能都以程序员可以用来创建新应用程序的对象和方法的形式存在。但是,没有内置的应用程序或应用程序片段,甚至没有开发人员希望在每个 Rails 安装中找到的集中式数据库模式。
Rails 核心开发人员表示,这样做是有目的的,因为每个应用程序都有不同的需求,并且不可能让每个人都满意。而且,我确实理解他们的观点。我的每个应用程序总是需要保留稍微不同类型的用户信息,更不用说其他类型的数据了。开发人员可能做出的任何选择对于某些人来说都是错误的。
我碰巧认为这里存在中间地带。也许 Rails 核心不需要包含针对用户、组和权限的完整解决方案。但是,鉴于定义和使用此类对象的应用程序数量庞大,在框架本身内包含一个易于扩展的骨架是有意义的。
鉴于 Rails 核心团队过去对此表达的强烈感受,此类扩展不太可能在不久的将来出现。但是,一切还没有结束。Rails 包含一个“插件”系统,该系统使下载代码集合(包括模型、视图、控制器等)并将它们安装到应用程序中成为可能。如果您可以找到并安装合适的插件,您将获得某种折衷解决方案。安装后,代码就像是应用程序的组成部分一样运行。而且,当然,您只能添加对您的特定应用程序重要的插件。
由于许多应用程序都需要用户注册和身份验证,因此有许多可用的插件也就不足为奇了。其中最受欢迎的插件之一是 acts_as_authenticated,这是由 Rails 核心团队成员 Rick Olson 编写的插件。该名称不是指实际声明,而是一种俏皮的说法,表示它旨在与 Rails 一起使用。而且,尽管 README 文件(在您安装插件时显示)表明它已被弃用(赞成 restful_authentication),但 acts_as_authenticated 足够流行和稳定,并且与 OpenID 配合良好,因此值得一看。
Rails 插件使用内置的插件工具安装,该工具位于 script/plugin 中。您可以列出可用的插件
script/plugin list
但是,这将仅列出位于系统已知来源之一的插件。要查看这些来源的列表,只需键入
script/plugin sources
要将新来源添加到列表中,只需说
script/plugin source http://svn.techno-weenie.net/projects/plugins/
果然,这样做之后,运行script/plugin sources显示新 URL。而且,当然,现在键入script/plugin list显示来自旧来源和新来源的许多新插件。
要安装新插件(例如 acts_as_authenticated),我们必须将其 URL 提供给 script/plugin。这就像以下操作一样简单
script/plugin install http://svn.techno-weenie.net/projects/plugins/acts_as_authenticated
现在,安装插件时会发生什么?Rails 将其安装到 vendor/plugins 目录中,并在以插件命名的新目录下。因此,我安装的 acts_as_authenticated 在 vendor/plugins/acts_as_authenticated 中安装了许多文件。
就其本身而言,安装插件不会更改我的 Rails 安装或添加任何新功能。相反,插件通常会创建一个或多个生成器,这些生成器用于创建或修改应用程序使用的文件。
在 acts_as_authenticated 的情况下,它带有两个不同的生成器,我们可以通过进入 generators 子目录来查看它们。在这里,有两个生成器,分别名为 authenticated 和 authenticated_mailer。如果我们进入 authenticated 目录,我们会看到 authenticated_generator,它定义了生成器。这允许我们转到 Rails 应用程序的根目录并键入
script/generate authenticated user account
上面告诉 Rails 我们要使用 authenticated 插件,它在插件目录中找到。此命令的其他参数指示我们将使用的模型(和表名)(在本例中为 user)以及应生成的用于处理帐户的控制器。
生成器创建一个迁移文件,使用 Ruby 定义 Users 表的列,以提高数据库独立性。为了创建数据库的列,我们必须运行迁移
rake db:migration
使用我的 PostgreSQL 数据库客户端,我现在可以看到迁移完成了它的工作
atf_development=# \d users Table "public.users" Column | Type | ---------------------------+-----------------------------+ id | integer | login | character varying(255) | email | character varying(255) | crypted_password | character varying(40) | salt | character varying(40) | created_at | timestamp without time zone | updated_at | timestamp without time zone | remember_token | character varying(255) | remember_token_expires_at | timestamp without time zone |
既然我已将 acts_as_authenticated 合并到我的应用程序中,我应该能够做几件简单的事情
将页面标记为对公众开放。
将页面标记为私有——即,仅对注册用户开放。
允许人们注册。
允许用户登录。
允许用户注销。
所有这些不仅可以通过 acts_as_authenticated 实现,而且还非常容易。要使页面默认需要身份验证,我们可以说
before_filter :login_required
当然,如果我们要求人们在使用登录页面之前登录,用户会发现自己陷入无限循环。因此,我们可以在 account_controller.rb 的顶部为该页面添加一个例外
before_filter :login_required, :except => [:login, :signup]
一旦此过滤器到位,尝试访问登录或 :signup 以外的任何页面都会将我们弹回登录页面。
我将注册,方法是在注册表中输入我的登录名、我的电子邮件地址和我的密码(两次)。一旦我单击提交按钮,应用程序会将我的数据插入数据库。我在那里,ID 为 #1,以及我的明文数据和我的加密数据。
此外,在网站注册后,我现在也已登录。我可以查看任何我想要的页面,而无需再次登录。我的登录将持续到我访问 /account/logout URL。不幸的是,acts_as_authenticated 附带的默认 index.rhtml 页面没有明确说明您何时注销。我们可以通过在顶部添加一行来轻松检查这一点,显示非空白通知的内容
<p><%= flash[:notice] if not flash[:notice].blank? %></p>
我们现在有了一个基本可用的身份验证 Web 服务器版本。人们可以注册(如果他们已经注册,则可以登录),我们可以通过控制器和before_filter :login_required命令添加受限和非受限页面。
对于许多站点来说,acts_as_authenticated 目前的状态已经足够好。但是,您可以将许多插件、建议和修改与 acts_as_authenticated 一起使用。
例如,许多注册系统都希望阻止机器人自动创建用户名或电子邮件地址,这些地址可用于发送垃圾邮件。因此,注册系统通常要求用户通过电子邮件确认其会员资格请求。因此,您在网站上输入您的信息,并收到一条消息,要求您单击链接。只有在单击该链接后,您的帐户才会被实际激活。
此功能虽然不是核心 acts_as_authenticated 插件的明显组成部分,但它随插件一起提供,并且易于使用。基本上,我们使用 acts_as_authenticated 附带的其他生成器。这会创建模板和我们需要的用于人们确认其登录状态的大部分逻辑。
您可以使用 acts_as_authenticated 执行各种其他操作。例如,您可以将其设置为以可逆的方式加密密码。另一个常见的任务是让用户更改他们的个人信息,例如电子邮件地址和电话号码。
对 acts_as_authenticated 的所有讨论都始于我想在 Rails 应用程序中使用 OpenID。但是,我也想将 OpenID 与现有的身份验证机制集成,这使我接触到了 acts_as_authenticated。现在我们在我们的网站上拥有了一个可用的(如果简陋的)身份验证系统,我们可以继续下一步。
即使您没有在 Rails 应用程序中使用 acts_as_authenticated,了解插件的工作原理、您如何与它们交互以及如何使用它们来构建由其他程序员贡献的部分组成的 Rails 应用程序也是有用的。
下个月,我们将研究如何将 OpenID 集成到我们的登录系统中——即,允许人们使用用户名/密码组合或 OpenID 登录。
资源
如果您仍然是 Rails 新手,我强烈推荐 Obie Fernandez 的 The Rails Way。我发现它既清晰又全面,并且本书中的一章专门介绍了 acts_as_authenticated。
Web 上有很多关于 acts_as_authenticated 的优秀资源。但是,最全面的是作者的 Wiki,网址为 technoweenie.stikipad.com/plugins/show/Acts+as+Authenticated。
Reuven M. Lerner 是一位长期的 Web/数据库开发人员和顾问,他是西北大学学习科学专业的博士候选人,研究在线学习社区。他在芝加哥地区生活了四年后,最近(与妻子和三个孩子)返回他们在以色列莫迪因的家。