Ember auth с разработкой CORS или CSP?вопрос - PullRequest
0 голосов
/ 12 мая 2018

Я работаю над безголовым приложением Rails с Ember на внешнем интерфейсе.Я пытался заставить аутентификацию работать с devise.Я следовал этому руководству: http://romulomachado.github.io/2015/09/28/using-ember-simple-auth-with-devise.html, но в журналах я получаю следующее:

Started POST "/users/sign_in" for 127.0.0.1 at 2018-05-12 01:36:58 -0700
Processing by SessionsController#create as JSON
Parameters: {"user"=>{"password"=>"[FILTERED]"}, "session"=>{"user"=>{"password"=>"[FILTERED]"}}}
HTTP Origin header (http://localhost:4200) didn't match request.base_url (http://localhost:3000)
Completed 422 Unprocessable Entity in 1ms (ActiveRecord: 0.0ms)
ActionController::InvalidAuthenticityToken
(ActionController::InvalidAuthenticityToken):

Я запускаю приложение rails локально на порте по умолчанию :3000, а также запускаю экземпляр emberлокально (из другого каталога) на порту по умолчанию :4200.

Я установил ember-cli-cors и ember install ember-cli-content-security-policy и перепробовал все, что знаю, чтобы он заработал.Любая помощь с благодарностью.

Вот мои файлы:

//config/environment.js
module.exports = function(environment) {
  let ENV = {
    modulePrefix: 'dino-ui',
    environment,
    rootURL: '/',
    locationType: 'auto',
    contentSecurityPolicy: {
      'default-src': "'self' *",
      'script-src': "'self' *",
      'connect-src': "'self' *"
    },
    EmberENV: {
      FEATURES: {
      },
      EXTEND_PROTOTYPES: {
        Date: false
      }
    },

    APP: {
    }
  };

  ENV['ember-simple-auth'] = {
    routeAfterAuthentication: 'dashboard',
    routeIfAlreadyAuthenticated: 'dashboard'
  }
...
return ENV;
}
//components/login-form.js
import Ember from 'ember';

const { service } = Ember.inject;

export default Ember.Component.extend({
  session: service('session'),

  actions: {
    authenticate: function() {
      let { email, password } = this.getProperties('email', 'password');
      return this.get('session').authenticate('authenticator:devise', email, password).catch((reason) => {
        this.set('errorMessage', reason.error);
      });
    }
  }
});

//templates/login-form.hbs
<form {{action "authenticate" on="submit"}}>
  <label for="email">Login</label>
  {{input value=email placeholder="Enter Login"}}

  <label for="password">Password</label>
  {{input value=password type="password" placeholder="Enter Password"}}

  <button type="submit">Login</button>
</form>

{{#if errorMessage}}
  {{errorMessage}}
{{/if}}

//application.rb
class Application < Rails::Application
    # Initialize configuration defaults for originally generated Rails version.
    config.middleware.insert_before 0, Rack::Cors do
      allow do
        origins '*'
        resource '*', :headers => :any, :methods => [:get, :post, :put, :delete, :options, :patch, :head]
      end
    end
    config.middleware.use ActionDispatch::Flash
  ....

//controllers/application.rb
class ApplicationController < ActionController::Base
  protect_from_forgery with: :exception, prepend: true

  before_action :authenticate_user_from_token!
  before_action :authenticate_user!

  private

  def authenticate_user_from_token!
    authenticate_with_http_token do |token, options|
      user_email = options[:email].presence
      user = user_email && User.find_by_email(user_email)

      if user && Devise.secure_compare(user.authentication_token, token)
        sign_in user, store: false
      end
    end
  end
end

//controllers/sessions.rb
class SessionsController < Devise::SessionsController
  respond_to :html, :json

  def create
    super do |user|
      if request.format.json?
        data = {
          token: user.authentication_token,
          email: user.email
        }
        render json: data, status: 201 and return
      end
    end
  end
end

Ответы [ 2 ]

0 голосов
/ 12 мая 2018

Эта ошибка связана с проверкой подделки межсайтовых запросов в Rails.Когда вы запускаете приложение, отображаемое на сервере Rails, оно подтверждает, что запрос поступает из домена, в который Rails передает приложение, а не от злонамеренной третьей стороны.Отключение protect_from_forgery, как вы это сделали, является правильным решением в вашем случае, потому что ваше намерение состоит в том, чтобы запросы приходили с другого сервера (т.е. порта).

0 голосов
/ 12 мая 2018

Интересно - кажется, что комментирование protect_from_forgery в моем контроллере приложения решает проблему. Логин работает, но я не уверен, почему это все еще исправляет. Результирующий контроллер приложения:

class ApplicationController < ActionController::Base

  before_action :authenticate_user_from_token!
  before_action :authenticate_user!

  # protect_from_forgery with: :exception, prepend: true

  private

  def authenticate_user_from_token!
    authenticate_with_http_token do |token, options|
      user_email = options[:email].presence
      user = user_email && User.find_by_email(user_email)

      if user && Devise.secure_compare(user.authentication_token, token)
        sign_in user, store: false
      end
    end
  end
end
...