Лучшая маршрутизация маршрута RESTful при обращении к current_user с маршрута?
У меня типичные маршруты RESTful для пользователя:
/user/:id
/user/:id/edit
/user/:id/newsfeed
Однако маршрут /user/:id/edit
может быть доступен только тогда, когда id равен идентификатору current_user. Поскольку я хочу, чтобы current_user имел доступ к редактированию своего профиля. Я не хочу, чтобы другие пользователи могли редактировать профили, которые не принадлежат им.
Как правило, лучше всего справиться с этой ситуацией?
Должен ли я оставить маршрут как есть, и через ошибку, если current_user.id != param[:id]
, заставляя клиентского интерфейса, вызывающего api, отслеживать зарегистрированный идентификатор пользователя?
Должен ли я сделать специальный маршрут /user/self/edit
и в контроллере проверить, есть ли param[:id] == 'self'
?
Ответы
Ответ 1
Я бы добавил специальные маршруты для текущих действий профиля пользователя, в этом случае вам не нужно ничего проверять. Просто загрузите и отобразите данные текущего пользователя. Например:
/my-profile/edit
/my-profile/newsfeed
Это не тот RESTful, но вам не нужно ставить лишние проверки, чтобы ваш код был чистым.
Если вам все еще нужно (или хотите иметь) строгие маршруты RESTful, я бы использовал файл before_filter и проверить, равен ли id = current_user.id. Если нет, верните 401 или 403.
Ответ 2
Я хочу, чтобы current_user имел доступ к редактированию своего профиля. я не хотите, чтобы другие пользователи могли редактировать профили, не принадлежащие их.
Я предлагаю использовать некоторые графы авторизации, например pundit p >
Пример кода:
class UserPolicy
attr_reader :current_user, :model
def initialize(current_user, model)
@current_user = current_user
@user = model
end
def edit?
@current_user == @user
end
end
Также с аутентификационным камнем, например Разработать, только current_user
(пользователи, которые вошли в систему) могут просматривать и редактировать свои профили только
Ответ 3
Я бы сказал, что вы делаете это правильно, просто сохраняйте свой текущий маршрут, как сейчас. И что вы должны сделать, так это добавить ограничение в свой контроллер. Я бы предположил, что вы используете Rails и работаете с users_controller.
class UsersController < ApplicationController::Base
def edit
if current_user.id == params[:id]
# do your work
else
render :404
end
end
end
Или вы можете очистить свой контроллер, переместив ограничение на обратный вызов:
class UsersController < ApplicationController::Base
before_filter :restrict_user, only: [:edit]
def edit
# do your work
end
private
def restrict_user
render :404 unless current_user.id == params[:id]
end
end
Ответ 4
Вы можете добавить gem "cancancan"
и после инициализации....
class Ability
include CanCan::Ability
def initialize(user)
can :update, User do |user|
user.id == params[:id]
end
end
end
Затем добавьте этот authorize! :edit, @user
к вашему действию обновления
Ответ 5
Вам нужно будет добавить код авторизации во всех методах user_controller в качестве другого комментария. Обычно то, что я делаю в приложениях, где пользователь должен только редактировать свой собственный профиль, я добавляю маршрут/профиль для пользователя, чтобы отредактировать свой собственный профиль, а затем на маршрутах main/users/: id/*. Я добавляю логику, чтобы предотвратить -admin пользователей от доступа к этим маршрутам.
Ответ 6
Пользователь может просматривать его профиль /users/1
или редактировать его профиль /users/1/edit
. С точки зрения пользователей эти URL-адреса абсолютно прекрасны.
Нет ссылок, которые могут привести пользователя к редактированию другого пользователя. Вы пытаетесь охватить различную ситуацию: когда кто-то вручную пытается создать URL-адрес и получить доступ к другой учетной записи. Я бы не назвал их хакерами, но технически они - пользователи, которые пытаются использовать ваш сайт, чтобы передать ограничения.
Вам не нужно беспокоиться о удобстве "хакеров". Я всегда использую current_user
в действии edit
, поэтому никто не может редактировать неправильный профиль независимо от его профиля.
def edit
@user = current_user
end
Кроме того, я должен упомянуть, что вы должны также покрыть действие update
с такими проверками. С помощью edit
вы можете получать данные (и, возможно, только широко открытые открытые данные, если вы не добавили в шаблон edit
платежную информацию или текстовые пароли). Но с update
вы можете реально изменить данные, которые могут быть более разрушительными.
Ответ 7
Поскольку кажется, что единственный доступный пользовательский ресурс должен быть аутентифицированным пользователем, я думаю, что лучший способ решить это -
GET /user
PUT /user
GET /user/newsfeed
Если вам нравится расширять использование api в будущем, чтобы один пользователь мог получить доступ к другим ресурсам пользователя, вам нужно решение, которое включает идентификаторы пользователя. Здесь имеет смысл вводить маршруты для "я" тоже. Но тогда вам также нужно выполнить проверку доступа на стороне сервера.
GET /user/id/:id
PUT /user/id/:id
GET /user/id/:id/newsfeed
GET /user/self
PUT /user/self
GET /user/self/newsfeed
Но я думаю, вы должны держать его как можно проще
Для дальнейших исследований я бы предложил такие книги, как http://apigee.com/about/resources/ebooks/web-api-design, которые дают хорошее представление о дизайне API
Ответ 8
Поскольку вы только хотите предоставить конечные точки RESTful только для текущего пользователя, прошедшего проверку подлинности, который доступен в ваших контроллерах как current_user
, я говорю, что вам не нужен параметр идентификатора id
. Я предлагаю использовать следующие маршруты:
GET /user => users#show
PUT/PATCH /user => users#update
GET /user/edit => users#edit
Ответ 9
Вы должны сохранить url как есть. Аутентификация и авторизация являются отдельными проблемами. "current_user" относится к пользователю, который прошел аутентификацию для доступа к apis. Идентификатор в URL-адресе идентифицирует ресурс, на котором работает "current_user", так что у него есть доступ к этому ресурсу или нет, это проблема авторизации. Поэтому вы должны добавить current_user.id != param[:id]
(как вы упомянули) в свои разрешения api и выдать код статуса 403 в ответ.
Ответ 10
Вы должны использовать этот маршрут:
PUT /user/me
Обратите внимание, что нет необходимости в "редактировании": вместо этого вы должны использовать метод PUT
.
Кроме того, вы должны явно указать маршрут, который я написал выше, вместо проверки, если id == 'self'
.