Рельсы предотвращают изменение URL - PullRequest
1 голос
/ 07 марта 2019

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

Например, я установил URL в этой части веб-сайта, чтобы искать значение 1a из /pathfinder/a/quest1/1a/q1sub1/, чтобы отобразить определенную часть страницы индекса q1sub1.

Если бы кто-то изменил значение 1a на 1n Я хотел бы проверить, изменился ли URL-адрес, и выдать какое-то сообщение об ошибке.

Не уверен, каким фрагментом кода поделиться в этом случае, поэтому дайте мне знать, если вам нужна дополнительная информация.

Я открыт для любых идей и ценю любой вклад. Спасибо!

Ответы [ 2 ]

0 голосов
/ 09 марта 2019

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

Вот пример.

Пользователь получит доступ к /foo и передаст пользовательский параметр data. Приложение будет использовать этот параметр для создания настраиваемого URL-адреса в формате /my/secret/:one/path/:two и перенаправления клиента на него. Это просто для простоты, и тот же подход может быть применен, если сгенерированный URL будет использоваться как <a href="..."> на странице.

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

Давайте посмотрим на код. Маршруты:

Rails.application.routes.draw do
  get :foo, to: 'example#foo'
  get '/my/secret/:one/path/:two', to: 'example#bar', as: 'bar'
end

И контроллер:

class ExampleController < ApplicationController
  # GET   /foo?data=xx  foo_path
  #
  def foo
    user_data = request[:data]
    go_to_path = bar_path(one: user_data, two: "foobar")
    go_to_path += "?check=#{url_fingerprint(go_to_path)}"

    redirect_to go_to_path
  end

  # GET   /my/secret/:one/path/:two  bar_path
  #
  def bar
    unless valid_request?
      render plain: "invalid request!", status: 403
      return
    end

    render plain: "this is a good request", status: 200
  end

  private

  SECRET = ENV.fetch("URL_FINGERPRINT_SECRET", "default secret")

  # Calculate the fingerprint of a URL path to detect
  # manual tampering.
  #
  # If you want to restrict this to a single client, add
  # some unique identifier stored in a cookie.
  #
  def url_fingerprint(path)
    Digest::SHA2.hexdigest(path + SECRET)
  end

  def valid_request?
    return false unless params[:check].present?
    params[:check] == url_fingerprint(request.path)
  end
end

При этом клиент будет начинать с:

$ curl -i -s http://localhost:3000/foo?data=hello | grep Location
Location: http://localhost:3000/my/secret/hello/path/foobar?check=da343dd84accb4c0f5f7ff1d6e68152ac124ca1a39ce4746623bcb7b9043cab3

А потом:

curl -i http://localhost:3000/my/secret/hello/path/foobar?check=da343dd84accb4c0f5f7ff1d6e68152ac124ca1a39ce4746623bcb7b9043cab3
HTTP/1.1 200 OK

this is a good request

Но если URL будет изменен:

curl -i http://localhost:3000/my/secret/IWASCHANGED/path/foobar?check=da343dd84accb4c0f5f7ff1d6e68152ac124ca1a39ce4746623bcb7b9043cab3
HTTP/1.1 403 Forbidden

invalid request!

То же самое произошло бы, если бы сам отпечаток был модифицирован или его не было.

0 голосов
/ 07 марта 2019

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

def show # for example
  if request.referrer != "http://example.com/myformpage"
    redirect_to root_path, notice: "Invalid access"
  else 
    # do stuff
  end
end

Однако это все еще не безопасно, поскольку заголовки могут быть подделаны (спасибо @Holgar Just).Если вы действительно хотите обеспечить безопасность в своем приложении, вам следует прочитать документацию , а если вам нужен более детальный контроль над разрешениями пользователей, возможно, обратитесь к CanCanCan gem

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