首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >更改表单redirects_to的位置

更改表单redirects_to的位置
EN

Stack Overflow用户
提问于 2014-04-25 03:37:49
回答 3查看 187关注 0票数 1

当用户(没有登录)遵循我在电子邮件中发送给他们的确认链接时,用户确认是如何工作的:

更新:好的,考虑一下,用户确认只是为了测试电子邮件地址的存在,而与安全性无关。说到这里,我仍然想知道如何改变表单的重定向方向,以这个问题为例。

他们沿着确认路径->重定向在表单->中签名,他们在正确的->中签名,他们必须再次遵循链接,->,他们到达确认动作->,他们被确认了

这有点笨拙。我宁愿这样做:

他们沿着确认路径->重定向在表单->中签名,他们正确地在->中签名,他们到达确认动作->,他们被确认了

我想消除第二次遵循链接的需要,但我不知道如何继续这样做。这是我的sign_in表格:

代码语言:javascript
复制
<%= form_for(:session, url: sessions_path) do |f| %>
    <%= f.label 'Email address' %><br>
    <%= f.text_field :email, class: 'form-control', placeholder: 'Enter email' %><br>

    <%= f.label 'Password' %><br>
    <%= f.password_field :password, class: 'form-control', placeholder: 'Enter password' %><br>


    <%= f.submit 'Sign In', class: 'btn btn-default' %>
<% end %>

它将其参数传递给我的sessions#create操作:

代码语言:javascript
复制
def create
    user = User.find_by(email: params[:session][:email].downcase )

    if user && user.authenticate(params[:session][:password])
        sign_in(user)
        redirect_to user_path(current_user)
    else
        flash.now[:error] = 'Wrong email or password!'
        render 'new'
    end
end

现在我相信关键就在行动的第5行:

代码语言:javascript
复制
redirect_to user_path(current_user)

这需要改变。我相信我能在这里搞到一些东西,但我想知道你将如何处理这个问题。

  • 确认路径的操作必须设置一个变量,该变量将存储我们想要的新路径。
  • 然后,create redirect_to应该在默认的user_path之上使用这个变量。
  • 然后应该清空变量,这样再次登录就不会重定向到确认操作。
  • 为了做到这一点,应该将这个变量存储在哪里?在会议上?
  • 我应该如何以最开放的方式解决这个问题,这样如果需要的话,我可以很容易地为其他形式解决这个问题。
  • 考虑到这一点,我们存储路径的变量可能是一个散列,将有几个键值对。然后,我们的动态表单的创建操作只检查与它们相关的键值。
  • 我对宝石过敏,因为它们会让人们停止学习,但是如果你知道任何这样做的话,我仍然想知道。但请先告诉我如何为自己做这件事:)
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2014-04-30 00:36:51

说到这里,我仍然想知道如何改变表单的重定向方向,以这个问题为例。

我可以给你一个想法和最普遍的做法,大家都遵循。

如果用户未登录并重定向到该部分,则只需保存请求的路径即可。设计创业板也使用同样的策略,如果你使用的话,你可以利用它的优势。

我是在描述一般的解决办法。要保存和获取存储位置,需要在application控制器中使用两种方法

store_location:用于存储位置,所以我们将在登录后重定向它。

代码语言:javascript
复制
def store_location(location)
  if location
    uri = URI.parse(location)
    session["return_path"] = [uri.path.sub(/\A\/+/, '/'), uri.query].compact.join('?')
  end
end

stored_location:用于检索保存的位置(尝试定位)。同时删除会话路径(我将在最后部分对其进行解释)。

代码语言:javascript
复制
def stored_location
 location = session["return_path"]
 session.delete("return_path")
 location
end

你必须在你的confirmation控制器中做这样的事情

代码语言:javascript
复制
before_action: authenticated!

def authenticated!
  unless signed_in?
    store_location_for(request.original_url)
    redirect_to sign_in_path
  end
end

您只需自定义session#create控制器,这样的东西会工作。

代码语言:javascript
复制
 redirect_to stored_location ||  user_path(current_user)

现在,考虑一下你的女儿

  1. 他们遵循确认路径
  2. 重定向到在表单中签名(它还将确认路径位置存储在会话中)
  3. 他们正确地签名,他们将被重定向以确认路径,所以我们消除了额外的步骤
  4. 让假设使用确认,做某事和签名。他访问了网站,点击了“登录”按钮,并试图正常地进行登录。如果我们没有删除/删除他最后一次尝试从会话中删除url,他将被重定向到同一个地方,为了避免这一点,我们做了session.delete("return_path").

我希望这能说明清楚。

PS:上面的代码是抽象的,如果您有基于角色的应用程序,您必须对位置进行不同的范围调整,我还没有解释这件事,因为它远远超出了这个主题。如果你想学得更多,你可以读 gem specs

票数 3
EN

Stack Overflow用户

发布于 2014-04-25 16:45:50

根据我们的意见,我首先创建一个确认模型。

代码语言:javascript
复制
rails g model Confirmation key:string user_id:integer

可以使用回调生成随机散列:

代码语言:javascript
复制
require 'securerandom'
  ...
  before_validation :generate_random_key
  belongs_to :user  
  validates_uniqueness_of :user_id
  ...
  private

  def generate_random_key
    self.key = SecureRandom.hex(32)
  end

然后,用于创建新注册的控制器为新用户向该模型添加一条记录。此外,User模型有一个has_one :confirmation关系是合适的。(Rails has_one实际上意味着0或1。)

接下来,使用确认控制器将用户的状态设置为“确认”。类似于:

代码语言:javascript
复制
rails g controller confirmation new

然后我会编辑config/routes.rb以使用单一的CRUD资源路径,因为只有

代码语言:javascript
复制
resource :confirmation, only: :new

这样,您的电子邮件中的路径应该如下所示:

代码语言:javascript
复制
.../confirmation?key=<long hex string>

控制员:

代码语言:javascript
复制
class ConfirmationController < ApplicationController

  def new
    key = params[:key]
    user = key && User.joins(:confirmation).where(key: key)
    if user
      user.confirmation.destroy  # Kill the confirmation. It's not needed any more.
      user.confirmed = true      # Mark the user confirmed
      user.save!                 # Update her record.
      flash[:alert] = 'Your registration has been confirmed. Log in for full service!'
    else
      flash[:error] = 'Your confirmation link is broken or expired. Log in to request a new one.'
    end
    redirect_to controller: :sessions, :action: :new 
  end

end

会话控制器应该重定向到一个“无服务”登陆页面,该页面在未经确认的用户登录时显示。只有一件事会有一个链接,要求一个新的确认电子邮件。对于确认的用户登录,它将重定向到完整的服务登陆页面。

在创建新的确认记录之前,删除用户存在的任何旧确认记录。如果需要,可以使用后台作业过期未使用的作业。

票数 2
EN

Stack Overflow用户

发布于 2014-05-02 22:18:33

我更喜欢将重定向URL作为参数传递给Paritosh解决方案的变体,而不是将其存储在会话中。它更容易受到XSS攻击(因此您在重定向时需要小心验证),但如果用户在登录前打开多个选项卡到站点上的不同页面,则不会中断。这是我最讨厌的事。)

基本思想是,当重定向到表单中的符号时,身份验证检查总是在目标路径上传递:

代码语言:javascript
复制
# Variation on Paritosh's solution
before_action: authenticated!

def authenticated!
  unless signed_in?
    uri = URI.parse(request.original_url)
    redirect_to sign_in_path(redirect_path: [uri.path.sub(/\A\/+/, '/'), uri.query].compact.join('?'))
  end
end

然后,您的表单中的签名将该路径与用户名和密码一起传递出去。

代码语言:javascript
复制
<%= form_for(:session, url: sessions_path) do |f| %>
    <%= hidden_field_tag(:redirect_path, params[:redirect_path]) if params[:redirect_path] %>
    <%= f.label 'Email address' %><br>
    <%= f.text_field :email, class: 'form-control', placeholder: 'Enter email' %><br>

    <%= f.label 'Password' %><br>
    <%= f.password_field :password, class: 'form-control', placeholder: 'Enter password' %><br>


    <%= f.submit 'Sign In', class: 'btn btn-default' %>
<% end %>

然后会话控制器重定向到该路径(如果有效的话)

代码语言:javascript
复制
def create
    user = User.find_by(email: params[:session][:email].downcase )

    if user && user.authenticate(params[:session][:password])
        sign_in(user)
        redirect_path redirect_path || user_path(current_user)
    else
        flash.now[:error] = 'Wrong email or password!'
        render 'new'
    end
end

private

def redirect_path
    params[:redirect_path] if params[:redirect_path] && params[:redirect_path] =~ /\A\/[^\/]/
end

如果您使用子域作为服务中的登录,则可以传递完整的URL,而不仅仅是路径。在这种情况下,您需要验证URL中的主机名是否是您拥有的主机名。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/23283711

复制
相关文章

相似问题

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