Rails Login Engine和User Engine提供了基本的用户登录,用户管理相关的功能,可以直接在应用程序中使用。
安装:
ruby script/plugin install http://svn.rails-engines.org/engines/trunk/
ruby script/plugin install http://svn.rails-engines.org/login_engine/trunk/
ruby script/plugin install http://svn.rails-engines.org/user_engine/trunk/
上面3个命令就分别安装好了所需的Engine。
相关的文档在:http://api.rails-engines.org/engines/
http://api.rails-engines.org/login_engine/
http://api.rails-engines.org/user_engine/
按照文档里面写的一步一步来就OK了。
Login Generator plugin - README
= 开始之前
这是Rails Engine 版本的 Salted Login Generator,一个极好的登录系统,它足以满足大多数通常的需要。对于大多数部分,这个代码并没有修改它的生成器生成的表单,只有下面是例外* 国际化部分被移除。* 'welcome'页被换成了'home'页。* 有少数功能被抛弃。
However, what I'm trying to say is that 99.9999% of the credit for this should go to Joe Hosteny, Tobias Luetke (xal) and the folks that worked on the original Salted Login generator code. I've just wrapped it into something runnable with the Rails Engine system.
Please also bear in mind that this is a work in progress, and things like testing are wildly up in the air... but they will fall into place very soon. And now, on with the show.
= 安装
安装 Login Engine 非常简单。
你的操作步骤是:1. 做为一个 Rails 插件来安装:$ script/plugin install login_engine2. 使用 svn:externals$ svn propedit svn:externals vendor/plugins
你可以选择使用最后发行的稳定版本:login_engine http://svn.rails-engines.org/plugins/login_engine
或者是一个指定的版本 (recommended for releases of your code):login_engine http://svn.rails-engines.org/logine_engine/tags/<TAGGED_RELEASE>
为了更好地运行你需要接受下面几个配置步骤。需要你修改的应用程序被列在下面:
=== 配置你的 Rails 应用程序
编辑你的 database.yml ,这是很重要的!你也可能需要设置 config/routes.rb 内的默认路由器。
=== 添加配置和启动引擎
添加下面到 environment.rb 文件的底部:
module LoginEngineconfig :salt, "your-salt-here"end
Engines.start :login你或许应该修改 Salt 的值以让它是唯一的。你也可以用同样方式来覆写 lib/user_system.rb 文件内,其顶部的配置值。注意:你不需要用 Engines.start :login_engine 来启动引擎,相反,如果 engine 有一个目录名 <some-name>_engine 的话,你使用 :login 来代替就可以了。
=== 添加过滤器
接着,编辑你的 app/controllers/application.rb 文件。你的 ApplicationController 文件的开始部分看起来应该是这样:
require 'login_engine' # 1
class ApplicationController < ActionController::Baseinclude LoginEngine # 2helper :user # 3model :user # 4before_filter :login_required # 5
如果你不希望所有的动作都要求登录的话,你需要继续往下读如何用 only 限制某些动作。
添加下面到你的 ApplicationHelper 文件内:
module ApplicationHelperinclude LoginEngine # 1end
这确保在你的视图内用 user 工作的方法能正常工作。
=== 设置 ActionMailer
如果你希望在 Login Engine 内取消邮件功能,只要在你的 environment.rb 文件内简单地设置 :use_email_notification 的 config 标志为 false 就可以了:
module LoginEngine# ... other options...config :use_email_notification, false # 1
end
你应该注意到当邮件功能被禁止时,自动地查找丢失口令是不需要的。相反,用户提供它们的信息给系统管理员。
如果你希望使用邮件通知和账户创建确认,你必须为你的邮件设置配置 ActionMailer 。例如,你可以添加下面到 config/environments/development.rb 文件中(对于 Mac 账户,要明确地提供用户名和口令):
ActionMailer::Base.server_settings = {:address => "smtp.mac.com",:port => 25,:domain => "smtp.mac.com",:user_name => "<your user name here>",:password => "<your password here>",:authentication => :login}
You'll need to configure it properly so that email can be sent. One of the easiest ways to test your configuration is to temporarily reraise exceptions from the signup method (so that you get the actual mailer exception string). In the rescue statement, put a single "raise" statement in. Once you've debugged any setting problems, remove that statement to get the proper flash error handling back.
=== 创建 DB schema
在你修改完 ApplicationController 与它的帮助方法后,你可以引入 user 模型到数据库内。迁移信息在 login_engine/db/migrate/ 目录内。
你必须检查这些文件不能以任何形式出现在你的应用程序内。
你也可以添加下面行来修改表的名字
module LoginEngine# ... other options...config :user_table, "your_table_name"
end
... LoginEngine 配置在 environment.rb 文件内。然后到你的工程的根目录内:
rake db:migrate:engines ENGINE=loginor(rake engine_migrate ENGINE=login)会引入 schema 到你的数据库内。
== 包含样式表
如果你需要缺省的样式表,添加下面行到你的层中:
<%= engine_stylesheet 'login_engine' %>... 它要出现在你的层文件的 <head> 段内。
== 整合 flash 消息到你的层 layout 中
LoginEngine 并不在包含它的视图内显示任何 flash 消息,所以你必须自己显示它们。这允许你整合任何消息到你的现有层文件内。LoginEngine 支持标准的 flash 用法:
* :warning - 警告 (失败) 消息。* :notice - 成功消息* :message - 通常的 (提示,信息) 消息。
这可让你更灵活地,分别安排不同的消息类。在你的层文件中,你应该检查并显示 flash[:warning], flash[:notice] 和 flash[:message]。例如:
<% for name in [:notice, :warning, :message] %><% if flash[name] %><%= "<div id="#{name}">#{flash[name]}</div>" %><% end %><% end %>
此外,你可以查阅 flash 帮助插件 (https://opensvn.csie.org/traccgi/flash_helper_plugin/trac.cgi/),它支持同样的命名约定。(my4java:在例子中是把此段放在login.rhtml内。)
= 如何使用 Login Engine
现在你可以添加 "before_filter :login_required" 到你想保护的控制器内。
在整合登录系统到你的 Rails 应用程序之前,先导航到你新的控制器的 singup 方法。那里你可以创建一个新的账户。在做此事之前,你最好检查一下数据库。After integrating the login system with your rails application navigate to your new controller's signup method. There you can create a new account. After you are done you should have a look at your DB. Your freshly created user will be there but the password will be a sha1 hashed 40 digit mess. I find this should be the minimum of security which every page offering login & password should give its customers. Now you can move to one of those controllers which you protected with the before_filter :login_required snippet. You will automatically be re-directed to your freshly created login controller and you are asked for a password. After entering valid account data you will be taken back to the controller which you requested earlier. Simple huh?
=== 使用 before_filter 的保护
添加行 before_filter :login_required 到你的 app/controllers/application.rb 文件内,它将保护你应用程序中每个控制器内的所有方法。如果你只想控制对特定控制器的访问,从 application.rb 文件内移除此行,再将它添加到你想保护的控制器内。
在每个控制器内,你可以约束哪个方法在执行前需要过滤:
before_filter :login_required, :only => [:myaccount, :changepassword]before_filter :login_required, :except => [:index]
=== 使用 protect?() 的保护
做为选择,你可以忽略全局 application.rb 文件内的 before_filter ,而通过在指定控制器内定义一个 protect?() 方法来约束要控制的动作。
例如,在 UserController 内我们希望允许每个人访问 'login','singup' 和 'forgot_password' 方法(否则的话,没有人能访问我们的站点)。所以可以像下面一样在 user_controller.rb 内定义一个 protect?() 方法:
def protect?(action)if ['login', 'signup', 'forgot_password'].include?(action)return falseelsereturn trueendend
当然,你可以在你的应用程序中覆写 Engine 行为 -- 参阅下面。
== 配置
下面的配置变量在 lib/login_engine.rb 文件内设置。如果你希望覆写它们,你应该在调用 Engines.start 之前设置它们。
例如,下面可以出现在 /config/environment.rb 文件的底部:
module LoginEngineconfig :salt, 'my salt'config :app_name, 'My Great App'config :app_url, 'http://www.wow-great-domain.com'endEngines.start
=== 配置选项
email_from:: The email from which registration/administration emails will appear to come from. Defaults to 'webmaster@your.company'.+admin_email+:: The email address users are prompted to contact if passwords cannotbe emailed. Defaults to 'webmaster@your.company'.+app_url+:: The URL of the site sent to users for signup/forgotten passwords, etc.Defaults to 'http://localhost:3000/'.+app_name+:: The application title used in emails. Defaults to 'TestApp'.+mail_charset+:: The charset used in emails. Defaults to 'utf-8'.+security_token_life_hours+:: The life span of security tokens, in hours. If a securitytoken is older than this when it is used to try and authenticatea user, it will be discarded. In other words, the amount of timenew users have between signing up and clicking the link theyare sent. Defaults to 24 hours.+two_column_input+:: If true, forms created with the UserHelper#form_input method willuse a two-column table. Defaults to true.+changeable_fields+:: An array of fields within the user model which the useris allowed to edit. The Salted Hash Login generator documentationstates that you should NOT include the email field in thisarray, although I am not sure why. Defaults to +[ 'firstname', 'lastname' ]+.+delayed_delete+:: Set to true to allow delayed deletes (i.e., delete of recorddoesn't happen immediately after user selects delete account,but rather after some expiration of time to allow this actionto be reverted). Defaults to false.+delayed_delete_days+:: The time delay used for the 'delayed_delete' feature. Defaults to7 days.+user_table+:: The table to store User objects in. Defaults to "users" (or "user" ifActiveRecord pluralization is disabled).+use_email_notification+:: If false, no emails will be sent to the user. As a consequence,users who signup are immediately verified, and they cannot requestforgotten passwords. Defaults to true.+confirm_account+:: An overriding flag to control whether or not user accounts must beverified by email. This overrides the +user_email_notification+ flag.Defaults to true.
== 覆写控制器和视图
大多数情况下标准的 home 页并不是你想呈现给你的用户的页面。因为这个登录系统是个 Rails 引擎,覆写缺省行为并不太简单。为 home 动作修改要显示的 RHTML 模板,简单地在 RAILS_ROOT/app/views/user/home.rhtml 内创建个文件(你或许同时需要创建目录 user )。这个新的视图文件将代替登录引擎中的哪个来被使用。
== Tips & Tricks
我如何...
... 访问当前登录的用户?
A: 你可以使用 session[:user] 来获得 user 对象。例如:Welcome <%= session[:user].name %>
你也可以使用由 UserHelper 提供的 'current_user' 方法:例如:Welcome <%= current_user.name %>
... 只对少数几个方法进行约束? A: 在范围内绑定使用 before_filters 。 例如: before_filter :login_required, :only => [:myaccount, :changepassword]before_filter :login_required, :except => [:index]... 在视图内检查用户是否登录?A: session[:user] 会话会告诉你。这个有个帮助方法的例子,你也可以让它做更多的事。例如: def user?!session[:user].nil?end
... 如何返回用户登录前输入的 URL ?
A: 名为 "store_location" 的方法会把用户送回到它在登录前请求的页面。例如:在登录前用户输入 /articles/show/1 。在 articles_controller.rb 内,添加 store_location 给 show 方法并发送用户到登录表单。在登录后,会弹回 /articles/show/1 的日志。
你可以在 http://wiki.rubyonrails.com/rails/show/SaltedLoginGenerator 中找到更多的帮助方法。
== Troubleshooting
One of the more common problems people have seen is that after verifying an account by following the emailed URL, they are unable to login via the normal login method since the verified field is not properly set in the user model's row in the DB.
The most common cause of this problem is that the DB and session get out of sync. In particular, it always happens for me after recreating the DB if I have run the server previously. To fix the problem, remove the /tmp/ruby* session files (from wherever they are for your installation) while the server is stopped, and then restart. This usually is the cause of the problem.
= Notes
=== Database Schemas & Testing
Currently, since not all databases appear to support structure cloning, the tests will load the entire schema into your test database, potentially blowing away any other test structures you might have. If this presents an issue for your application, comment out the line in test/test_helper.rb
= Database Schema Details
You need a database table corresponding to the User model. This is provided as a Rails Schema file, but the schema is presented below for information. Note the table type for MySQL. Whatever DB you use, it must support transactions. If it does not, the functional tests will not work properly, nor will the application in the face of failures during certain DB creates and updates.
mysql syntax:CREATE TABLE users (id INTEGER UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,login VARCHAR(80) NOT NULL,salted_password VARCHAR(40) NOT NULL,email VARCHAR(60) NOT NULL,firstname VARCHAR(40),lastname VARCHAR(40),salt CHAR(40) NOT NULL,verified INT default 0,role VARCHAR(40) default NULL,security_token CHAR(40) default NULL,token_expiry DATETIME default NULL,deleted INT default 0,delete_after DATETIME default NULL) TYPE=InnoDB DEFAULT CHARSET=utf8;
postgres:CREATE TABLE "users" (id SERIAL PRIMARY KEYlogin VARCHAR(80) NOT NULL,salted_password VARCHAR(40) NOT NULL,email VARCHAR(60) NOT NULL,firstname VARCHAR(40),lastname VARCHAR(40),salt CHAR(40) NOT NULL,verified INT default 0,role VARCHAR(40) default NULL,security_token CHAR(40) default NULL,token_expiry TIMESTAMP default NULL,deleted INT default 0,delete_after TIMESTAMP default NULL) WITH OIDS;
sqlite:CREATE TABLE 'users' (id INTEGER PRIMARY KEY,login VARCHAR(80) NOT NULL,salted_password VARCHAR(40) NOT NULL,email VARCHAR(60) NOT NULL,firstname VARCHAR(40),lastname VARCHAR(40),salt CHAR(40) NOT NULL,verified INT default 0,role VARCHAR(40) default NULL,security_token CHAR(40) default NULL,token_expiry DATETIME default NULL,deleted INT default 0,delete_after DATETIME default NULL);
Of course your user model can have any amount of extra fields. This is just a starting point.
User Engine plugin - README
= UserEngine: Login + Roles
UserEngine 以非常简单的,基于角色的访问控制, RBAC 实现扩展了 LoginEngine。就像 'User' 对象,UserEngine 提供了 Permission 对象和 Role 对象。每个用户可以有多个角色,每个角色可以用多个许可来访问。许可是个简单的 控制器/动作 对。带有一些许可的角色可以访问指定的 控制器/动作 对,例如,带有 "user/home" 访问的 Permission 对象的角色可以允许调用此动作。
=== 并不是一个真正的 RBAC 系统
在开始处我就声明这一点,以不会造成什么麻烦 - 这不是一个完整的许可系统。UserEngine 只控制哪个用户有权利使用哪个 控制器/动作 对。它并不控制对任何数据的访问,所以你不能使用它来指定只能编辑你的数据对象子集的用户(除非子集是由不同的控制器动作控制的)。
= 安装
1. 创建个 Rails 应用程序,设置你的数据库, 安装 Engines 插件和 LoginEngine 插件。
2. 安装 UserEngine 插件到 vendor/plugins 目录内。
3. 在 config/environment.rb 文件内修改你的 Engines.start 调用,如果你已有特定的,已指定哪个引擎被启动,确保你添加 :user (或 :user_engine)。 最重要的一点是,要注意 UserEngine 必须在 LoginEngine 之后被启动,因为它必须覆写 LoginEngine 内的一些行为。 environment.rb 文件的尾部看起来应该像这样:
Engines.start :login, :user
或
Engines.start :loginEngines.start :user
or simply:
Engines.start # note that this use assumes that you haven't renamed the user_engine# to anything which would come before 'login_engine' alphabetically
4. 编辑 application.rb 文件,以便它看起来像下面这样 (注意新的 include UserEngine 和修改后的 before_filter):
class ApplicationController < ActionController::Baseinclude LoginEngineinclude UserEngine
helper :usermodel :user
before_filter :authorize_actionend
5. 编辑 application_helper.rb 文件:
module ApplicationHelperinclude LoginEngineinclude UserEngineend
6. 完成你需要的配置之后。 你或许想看看 environment.rb 内的这些值(在调用 Engines.start 之前):
module UserEngineconfig :admin_login, "the login name for your administrator user"config :admin_email, "an email address for your administrator"config :admin_password, "your initial admin password"end
7. 初始化数据表。你必须确保用于 LoginEngine 的表存在,因为这个引擎构建在它们之上。如果你第一次安装 User 引擎,你或许会得到一个警告,它指出你还没有一个 Admin 角色 - 这很好,我们稍后将创建一个。你可以用下面的调用来使用迁移:
rake engine_migrate
来移除所有在它们之前的引擎,或
rake engine_migrate ENGINE=user
来只迁移这个引擎。另外,如果你想加载完整的 User 和 LoginEngine 的 schema ,运行
rake import_user_engine_schema
8. 运行 rake 任务来安装默认的角色和管理员用户。这也会创建一个新的有 Admin 角色的用户- 缺省的登录名(如果你没有以步骤6来设置的话)是 'admin' 和缺省口令 'testing' 。确保你修改它!:
rake bootstrap
9. UserEngine 包括了一个方法来检查上面创建的系统角色是否是完整的。典型地你应该在服务器每次启动时调用它,可以把下面行放在 environment.rb 的底部:
UserEngine.check_system_roles
10. UserEngine 提供了一个缺省的样式表和一个小的 java 脚本帮助文件(用于 Role#edit 动作内),因此或许你想在 application 层内包括前者和后者。添加下面的行:
<%= engine_stylesheet "user_engine" %><%= engine_javascript "user_engine" %>
11. 移除所有的现有会话(因为它们可能会与 login 进程交互),并重启服务器,使用你配置的 administrator 登录名和 口令登录(如果你没有明确地在配置中设置,则缺省是 'admin'/'testing' - 一定要修改它们!)然后定位到 http://localhost:3000/user/list 会看到所有用户的列表。你可以创建新用户,查看角色和许可,等等....
12. 因为 UserEngine 覆写了 LoginEngine 内的一些缺省行为,如果你在你的 app 目录内做了一些修改的话,你或许应该检查这些修改,以确保你自己定制的部分还能工作。你需要查看下面这些:
* UserEngine 的 models/user.rb 模型将覆写缺省由 LoginEngine 给出的。如果你有自己的app/models/user.rb 文件,你将需要包括 UserEngne::AuthorizedUser 在你的文件内。
* UserController#edit 动作已经被 Roles 覆写。祥细信息查阅 user_engine/app/user_controller.rb 。
* 为管理员用户,角色和许可提供了很多新方法,可查阅 user_engine/app/user_controller.rb 文件。
* 如果你覆写了任何的 User 视图,要查看 UserEngine 内的相应视图,看看你自己的版本内是否包含了你希望的修改。
= 配置
有大量配置参数来允许你在对缺省值不满意时,控制数据如何被存储。下面是一些要点。例如,你可以在你的 environment.rb 文件内定制 :admin_email 值:
module LoginEngineconfig :salt, 'your salt value'endmodule UserEngineconfig :admin_email, 'admin@megacorp.com'endEngines.start :login, :user
=== 配置选项
role_table:: 存储 Role 对象的表名字。缺省是 "roles" (如果你关闭复数的话,则是 "role" 。)permission_table:: 存储 Permission 对象的表名字。缺省值是 "permissions" (如果你关闭 复数的话,是 "permission" 。)user_role_table:: 用户与角色的 join 表。缺省值是 <user_table>_<role_table>。 (User 表在 LoginEngine 配置内指定)。permission_role_table:: 角色与许可是 join 表。缺省值是 <permission_table>_<role_table>。guest_role_name:: Guest 角色的名字。缺省值是 "Guest"。user_role_name:: User 角色的名字。缺省值是 "User"。admin_role_name:: Admin 角色的名字。缺省值是 "Admin"。admin_login:: 初始化 Admin 用户的登录 ID 。缺省值是 "admin"。admin_email:: 站点管理员的邮件地址。缺省值是 "admin@your.company"。login_page:: 描述登录页面位置的哈希表。缺省值是 {:controller => 'user', :action => 'login'}。steath:: a boolean flag to indicate whether or not the system shoulddisplay helpful messages about authorized roles when they aredenied access to an action, or if it should simply deny theuser access without revealing which roles can access that action.Defaults to false (i.e. DO show helpful messages). = 用法
=== 用户
一旦你以管理员身份登录,你可到 /user/list 来列出所有用户。在此页你也可以创建新用户(/user/new),以及编辑用户。
在编辑一个用户时(/user/edit_user/id),你不但可以修改用户的细节和口令,也可以指定用户的角色。
=== 角色
UserEngine 初始化建有三个角色对象。
* Guest, 带有登录,注册和找回口令的许可。* User, 带有登录,到 /user/home,修改口令,编辑自己信息的许可。* Admin, 带有编辑所有用户,列出用户,编辑所有角色,编辑许可,等等的许可。
/role/new 可以容易地创建新角色,那里您可以选择该角色应该有的许可。界面 /role/edit/id完成同样的工作。例如,如果你有个具有两个动作 view 和 edit 的控制器RepotController,那么你可以创建两个新角色 --- 'ReportViewer' 和 'ReportEditor' 。ReportViewer 的唯一许可是 report/view,同样 ReportEditor 是 report/edit。现在你就可以赋值 ReportViewer 角色给多个需要 view 的用户,但是你只能赋值 ReportEditor 给一个能够使用 edit 的用户。
要注意的一点是,如果一个用户能够编辑其它用户(/user/edit_user)的话,它可以赋值角色给用户。同样,可以编辑角色(/role/eidt)的用户可以添加任何许可给系统内的角色。因此,做为系统管理员的你必须小心地来发放许可。
通常,你不应该给普通用户比缺省值多的 any 许可,以及对你的应用程序所有控制器的许可。
=== 许可
你可以使用支架风格界面来创建许可,它可避免手工创建的一些错误。而且有个方法,它提供了自动扫描你的控制器,并确保对每个控制器对有个现有 Permission 对象。这个方法是 Permission.sychronize_controllers (或者用缩写 Permission.sync ),你可以从控制台像个 rake 任务来调用它:
rake sync_permissions要注意当前这个方法将故意从不删除你的系统内的任何许可对象,即使此方法不再存在。
== Helper 方法
UserEngine 提供了几个帮助方法,它们理解使用在你的视图内的许可和角色。下面谈到的是两个最重要的。 |