开发者

Devise and current user

开发者 https://www.devze.com 2023-03-01 14:17 出处:网络
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

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.

开发者_如何学JAVA

So 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
0

精彩评论

暂无评论...
验证码 换一张
取 消