2

我想通过 JSON POST 在 Rails 服务器上创建一个“图像”对象。这工作得很好,但现在我添加了用户身份验证,它不再工作了。我使用 gem 'devise' 进行身份验证。注册、登录和注销与 json 完美配合。

用户.rb:

class User < ActiveRecord::Base
  has_many :images

  attr_accessible :name, :email, :password, :password_confirmation, :remember_me, :encrypted_password

  has_secure_password

  validates :email, format: /^([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/i, uniqueness: true

end

图像控制器:

class ImagesController < ApplicationController

before_filter :require_login #checks if user is logged in before user accesses images

  respond_to :json

def index
    @images = current_user.images

    respond_to do |format|
      format.html { }
      format.json { render :json => {:success => true,
                      :info => "images",
                      :data => @images } }
    end

  end

  def edit
    @image = current_user.images.find(params[:id])
  end

  def new
    @image = current_user.images.build
  end


  def create
    @image = current_user.images.build(params[:image])

    respond_to do |format|
      if @image.save
        format.html { redirect_to images_path }
        format.json { render :json => @image }
      else
        format.html { render "new" }
        format.json { render json: @image.errors, status: :unprocessable_entity }
      end
    end #respond_to
  end

private

  def require_login
    unless user_signed_in? #in application_controller
      redirect_to login_path,
      alert: "Login first."
    end
  end

  end

会话控制器:

class SessionsController < ApplicationController

  respond_to :json

  def new
    #empty because no underlying model
  end


  def create
    #user = User.find_by_email(params[:user][:email]) #when JSON: { "user" : { "email":"asdf@asdf.at", "password":"asdf" }}
    user = User.find_by_email(params[:email]) #when JSON: { "email":"asdf@asdf.at", "password":"asdf" }

    respond_to do |format|
      if user && user.authenticate(params[:password]) #because user has_secure_password
        session[:user_id] = user.id

        format.html { redirect_to images_path, notice: "Login successful!" }
        format.json { render :json => {:success => true,
                      :info => "Logged in",
                      :data => { } } }
      else
        format.html { flash.now.alert = "Wrong email or password"
                    render "new" }
        format.json { render :json => {:success => false, :info => "Wrong email or password" } }
      end
    end
  end



  def destroy

    session[:user_id] = nil
    respond_to do |format|
      format.html { redirect_to root_path, notice: "Logout successful!" }
      format.json { render :json => {:success => true,
                      :info => "Logged out",
                      :data => { } } }
    end

  end


end

耙路线:

      root        /                          pages#home
 new_image GET    /images/new(.:format)      images#new
    images GET    /images(.:format)          images#index
     image GET    /images/:id(.:format)      images#show
           POST   /images(.:format)          images#create
edit_image GET    /images/:id/edit(.:format) images#edit
           PUT    /images/:id(.:format)      images#update
     image DELETE /images/:id(.:format)      images#destroy
     users POST   /users(.:format)           users#create
  new_user GET    /users/new(.:format)       users#new
     login GET    /login(.:format)           sessions#new
  sessions POST   /sessions(.:format)        sessions#create
    logout DELETE /logout(.:format)          sessions#destroy

应用程序控制器:

class ApplicationController < ActionController::Base
  protect_from_forgery

  def current_user
    if session[:user_id]
      @current_user ||= User.find(session[:user_id])
    end
  end

  def user_signed_in?
    current_user.present?
  end

  helper_method :user_signed_in?

end

登录后(显示图像也适用GET method and url http://localhost:3000/images),我无法使用 JSON 创建新图像。这是我来自客户端的请求(我使用 Chrome 的简单 REST 客户端):

url:           http://localhost:3000/images
method:        POST
Content-Type:  application/json
               Accept: application/json
Data:          {"image":{ "title":"someTitle","url": "someUrl" }}

回复:

500 Internal Server Error
<h1>Template is missing</h1>
<p>Missing template sessions/new, application/new with {:locale=&gt;[:en], :formats=&gt;[:json], :handlers=&gt;[:erb, :builder, :coffee]}. Searched in:
  * &quot;c:/Users/XXX/workspaceRubyOnRails/my_server/app/views&quot;
  * &quot;c:/RailsInstaller/Ruby1.9.3/lib/ruby/gems/1.9.1/gems/devise-2.2.4/app/views&quot;
</p>
4

2 回答 2

1

似乎您的 JSON 请求未经过身份验证。因此,Devise 会将您发送到登录页面。但是您没有登录页面的 JSON 版本,因此您会收到Missing template sessions/new错误消息。

您可以将 cookie 与请求一起发送,或者更好的是,使用Devise 的令牌身份验证,这样您就可以使用令牌进行请求,如下所示:

curl -v -H "Accept: application/json" -H "Content-type: application/json" http://localhost:3000/images?auth_token=<token>

您可以在此处找到一些代码示例:https ://github.com/plataformatec/devise/wiki/How-To:-Simple-Token-Authentication-Example

于 2013-06-24T00:46:31.260 回答
0

我认为您需要通过 Chrome Simple REST 客户端进行身份验证 - 您的 rails 应用程序似乎在区分 Chrome 本身和其余客户端。

一旦你克服了这个障碍,我会扩大这个答案。

于 2013-06-24T00:34:03.823 回答