2012-04-29 1 views
0

У меня есть модели пользователей, аккаунтов и ролей. Роль сохраняет тип отношений между учетной записью и пользователем.Как избежать уязвимости при массовом назначении с помощью динамических ролей?

Я оставил attr_accessible в Role пустым, чтобы предотвратить уязвимость массового присвоения (в противном случае злоумышленники могли бы изменить тип роли - владелец, администратор и т. Д. ..., учетные записи или идентификаторы пользователей).

А что, если администратор хочет изменить подписчика на модератор? Это вызовет исключение безопасности массового присвоения:

user = User.find(params[:id]) 
role = user.roles.find_by_account_id(params[:account_id]) 
role.type = "admin" 

Как это решить? Один из способов - создать отдельную модель для представления каждой роли (владельца, администратора, модератора, подписчика) и использовать шаблон типа STI. Это позволяет мне:

user = User.find(params[:id]) 
user.moderatorship.build(account_id: params([:account_id]) 

Нужна! Я должен был бы создать Onwership, Moderatorship, Subscribership и т. Д. И унаследовать их от Role. Если я хочу придерживаться одной модели ролей, как я могу иметь динамические роли, не подвергая себя уязвимости при массовом назначении?

Бонус вопрос: Должен ли я использовать HAS_MANY Пользователь роли (пользователь может иметь одну запись для каждого типа роли) или HAS_ONE роль (пользователь может иметь только одну роль записи, которая должна быть включена, если их изменения роли) шаблон ?

class User < ActiveRecord::Base 
    attr_accessible :name, :email 
    has_many :accounts, through: roles 
end 

class Account < ActiveRecord::Base 
    attr_accessible :title 
    has_many :users, through: roles 
end 

class Role < ActiveRecord::Base 
    attr_accessible 
    belongs_to: :user 
    belongs_to: :account 
end 

ответ

2

Вы можете использовать «как» с attr_accessible, чтобы иметь разные возможности назначения. Например,

attr_accessible :type, as: :admin 

Затем, когда вы делаете массовое назначение, вы можете сделать что-то вроде

@role.update_attributes {type: :moderator}, as: :admin # Will update type 
@role.update_attributes {type: :moderator} # Will not update type 
+0

Вы были бы любезны сообщить мне разницу между вашим подходом и предложением Flexoid (см. Другой ответ). – Mohamad

+0

Я действительно не вижу разницы. Похоже, решение Flexoid переводит логику от модели к контроллеру, что я бы не рекомендовал. (Помните, Rails защищает толстые модели, тощие контроллеры.) Я думаю, что у вас действительно есть две вещи, происходящие здесь. Одна из них - авторизация атрибута (тип роли), а другая - авторизация модели (тип роли). Я написал довольно подробный отчет о CanCan и о том, что вы можете сделать с ним здесь: http: // stackoverflow.com/questions/7130853/define-ability-in-more-complex-environment-with-role-and-group-models/7133839 # 7133839 – Max

+0

Кроме того, вы можете делать такие вещи, как пользователь u1, который вы хотите изменить, вы можете проверить, что зарегистрированный пользователь является администратором группы u1 принадлежит и т. д. Я определенно думаю, что CanCan - это способ пойти на это. Я пробовал другие, выполненные на заказ решения, дважды, и оба раза я возвращался в CanCan. Я бы хотя бы предложил прочитать вики. – Max

1

Наиболее гибкий подход является переопределить mass_assignment_authorizer метод в классе модели, чтобы изменить доступные атрибуты динамически.

Например:

class Article < ActiveRecord::Base 
    attr_accessible :name, :content 
    attr_accessor :accessible 

    private 
    def mass_assignment_authorizer 
    super + (accessible || []) 
    end 
end 

Теперь можно использовать это следующим образом:

@article.accessible = [:important] if admin? 

этого примера, из RailsCast #237, где вы можете узнать более подробную информацию об этом подходе.


Кроме того, я хочу порекомендовать вам CanCan драгоценный камень, который может помочь вам справиться с ролями и способностями.

+0

Спасибо. Вы порекомендовали бы это, используя 'as:: admi'? Кроме того, я должен был задать вопрос отдельно, но у вас будет несколько или одиночных записей роли на пользователя? (вопрос бонуса) – Mohamad

+0

Как я уже сказал, это решение более гибкое и дает вам возможность интегрировать защиту массового присвоения с любой системой авторизации. Обычно я использую только одно поле в пользовательской модели, представляющее его роль и «список» абстракций для каждой роли. Для последнего я предпочитаю cancan gem, который очень прост в использовании. – Flexoid

+0

Да, мне нужна таблица ролей. У меня есть много учетных записей, которые могут быть подписаны и модерированы многими пользователями. Таким образом, одно поле не является вариантом. Я просто не уверен, следует ли придерживаться одной или нескольких строк для каждого типа ролей для каждого пользователя на одну учетную запись. Идти, чтобы это зависало, но больше, прежде чем я приму ответ. Ура! – Mohamad

Смежные вопросы