首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Pundit::AuthorizationNotPerformedError

Pundit::AuthorizationNotPerformedError
EN

Stack Overflow用户
提问于 2021-02-19 17:52:39
回答 1查看 125关注 0票数 0

这是我在食谱展示页面上看到的:

我的控制器看起来像这样:

代码语言:javascript
复制
class RecipesController < ApplicationController
  skip_before_action :authenticate_user!, only: [:index, :show]
  def index
    if params[:query].present?
      @recipes = policy_scope(Recipe).search_by_title_and_description(params[:query]).order(created_at: :desc)
    else
      @recipes = policy_scope(Recipe).order(created_at: :desc)
    end
  end

  def show
    @recipe = Recipe.find(params[:id])
    @recipes = Recipe.first(5)
  end
end

我的policy.rb:

代码语言:javascript
复制
class RecipePolicy < ApplicationPolicy
  class Scope < Scope
    def resolve
      scope.all
    end

    def index?
      false
    end

    def show?
      false
    end
  end
end

这是在向show操作添加'authorize @recipe‘时出现的错误消息:

我需要为每个食谱,但不是食谱显示行动本身的评论专家授权。我做错了什么?谢谢你的帮助!!

EN

回答 1

Stack Overflow用户

发布于 2021-02-19 18:26:04

authenticate_user! (您还没有向我们展示/解释过它,但可能是devise中的一种方法或类似方法?)可能与登录有关--那是身份验证,而不是授权,因此超出了Pundit试图解决的范围。

身份验证就是检查“你登录了吗?”如果此检查失败,则服务器将使用401 status进行响应。

授权就是检查“您是否被允许执行此操作(可能是作为来宾)?”如果此检查失败,则服务器将以403 status响应

现在,您可能还在应用程序中添加了一些代码,如下所示:

代码语言:javascript
复制
class ApplicationController < ActionController::Base
  include Pundit
  after_action :verify_authorized, except: :index # !!!!!
end

这个after_action检查是一个安全网;它确保您永远不会忘记授权一个端点--因为默认情况下,这将允许任何用户执行该操作!此检查的存在是导致上述错误的原因。

所以。解释完这一点后,让我们看看如何实现它。

  1. 应可由RecipesController#show guests访问,或仅可由登录的访问

如果且仅当答案是"guests“,则添加以下内容:

代码语言:javascript
复制
skip_before_action :authenticate_user!, only: :show

  1. 假设您已经执行了所有必要的身份验证,您希望让任何用户看到任何recipe。你如何实现它呢?

选项1(推荐):

代码语言:javascript
复制
class RecipePolicy < ApplicationPolicy
  class Scope < Scope
    def resolve
      scope.all
    end
  end ## WARNING!! NOTICE THAT THE `Scope` CLASS ENDS HERE!!!

  def show?
    true # !!!!
  end
end

class RecipesController < ApplicationController
  # ...
  def show
    @recipe = Recipe.find(params[:id])
    authorize(@recipe) # !!!
    # ...
  end
end

选项2(同样有效,但更糟糕的是,因为它意味着您不能依赖策略类的单元测试):

代码语言:javascript
复制
class RecipesController < ApplicationController
  def show
    skip_authorization # !!!
    @recipe = Recipe.find(params[:id])
    # ...
  end
end
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/66275290

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档