2

我想限制用户只能查看和编辑来自他们公寓的数据。我已经在 session[:apartment_id] 中保存了他们的 apartment_id。所以,我有 CRUD,我想限制用户不能做 /data/ID/edit 只能更改 ID 然后编辑数据。有没有一种很好的方法可以做到这一点,比如说,通过一些范围,或者我必须在每个操作中验证我的控制器中的所有内容。先感谢您。多里扬

编辑:这是更详细的:假设有一个用户列表何时执行 /data 并且当您想查看有关某些具有 ID 的用户的特定数据时,您将转到 /data/ID 示例 /data/27。在我的数据库中,对于模型数据,我得到了 row apartment_id,它告诉用户属于哪个公寓。

现在,我想根据他们的会话数据限制某些用户的视图。例如,当用户登录时,他得到了 session[:apartment_id]。

因此,我希望能够限制用户不能访问例如 /data/34 的 user_id=34,它的公寓 ID 与会话 [:公寓 ID] 不同。

另外,当用户访问/data 时,只向用户显示他的表象。

我知道我可以在每个控制器中执行此操作,每种方法都可以检查这一点,但是我可以在模型的某个地方执行此操作吗?谢谢你

4

3 回答 3

3

为 Rails 应用程序添加行级安全性 如果您正在使用数据库构建 Web 应用程序,您可能需要多个用户,这意味着添加行级安全性和身份验证。

Rails 使用了一个很酷的 gem,叫做 Devise。Devise 创建一个 User 表和视图以通过会话向 Web 应用程序进行身份验证,然后您可以向每个视图添加身份验证以确保您有一个有效的会话来查看该视图。

这一切都很好,但并没有解决我的另一个问题,即按用户限制数据库中的数据。所以我选择使用 Devise User 模型,特别是 id 字段,并由其他数据库表更改以包含 id 字段(我称之为 user_id )。当您随后调整 Rails 应用程序的其余部分(例如模型调用)以使用会话 user_id 作为每个 SQL 查询的一部分时,这一切都有效。让我尝试解释基本步骤,其中包含一些细节,但您需要针对您的情况即兴发挥。

我眼中的过程分为特定于设计的步骤和行级安全步骤。

设计步骤

将设计添加到您的 Rails 项目

    add devise gem to gem file

    gem ‘devise’

    bundle install



rails generate devise:install

(将设计安装到 Rails 应用程序中 - 位于应用程序目录根目录中)

rails g devise:views

(可选步骤:这会复制视图,以便我们可以自定义和样式)

rails generate devise User

(创建用户模型)

bundle exec rake db:migrate

(创建表 - 注意您需要 yml 中的权限才能更改数据库结构)

其余与设计相关的步骤

添加顶部 div 到 application.html.erb 检查用户是否登录,并显示登录 ID 或新用户和登录链接

<div class=”top”&gt;

<p class=”notice”&gt;<%= notice %></p>

<p class=”alert”&gt;<%= alert %></p>

<p>

<% if user_signed_in? %>

  Logged in as <strong><%= current_user.email %></strong>.

  <%= link_to ‘Edit profile’, edit_user_registration_path %> |

  <%= link_to “Logout”, destroy_user_session_path, method: :delete  %>

<% else %>

  <%= link_to “Sign up”, new_user_registration_path  %> |

  <%= link_to “Login”, new_user_session_path %>

<% end %>

</div>

创建了一个“访客”控制器并在未登录时显示 - 还更新了 routes.rb 以使其成为根 - 即,当有人第一次访问您的站点时,您应该将他们带到访客控制器,而不是数据!您还没有会话。

更新了来宾/根控制器,特别是如果用户已登录,则索引操作以转到已登录的控制器

  if user_signed_in?

    redirect_to :controller=>’home’, :action=> ‘index’

  end

在每个其他 data/loggedin 控制器中,将以下内容添加到控制器顶部的操作之前:这将确保没有人可以使用 URL 路径在未经身份验证的情况下登陆页面。

before_filter :authenticate_user!

行级步骤

使用 user_id 列更改您想要行级安全性“RLS”的表。

mysql> ALTER TABLE mytable ADD COLUMN user_id VARCHAR(255) AFTER id;

使用 users 表中的有效 user_id 更新表(假设您已经使用注册表单创建了一个用户。或者只使用 1,因为 Devise 似乎从 1 开始第一个用户 id)

mysql> UPDATE mytable SET user_id = ( SELECT id FROM users WHERE email = ‘mememe@me.com’ );

处理将 user_id 添加到表插入

在 data/loggedin 控制器 CREATE 操作中,更新参数对象中的 user_id 字段。

def create

params[:mytable][:user_id] = current_user.id

…

end

通过传递 user_id 作为参数来处理选择/查询

在数据/登录模型中,将 user_id 传递到新的 my 查询范围,然后将该新范围与其他范围组合(确保将 user_id 传递到其他范围;还有其他方法可以做到这一点,但我喜欢范围):

scope :my, -> (user_id) { where(“user_id = ?”, user_id) }

scope :mylovelyquery, -> (user_id) { my(user_id).where(:mylovelyselectioncriteria=>”A”).order(“mysortfield”)  }

在 data/logged 控制器中,更改索引操作以获取 current_user.id 并将其传递给您创建的 ActiveRecord 范围。这一步很乏味,可以经常完成——查找任何控制器索引或任何执行 SELET 的控制器操作——需要 RLS!这也适用于 Ajax 调用。

def index

@user_id = current_user.id

@mytables = Mytable.my(@user_id).order(mylovelysortfield DESC”)

end

得到教训

可能让我最头疼的一件事是在检索数据库之前忘记获取 current_user.id。

于 2014-03-15T21:11:35.993 回答
1

如果您的用户 has_many 公寓,那么通常您可以在控制器中执行此操作:

def edit
  current_user.apartments.find(params[:id])
end

这只会找到属于当前用户的公寓。

更新

看起来你没有 current_user 对象......所以:

def edit 
  @apartment = Apartment.find(params[:id])
  redirect_to root_path, error: "You do not have access for this apartment"
end
于 2012-04-19T01:18:10.983 回答
0

您可以before_filter在您想要在控制器中限制的任何操作上使用 a。这里有一些关于这个主题的阅读:http: //guides.rubyonrails.org/action_controller_overview.html#filters

于 2012-04-19T01:20:33.093 回答