2013-06-24 17 views
2

Я хочу создать объект 'image' на сервере rails JSON POST. Это сработало отлично, но теперь я добавил аутентификацию пользователя, и он больше не работает. Для аутентификации я использую «изобретать» драгоценный камень. Регистрация, вход в систему и выход из системы отлично работают с json.рельсы: создать новый объект с помощью json и аутентификацию пользователя

user.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 

images_controller:

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 

sessions_controller:

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":"[email protected]", "password":"asdf" }} 
    user = User.find_by_email(params[:email]) #when JSON: { "email":"[email protected]", "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 

application_controller:

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. Это мой запрос от клиента (я использую Simple REST Client для Chrome):

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> 

ответ

1

Похоже, что ваш запрос JSON не аутентифицирован. Из-за этого Devise отправляет вас на страницу входа. Но у вас нет JSON-версии вашей страницы входа и, следовательно, вы получаете ошибку Missing template sessions/new.

Вы можете отправить печенье вместе с просьбой или даже лучше, используйте token authentication из Завещания, так что вы можете сделать свой запрос с маркером для аутентификации, как это:

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

+0

Мне нужно было бы добавить к пользователю столбец «authentication_token», верно? –

+0

@ AndiR. Да, вам нужен столбец «authentication_token». – htanata

+0

Я согласен. Чтобы поддерживать сеанс, вы должны отправить cookie в заголовок с каждым запросом. Я рекомендую auth для файлов cookie для API, потребляемых одностраничным приложением в браузере, и omniauth для API, потребляемых третьими лицами. – user1158559

0

Я думаю, что вам нужно для проверки подлинности с помощью простого клиента REST Chrome - ваши рельсы приложение, как представляется, быть дифференцированным между самим Chrome и остальным клиентом.

Я разберу этот ответ, как только вы преодолеете это препятствие.

+0

Ну, аутентификация, похоже, работает от простого клиента REST, потому что я могу войти на сервер, а затем просмотреть изображения конкретного пользователя, поэтому GET работает. –

+0

Что содержит «require_login»? –

+0

Я отредактировал свое оригинальное сообщение. «require_login» означает, что доступ к изображениям возможен только при входе пользователя в систему (для предотвращения внешнего доступа с «случайным» идентификатором пользователя). –