Хобрук: Ваш путь к мастерству в программировании

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

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

Я оставил 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 и т. Д. И унаследовать их от роли. Если я хочу придерживаться единой ролевой модели, как я могу иметь динамические роли, не подвергая себя уязвимости массового назначения?

Дополнительный вопрос: следует ли использовать роль пользователя 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

Ответы:


1

Вы можете использовать «as» с 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
29.04.2012
  • не могли бы вы рассказать мне разницу между вашим подходом и подходом Flexoid (см. другой ответ) 30.04.2012
  • Я действительно не вижу разницы. Кажется, что решение Flexoid перемещает логику с модели на контроллер, что я бы не рекомендовал. (Помните, Rails отстаивает толстые модели и тонкие контроллеры.) Я думаю, здесь действительно происходят две вещи. Первый - это авторизация по атрибуту (тип роли), а другой - авторизация модели (чей тип роли). Я написал довольно подробный пост о CanCan и его возможностях здесь: stackoverflow.com/questions/7130853/ 30.04.2012
  • Кроме того, вы можете делать такие вещи, как, учитывая пользователя u1, которого вы хотите изменить, вы можете проверить, является ли вошедший в систему пользователь администратором группы, к которой принадлежит u1 и т. Д. Я определенно думаю, что CanCan - это способ для этого. Я дважды пробовал другие решения, созданные на заказ, и оба раза возвращался в CanCan. Я бы по крайней мере посоветовал почитать вики. 30.04.2012
  • спасибо, я думаю, что пойду на этот подход. И последнее: я просто не уверен, следует ли придерживаться одной или нескольких строк для каждого типа роли для каждого пользователя для каждой учетной записи. Итак, если у User1 будет 3 строки в ролях (мод, админ и т. Д.) Или только одна строка, которая будет переключаться / изменяться! 30.04.2012
  • Кроме того, я предполагаю, что вы упустили необходимость писать вспомогательный метод, чтобы получить роль curret_user 30.04.2012

  • 2

    Самый гибкий подход - переопределить метод 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, который поможет вам справиться с ролями и способностями.

    29.04.2012
  • Спасибо. Вы бы порекомендовали это вместо использования as: :admi? Кроме того, мне следовало задать вопрос отдельно, но будет ли у вас несколько или одна запись роли для каждого пользователя? (бонусный вопрос) 30.04.2012
  • Как я уже сказал, это решение более гибкое и дает вам возможность интегрировать защиту массового назначения с любой системой авторизации. Обычно я использую только одно поле в модели пользователя, представляющее его роль и список способностей для каждой роли. Из последнего я предпочитаю драгоценный камень канкан, который очень прост в использовании. 30.04.2012
  • Да, мне нужна таблица ролей. У меня много учетных записей, на которые могут подписаться и модерировать многие пользователи. Так что одно поле не вариант. Я просто не уверен, следует ли придерживаться одной или нескольких строк для каждого типа роли для каждого пользователя на учетную запись. Я собираюсь позволить этому повиснуть еще немного, прежде чем я приму ответ. Ваше здоровье! 30.04.2012
  • Новые материалы

    Основы принципов S.O.L.I.D, Javascript, Git и NoSQL
    каковы принципы S.O.L.I.D? Принципы SOLID призваны помочь разработчикам создавать надежные, удобные в сопровождении приложения. мы видим пять ключевых принципов. Принципы SOLID были разработаны..

    Как настроить Selenium в проекте Angular
    Угловой | Селен Как настроить Selenium в проекте Angular Держите свое приложение Angular и тесты Selenium в одной рабочей области и запускайте их с помощью Mocha. В этой статье мы..

    Аргументы прогрессивного улучшения почти всегда упускают суть
    В наши дни в кругах веб-разработчиков много болтают о Progressive Enhancement — PE, но на самом деле почти все аргументы с обеих сторон упускают самую фундаментальную причину, по которой PE..

    Введение в Джанго Фреймворк
    Схема «работать умно, а не усердно» В этой и последующих статьях я познакомлю вас с тем, что такое фреймворк Django и как создать свое первое приложение с помощью простых и понятных шагов, а..

    Настольный ПК как «одно кольцо, чтобы править всеми» домашних компьютеров
    Вид после 9 месяцев использования С настольных компьютеров все началось, но в какой-то момент они стали «серверами», и мы все перешли на ноутбуки. В прошлом году я столкнулся с идеей настольных..

    Расширенные методы безопасности для VueJS: реализация аутентификации без пароля
    Руководство, которое поможет вам создавать безопасные приложения в долгосрочной перспективе Безопасность приложений часто упускается из виду в процессе разработки, потому что основная..

    стройный-i18следующий
    Представляем стройную оболочку для i18next. Эта библиотека, основанная на i18next, заключает экземпляр i18next в хранилище svelte и отслеживает события i18next, такие как languageChanged,..