简体   繁体   English

简单的Auth Devise提供Ember Rails中未经验证的错误

[英]Simple Auth Devise giving unauthenticated error in Ember Rails

I am setting up an ember app that is backed by ruby on rails. 我正在设置一个由ruby支持的ember应用程序。 I am running into issues with my sign in action using simple-auth and simple-auth-devise. 我在使用simple-auth和simple-auth-devise进行登录操作时遇到问题。 I successfully retrieve the sessions authentication token and username when I submit a correct username and password, but I am still given a 401 access denied error and I can't figure out why. 提交正确的用户名和密码后,我成功检索了会话身份验证令牌和用户名,但仍然收到401访问被拒绝的错误,我不知道为什么。 I suspect that it may have to do with the naming of email versus user_email and token vs user_token business. 我怀疑这可能与电子邮件与user_email以及令牌与user_token业务的命名有关。 I am taking this code mostly from dayjot , so you'd think it would be trivial to track down this bug but I am having tons of issues finding the exact issue. 我主要是从dayjot那里获取这段代码,因此您认为跟踪该错误会很简单,但是发现确切的问题却有很多问题。 Thanks for any help you can give me! 感谢你给与我的帮助!

The exact error I get in the rails server is: 我在Rails服务器中得到的确切错误是:

Started GET "/users/me" for 127.0.0.1 at 2015-02-17 10:25:31 -0600
Processing by UsersController#me as JSON
  Parameters: {"user"=>{}}
Filter chain halted as :authenticate_user! rendered or redirected
Completed 401 Unauthorized in 5ms (Views: 4.1ms | ActiveRecord: 0.0ms)
In rails, this is my application controller:

This is my application controller: 这是我的应用程序控制器:

class ApplicationController < ActionController::Base
  # Prevent CSRF attacks by raising an exception.
  # For APIs, you may want to use :null_session instead.
  # protect_from_forgery with: :null_session

  before_action :authenticate_user_from_token!, :handle_html
  around_action :user_time_zone, if: :current_user

  def index
    render file: 'public/index.html'
  end

  protected

  def authenticate_user!
    render(json: {}, status: 401) unless current_user
  end

  private

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

      if user && Devise.secure_compare(user.authentication_token, token)
        request.env['devise.skip_trackable'] = true
        sign_in user, store: false
      end
    end
  end

  def user_time_zone(&block)
    Time.use_zone(current_user.time_zone, &block)
  end

  # If this is a get request for HTML, just render the ember app.
  def handle_html
    render 'public/index.html' if request.method == 'GET' && request.headers['Accept'].match(/html/)
  end
end

My sessions controller looks like this: 我的会话控制器如下所示:

class SessionsController < Devise::SessionsController
  def create
    self.resource = warden.authenticate!(auth_options)
    sign_in(resource_name, resource)
    data = {
      user_token: self.resource.authentication_token,
      user_email: self.resource.email
    }
    render json: data, status: 201
  end

  def destroy
    sign_out :user
    render json: {}, status: :accepted
  end
end

My serializers are these: 我的序列化器是:

class UserSerializer < ActiveModel::Serializer
  attributes :id, :password, :user_email, :email, :user_token, :passwordConfirmation
end

class UserSerializer < ActiveModel::Serializer
  attributes :id, :email, :email_times, :last_export_time, :plan, 
             :plan_started, :plan_canceled, :plan_status, :trial_end, 
             :time_zone, :status, :created_at, :include_email_memory
end

My route is: 我的路线是:

Rails.application.routes.draw do Rails.application.routes.draw做

  # PLANS
  post 'update_plan' => 'plans#update_plan', as: :update_plan
  post 'update_card' => 'plans#update_card', as: :update_card
  post 'cancel_plan' => 'plans#cancel_plan', as: :cancel_plan

  # PASSWORDS
  post 'start_password_reset' => 'users#start_password_reset'
  put  'finish_password_reset' => 'users#finish_password_reset'
  get  'password-reset' => 'application#index', as: :edit_user_password

  # USERS
  devise_for :users, controllers: { sessions: 'sessions' }, :skip => [:passwords]
  resources :users, only: [:create, :update] do 
    get 'me' => 'users#me', on: :collection
  end

  # background processing admin
  match "/delayed_job" => DelayedJobWeb, :anchor => false, via: [:get, :post]    

  # catch-all for ember app
  get '*path' => 'application#index', :constraints => { :format => 'html' }


end

In the ember-cli app itself, my login controller is: 在ember-cli应用程序本身中,我的登录控制器为:

import Ember from "ember";

export default Ember.Controller.extend({
  authenticator: 'simple-auth-authenticator:devise',

  identification: null,
  password: null,
  error: null,
  working: false,

  actions: {
    authenticate: function() {
      var _this = this,
          data = this.getProperties('identification', 'password');

      this.setProperties({
        working: true,
        password: null,
        error: null
      });

      this.get('session').authenticate('simple-auth-authenticator:devise', data).then(function() {
        // authentication was successful
      }, function(data) {
        _this.set('working', false);
        _this.set('error', data.error);
      });
    }
  }
});

My application route is: 我的申请途径是:

// ember-simple-auth
import Ember from "ember";
import ApplicationRouteMixin from 'simple-auth/mixins/application-route-mixin';
import Notify from 'ember-notify';
import ENV from 'front-end/config/environment';

export default Ember.Route.extend(ApplicationRouteMixin, {
  beforeModel: function(transition) {
    this._super(transition);    
    return this.setCurrentUser();
  },
  actions: {
    sessionAuthenticationFailed: function(data) {
      this.controllerFor('login').set('working', false);
      this.controllerFor('login').set('loginErrorMessage', data.message);
    },
    sessionInvalidationSucceeded: function() {
      this.transitionTo('index');
    },
    sessionAuthenticationSucceeded: function() {
      var _this = this;
      this.controllerFor('login').set('working', false);

      this.setCurrentUser().then(function() {
        if (_this.get('session.currentUser.mustSubscribe')) {
          _this.transitionTo('plans');
        } else {
          _this.transitionTo('courses');
        }
      });      
    },
    authorizationFailed: function() {
      Notify.error("Could not be authenticated.. signing out.", {closeAfter: 5000});
      this.get('session').invalidate();
    }
  },

  setCurrentUser: function() {

    var _this = this,
        adapter = this.get('store').adapterFor('user');

    if (this.get('session.isAuthenticated')) {
      return new Ember.RSVP.Promise(function(resolve) {
        adapter.ajax(ENV.APP.API_HOST + "/users/me", "GET", {}).then(
          function(response){
            _this.store.pushPayload(response);
            var user = _this.store.find('user', response.user.id);
            resolve(user);
          },
          function(response){
            resolve(response);
          }
        );
      }).then(function(user) {
        _this.set('session.currentUser', user);  
      }, function() {
        Notify.error("Could not be authenticated.. signing out.", {closeAfter: 5000});
        _this.get('session').invalidate();
      });
    } else {
      return new Ember.RSVP.Promise(function(resolve){ resolve(); });
    }
  }
});

Finally my login route is: 最后,我的登录路线是:

import Ember from "ember";

export default Ember.Route.extend({
  activate: function() {
    if (this.get('session').isAuthenticated) {
      this.transitionTo('courses');
    }
  }
});

And Template is: 模板是:

<form {{action 'register' on='submit'}} class='d-auth-form fade-in'>

  {{#each errors}}
    <div class="d-error">
      {{this}}
    </div>
  {{/each}}

  {{input placeholder='Email' type='email' value=email autocomplete='off' autocapitalize="none"}}
  {{input placeholder='Password' type='password' value=password autocomplete='off'}}
  <button type="submit" class='d-btn d-btn--success' {{bind-attr disabled=working}}>
    {{#if working}}
      Registering..
    {{else}}
      Sign up for DayJot for free
    {{/if}}
  </button>

  <ul class='d-links'>
    <li>{{#link-to 'login'}}Login to existing account{{/link-to}}</li>
  </ul>
</form>

The important parts of environment.js are: environment.js的重要部分是:

    'simple-auth': {
      crossOriginWhitelist: ['http://localhost:3000','http://localhost:4202','https://api.dayjot.com'],
      authorizer: 'simple-auth-authorizer:devise',
      authenticationRoute: 'index'
    } 

and

  ENV['simple-auth-devise'] = {
    serverTokenEndpoint: ENV.APP.API_HOST+'/users/sign_in',
    identificationAttributeName: 'email'

  }

Checkout the README - Ember Simple Auth Devise expects the token to be returned as token , you're using user_token however. 检出自述文件 -Ember Simple Auth Devise希望将令牌作为token返回,但是您正在使用user_token Thus, the session will never actually be authenticated in Ember and the token won't be included in requests which leads to the 401 response. 因此,该会话实际上不会在Ember中进行身份验证,并且令牌不会包含在导致401响应的请求中。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM