Предотвращение возможности обнаружения в модели с REST-маршрутизацией - PullRequest
1 голос
/ 12 марта 2011

В моей базе данных есть модель, действие которой «show» открыто для просмотра по таким URL-адресам, как:

mysite.com/project/12
mysite.com/project/14

При настройке моей системы существует несколько определенных методов, с помощью которых этидолжно быть доступно:

  • Пользовательский маршрут, который я настроил, доступен для любого посетителя (зарегистрированного или незарегистрированного), который имеет этот маршрут.Например, этот пользовательский маршрут может быть mysite.com/companyname/projectid, который компания может раздавать себе определенным людям, к которым она хочет получить доступ.Обратите внимание, что этот пользовательский маршрут выполняет отдельное действие контроллера, которое устанавливает некоторую внутреннюю аналитику, а затем перенаправляет на действие show.
  • Прямой доступ при ссылке на домашнюю страницу зарегистрированного пользователя.

Я хочу ограничить возможность начать с mysite.com/project/14, а затем просто изменить идентификаторы, таким образом, просматривая любой проект.Как я могу это сделать?

Уточнение

Моя цель с этим вопросом - не просто запутать идентификаторы записей, чтобы затруднить обнаружение определенных записей.Вместо этого я хотел бы, чтобы было только два допустимых способа доступа к project/12:

  1. Пользователь нажимает на ссылку, которую мы предоставляем на его домашней странице (как я могу убедиться, что эта ссылка одна достигает проекта 12)?)
  2. Пользователь или простой посетитель перенаправляется сюда другим (определенным) действием контроллера.

Прямой ввод project/12 не должен быть возможен.На данный момент, я думаю, что лучший способ сделать это было бы для двух методов выше, чтобы передать код, который выбирается действием project#show.Я просто не знаю, как это реализовать и есть ли потенциальные недостатки.

Ответы [ 4 ]

2 голосов
/ 12 марта 2011

Что бы вы ни придумали - в конечном итоге это станет безопасностью из-за неясности из-за этого простого требования:

Пользователь нажимает на ссылку, которую мы предоставляем на его домашней странице (как я могуубедиться, что одна эта ссылка доходит до проекта 12?)

Однако вы можете просто затруднить точный выбор правильного URL-адреса для проекта.

Моя мысльбыло бы дать каждому проекту уникальный 'токен' - если вы не вошли в систему как владелец проекта, то вы должны использовать токен для доступа к нему.

Например, в вашей модели проекта вы могли быимейте это:

class Project
  before_create :set_public_token

  protected
    def set_public_token
      # Randomizes a 20-digit long hex code
      self.token = ActiveSupport::SecureRandom.hex(20)
    end
end

Затем в шоу-действии вашего проекта вам понадобится это:

class ProjectsController < ApplicationController
  def show
    @project = Project.find(params[:id])
    # Obviously you would changed signed_in? to whatever method
    # you have that verifies someone is logged in
    if !signed_in? || @project.owner_id != current_user.id
      raise "Unauthorized Access" if @project.token != params[:token]
    end
  end
end

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

www.example.com/projects/14?token=3jks83kasdkt84h6cd86

Опять же, любой с таким URL может получить доступ к проекту, и я не думаю, чтоВы сможете разумноИзбавьтесь от этого - но это делает его намного более сложным.

Это та же концепция, что и многие функции сброса пароля.Любой, у кого есть доступ к токену сброса пароля, может сбросить ваш пароль после того, как вы запросили пароль.Но, зная, какой токен использовать, у вас уйдут годы (сделайте токен длиннее, чтобы его было труднее переманивать).

Это то, как я бы с этим справился, и как я видел, как с этим справляются.прошлое (фотобакет, частные гистограммы на github и т. д.)

2 голосов
/ 12 марта 2011

Самый простой способ - связать проект с пользователем или учетной записью, а затем потребовать аутентификацию при просмотре ваших не публичных маршрутов. Если вы настроите ассоциацию, вы можете сделать:

@user = current_user
@project = @user.projects.find(params[:id])

Это гарантирует, что данный пользователь сможет найти только те проекты, которые ему «принадлежат».

Если вы не хотите авторизации и просто хотите запутать, вы не сможете использовать только «id» в маршруте (так как он последовательный). Вы можете либо связать 'id' со случайным ключом, хранящимся в модели (/ projects / 1? Key = 1234), либо использовать GUID вместо id.

1 голос
/ 12 марта 2011

ОК, теперь еще одна попытка, которую я вроде понимаю.

Сначала в вашем действии публичного контроллера вы хотите сделать что-то вроде этого:

def public_redirect
  session[:authorized_for] = params[:id]
  redirect_to resource_show_path(params[:id])
end

Теперь в вашем частном контроллере:

def show
  @resource = current_user.resources.find params[:id]
  if @resource # authorized
    respond_with @resource # ok
  elsif session[:authorized_for] == params[:id] #redirected from public route
    @resource = Resource.find params[:id]
    respond_with @resource # ok
  else
    raise NotAuthorizedException # not ok, do something
  end
end

Это зависит от сеансов.Это, конечно, можно взломать, но это будет гораздо сложнее, чем выяснить общественный маршрут.См. http://guides.rubyonrails.org/security.html#sessions.

. Вы можете повторно использовать технику сеанса для других аналогичных нужд (например, для ссылок с домашних страниц, где вы не можете проверить пользователя с контроллера и т. Д.

0 голосов
/ 12 марта 2011

У меня есть проект, который имеет аналогичные требования.Теперь, во-первых, я чувствую необходимость сказать, что это безопасность от неясности - и, следовательно, совсем не безопасность.Но для некоторых приложений, которые могут быть в порядке.

В моей модели есть обратный вызов при создании, который генерирует случайную строку (или число), которую я использую в качестве своего идентификатора - таким образом, невозможно трудно угадать путь другого ресурса.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...