Как я могу сохранить и установить пользователя в этой службе авторизации 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" в вашем контроллере приложений, но это очень рискованно.