Как я могу сохранить и установить пользователя в этой службе авторизации angularjs? Или это уже сделано?

Я использую на клиенте библиотеку облаков angularjs-devise. Когда я пытаюсь войти/зарегистрироваться, я получаю ответ 200 ok с открытым пользовательским объектом, видимым в консоли chrome js. Обновление страницы, похоже, потеряет эту информацию, хотя я предположил, что служба сохранит ее в какой-то момент, так как она также имеет методы выхода из системы и currentUser. https://github.com/cloudspace/angular_devise

Мои вопросы:

1) Действительно ли эта служба хранит пользователя, и если да, то как (например, с помощью файлов cookie или localstorage или в памяти)?

2) Если служба не хранит пользователя, как я могу хранить эту информацию в пользовательском файле cookie/localstorage и, что еще важнее, установить пользователя в службу, чтобы можно было использовать методы "isauthenticated" и "currentuser"?

Инструкции по чтению частичной библиотеки

Просто зарегистрируйте Devify как зависимость для вашего модуля. Затем служба Auth будет доступна для использования.

angular.module('myModule', ['Devise']).
    config(function(AuthProvider) {
        // Configure Auth service with AuthProvider
    }).
    controller('myCtrl', function(Auth) {
        // Use your configured Auth service.
    }); 

Auth.login(creds): Используйте Auth.login() для аутентификации с сервером. Имейте в виду, учетные данные отправляются в открытом виде; используйте SSL-соединение для их защиты. creds - это объект, который должен содержать любые учетные данные, необходимые для аутентификации с сервером. Auth.login() вернет обещание, которое разрешит зарегистрированному пользователю. См. AuthProvider.parse() для анализа пользователя на полезный объект.

angular.module('myModule', ['Devise']).
    controller('myCtrl', function(Auth) {
        var credentials = {
            email: '[email protected]',
            password: 'password1'
        };

        Auth.login(credentials).then(function(user) {
            console.log(user); // => {id: 1, ect: '...'}
        }, function(error) {
            // Authentication failed...
        });
    });

Мой частичный код:

main.js

var myApp = angular.module('mail_app', ['ngRoute', 'ngResource', 'Devise']);

myApp.config(function($routeProvider, $locationProvider, $httpProvider, AuthProvider) {
    console.log("in router")
    $locationProvider.html5Mode(true);
    $httpProvider.defaults.headers.common['X-CSRF-Token'] = 
    $('meta[name=csrf-token]').attr('content');
    $httpProvider.defaults.headers.common['ClientType'] = 'browser';

    // Customise login
    AuthProvider.loginMethod('POST');
    AuthProvider.loginPath('/api/v1/users/login.json');

    // Customise register
    AuthProvider.registerMethod('POST');
    AuthProvider.registerPath('/api/v1/users.json');

});

SessionsController.js

myApp.controller('SessionsController', ['$scope', 'Auth', '$http', function($scope, Auth, $http) {
 console.log("in session controller")
  console.log(Auth.isAuthenticated());

    $scope.loginUser = function() {
         console.log("in login")
        var credentials = {
            email: $scope.email,
            password: $scope.password
        };

        Auth.login(credentials).then(function(user) {
            $scope.authError = 'Success!';
            console.log(user); // => {id: 1, ect: '...'}
            Auth.currentUser = user;
        }, function(error) {
            $scope.authError = 'Authentication failed...';
        });     
    };

    $scope.registerUser = function(){
         console.log("in register function")
        var ncredentials = {
            email: $scope.newEmail,
            password: $scope.newPassword,
            password_confirmation: $scope.newPasswordConfirmation
        };

        Auth.register(ncredentials).then(function(registeredUser) {
            console.log(registeredUser); // => {id: 1, ect: '...'};
        }, function(error) {
            $scope.authError = 'Registration failed...';
        });
    };

    $scope.getCurrentUser = function(){
        Auth.currentUser().then(function(user) {
            // User was logged in, or Devise returned
            // previously authenticated session.
            console.log(user); // => {id: 1, ect: '...'}
            $scope.id = user.id;
        }, function(error) {
            // unauthenticated error
        });     
    };

    $scope.isUserAuthenticated = function(){
        Auth.isAuthenticated();     
    };


}]);

Ответ 1

Прежде всего вам нужно понять, как файлы cookie и сеансы работают в Rails.

Из эта статья:

Rails использует CookieStore для обработки сеансов. Это означает, что все информация, необходимая для идентификации сеанса пользователя, отправляется на клиент и ничего не хранится на сервере. Когда пользователь отправляет запрос, cookie сеанса обрабатывается и проверяется так, чтобы рельсы, надзиратель, изобретатель и т.д., могут выяснить, кто вы, и создать правильный пользователь из базы данных.

Это означает, что при каждом запросе Rails будет искать куки файл сеанса, декодировать его и получать что-то вроде

cookie = {
  "session_id": "Value",
  "_csrf_token": "token",
  "user_id": "1"
}

В этот момент Rails знает, что текущий пользователь имеет id=1 и может делать sql-запрос. (Как current_user = User.find(1)).

Когда пользователь вошел в систему, создается файл cookie, когда пользователь выходит из системы - файл cookie уничтожается. Если Rails не находит файл cookie или cookie не имеет информации о текущем пользователе, разработчик предположит, что пользователь не зашел в систему (current_user is nil)

Даже если вы входите в систему через ajax (чтобы быть конкретным, это через камень "angular_devise" в вашем случае), cookie создается. Он не хранится на сервере, а в браузере. (Вот почему, если вы вошли в один браузер, вы не авторизованы в другом браузере). Как вы указали, библиотека не хранит информацию, которая вошла в систему, и это связано с тем, что информация хранится в файле cookie и библиотека не может декодировать файл cookie без помощи сервера.

Вот почему вам нужно будет позвонить, чтобы получить текущего пользователя, если пользователь обновит страницу. (К сожалению)

Способ получения current_user очень прост. Это самое чистое решение, которое я нашел.

# application_controller.rb

def me
  render json: current_user
end

# routes.rb

get "me" => "application#me"

// main.js

// I am not familiar with angular_devise lib but you get the point:
// this method fetches from server when myApp is initialized (e.g. on page reload)
// and assigns the current_user so he/she can be used by the app
myApp.run(["AuthService", function(AuthService) {

  AuthService.getUserFromServer();

}]);

Если вам нужно загрузить данные, специфичные для пользователя, вам придется сначала загрузить пользователя, а затем данные. Излишне говорить, что вам придется использовать promises.

TL; DR: вам нужно будет спросить сервер

Я открыт для вопросов и комментариев.

Ответ 2

Я думаю, ваша проблема - это обновление. angular -devise lib, вероятно, предполагает, что вы находитесь в SPA (Singe Page Application), поэтому он не должен обновляться. В этом предположении angular -devise может хранить всю информацию в памяти. Когда вы обновляете свою страницу, вы в основном загружаете приложение с нуля. И запрос на сервер, вероятно, выдается вашим кодом при запуске приложения. Вероятно, вы назовете Auth.currentUser() где-то при запуске приложения

Ответ 3

Была такая же проблема. Просто используйте этот камень https://github.com/jsanders/angular_rails_csrf Вы также можете избавиться от "protect_from_forgery" в вашем контроллере приложений, но это очень рискованно.