I've set up Devise to manage the authentication to my app.
I have a Category model in which users create their own categories. User has_many :categories. This model has a user_id attribute, so when someone logs in and goes to categories/index for example, from the controller the query would bring categories using current_user.id to filter out which ones to bring.
开发者_如何学JAVASo far straight forward and works well, nobody seems to be able to see someone else's categories, but to be honest, unless I'm missing something, this seems a bit insecure. How do I know some hacker will not figure it out and send his own requests modifying the params?
Is this possible or am I being paranoid? Also, I might not be using the functionality properly?
Provided you're using the proper relationship between users
and categories
, i.e.
# in User.rb
has_many :categories
# in Category.rb
belongs_to :user
you should be able to use something like this in your controller:
@categories = current_user.categories
This way you're using the current user regardless of what parameters may be passed, and it will only get their galleries. You're not searching by a potentially insecure user_id anymore.
If you're worried about someone being able to view a category that isn't theirs, you can add your own private method similar to :authenticate_user!
to make sure that the category being shown or edited actually belongs to the current user, running it in a before_filter like the other one, and redirecting if they don't have permission.
private
def authenticate_owner!
if user_signed_in? && current_user.id == params[:id] # or something similar
return true
end
redirect_to root_url,
:notice => "You must have permission to access this category."
return false
end
I think you have the relationship setup for a one-to-one (one category per user) instead of a one-to-many (many categories per user). If you have a category_id
in the User
model, the following should be your setup.
# in User.rb
belongs_to :category
# in Category.rb
has_many :users
# in CategoriesController
@category = current_user.category
If you want to have multiple categories per user, than I suggest using a link table (as model UserCategory
) with user_id
and category_id
.
# in UserCategory.rb
belongs_to :user
belongs_to :category
# in User.rb
has_many :user_categories
has_many :categories, :through => :user_categories
# in Category.rb
has_many :user_categories
has_many :users, :through => :user_categories
Then, in your Category
controller you can use your code from above to grab all categories by a given user.
# in CategoriesController.rb
@categories = current_user.categories
Based on Josh's answer, I just made it into an if else statement. I converted params[:id]
to integer since current_user.id
returns one.
class UsersController < ApplicationController
before_filter :authenticate_owner!
#....
private
def authenticate_owner!
if user_signed_in? && current_user.id == params[:id].to_i
return
else
redirect_to root_url, :notice => "You must have permission to access this page."
end
end
end
精彩评论