ruby-on-rails - 从 Rails 应用程序为“公共”链接生成新路由
问题描述
我正在尝试建立一个“公共”链接,它使某人无需登录/授权即可访问我的应用程序的特定页面。
我对解决这个问题的最佳方法有点迷茫,所以寻求一些建议。
首先,我random_id
在对象的表中添加了一个我正在围绕 ( Captable
) 构建链接的对象。
我现在正在努力解决的是:我应该构建一个全新的控制器(例如PublicCaptableController
)并查看这个公共链接,以便我可以控制这个“公共查看器”会看到什么?或者有没有更简单的方法来使用我现有的 CaptablesController 创建一个新视图,它提供一组我可以使用现有控制器控制的选定信息?
我的一个想法是用以下内容编辑我application_controller.rb
的:
before_action :authenticate_user!, unless: -> params[:random_id].present?
但这感觉像是一个相当大的安全风险。我怎样才能以一种简单但更有效/安全的方式做到这一点?
感谢您的任何指导/帮助!
这是我的routes.rb
文件。
Rails.application.routes.draw do
devise_for :users
get '/landing', :to => redirect('/landing.html')
root 'companies#index'
post "companies/switch_current_company_context" => "companies#switch_current_company_context"
resources :companies do
resources :shareholders
resources :captables do
post :subscribe_to_captable
resources :events do
post :lock_event
post :unlock_event
resources :transactions
end
end
end
end
来自 CaptablesController 的片段
class CaptablesController < ApplicationController
before_action :set_company
before_action :set_captable, only: [:show, :edit, :update, :destroy]
def index
@captables = @company.captables
end
def show
@captable = Captable.find(params[:id])
end
来自 ApplicationController 的片段
class ApplicationController < ActionController::Base
protect_from_forgery with: :exception, unless: -> { request.format.json? }
before_action :authenticate_user!
def after_sign_in_path_for(resource_or_scope)
# Set a default current company scope for a use after signing in
session[:current_company] = current_user.companies.first.id unless current_user.companies.empty?
puts session[:current_company]
companies_path
end
end
解决方案
更新:这个答案已经过时了。在现代版本的导轨中,您应该使用has_secure_token
而不是重新发明轮子。
您可以向模型添加一个简单的访问令牌,并在通过查询字符串时使用它绕过授权/身份验证。
首先将列添加到表中:
rails g migration add_access_token_to_captables access_token:string
rails g migrate
然后你想要一个合适的伪随机令牌字符串。Ruby Stdlib 有一个 SecureRandom 模块,您可以使用它。
SecureRandom.hex(10) #=> "52750b30ffbc7de3b362"
让我们设置一个模型回调以在创建时生成一个随机令牌:
class Captable < ApplicationRecord
# ...
after_validation :set_access_token!, if: :new_record?
private
def set_access_token!
self.access_token = loop do
random_token = SecureRandom.hex(10)
break random_token unless self.class.exists?(access_token: random_token)
end
end
end
然后您可以使用令牌有条件地跳过回调:
class CaptablesController
skip_before_action :authenticate_user, if: :has_valid_access_token?, only: :show
private
def has_valid_access_token?
params[:access_token].present? && Captable.exists?(params.permit(:access_token, :id))
end
end
这比在 ApplicationController 中处理它更安全,因为您有选择地添加单个异常。
这是一种更简单的方法,它使用单个令牌让任何人都可以访问单个资源。您还可以通过创建一个单独的表并在使用后销毁/使它们失效来创建一次性令牌。
推荐阅读
- .net - 如何从 NuGet 安装包
- android - 运行后我无法使用 Flutter 运行我的第一个应用程序我收到此错误
- flutter - 当我运行我的代码时,为什么在 _WidgetsAppState 中找不到路由 RouteSettings("/coursePage", null) 的生成器
- reactjs - Tailwind css 在部署时不工作
- winapi - 如何在winapi-rs中获取IWICImagingFactory的实例
- ruby-on-rails - 地理编码器(alexreisner 版本)为我返回不正确的坐标
- nlp - RuntimeError:堆栈期望每个张量大小相等,但在条目 0 处得到 [5391],在条目 1 处得到 [8441]
- c++ - 从链表中的 getNext()、getPrev() 或 getData() 函数返回 NULL
- javascript - 如何在 appscripts 中获取 code.js 的生命周期摘要而不是 7 天?
- elasticsearch - ElasticSearch 如何过滤一个索引然后聚合?