Express、node.js、MongoDBをMongoose経由で使用する単一ページのAngularJSアプリがあります。ユーザー管理/認証にPassportを使用します。
ユーザーがログインしているかどうかに基づいてnavbarアイテムを変更したいのですが。私はそれを実装する方法を理解するのに苦労しています。
ユーザーがhttp
リクエストを介してログインしているかどうかを確認します。
server.js
_app.get('/checklogin',function(req,res){
if (req.user)
res.send(true);
else
res.send(false);
_
フロントエンドには、Angularの_$http
_サービスを使用してこれを呼び出すNavController
があります。
NavController.js
_angular.module('NavCtrl',[]).controller('NavController',function($scope,$http) {
$scope.loggedIn = false;
$scope.isLoggedIn = function() {
$http.get('/checklogin')
.success(function(data) {
console.log(data);
if (data === true)
$scope.loggedIn = true;
else
$scope.loggedIn = false;
})
.error(function(data) {
console.log('error: ' + data);
});
};
};
_
私のナビゲーションでは、_ng-show
_と_ng-hide
_を使用して、どの選択を表示するかを決定しています。また、ユーザーがnav項目をクリックしたときにisLoggedIn()
関数をトリガーし、クリックごとにユーザーがログインしているかどうかを確認します。
index.html
_<nav class="navbar navbar-inverse" role="navigation">
<div class="navbar-header">
<a class="navbar-brand" href="/">Home</a>
</div>
<ul class="nav navbar-nav">
<li ng-hide="loggedIn" ng-click="isLoggedIn()">
<a href="/login">Login</a>
</li>
<li ng-hide="loggedIn" ng-click="isLoggedIn()">
<a href="/signup">Sign up</a>
</li>
<li ng-show="loggedIn" ng-click="logOut(); isLoggedIn()">
<a href="#">Log out</a>
</li>
</ul>
</nav>
_
問題
私のアプリには、ユーザーがNavControllerのスコープ外にログイン/ログアウトできる他の場所があります。たとえば、LoginControllerに対応するログインページにログインボタンがあります。これをアプリ全体に実装するより良い方法があると思います。
_req.user
_がバックエンドでtrue
であるかどうかを「監視」し、それに応じてナビアイテムを応答させるにはどうすればよいですか?
$rootScope
を使用して、アプリ全体で情報を共有できます。
.controller('NavController',function($scope,$http, $rootScope) {
$scope.isLoggedIn = function() {
$http.get('/checklogin')
.success(function(data) {
console.log(data);
$rootScope.loggedIn = data;
})
.error(function(data) {
console.log('error: ' + data);
});
};
};
これで、上記のコードで行われたのと同じ方法で$rootScope.loggedIn
にアクセスして、アプリの他の場所からloggedIn
の値を変更できます。
つまり、関連するコードをサービスとディレクティブに抽象化する必要があります。これにより、$rootScope.loggedIn
の状態を処理、ログイン、ログアウト、および状態管理するための中心的な場所を1つ持つことができます。あなたが関連するコードの残りを投稿するなら、私はより具体的な答えであなたを助けることができます
ユーザーが正常にログインすると、そのイベントをブロードキャストできます。また、ユーザーがログインしている場合にサーバーをポーリングし続ける必要はありません。有効なセッションがあるかどうかを示す変数をメモリに保持できます。サーバー側で設定されるトークンベースの認証を使用できます。
services.factory('UserService', ['$resource',
function($resource){
// represents guest user - not logged
var user = {
firstName : 'guest',
lastName : 'user',
preferredCurrency : "USD",
shoppingCart : {
totalItems : 0,
total : 0
},
};
var resource = function() {
return $resource('/myapp/rest/user/:id',
{ id: "@id"}
)};
return {
getResource: function() {
return resource;
},
getCurrentUser: function() {
return user;
},
setCurrentUser: function(userObj) {
user = userObj;
},
loadUser: function(id) {
user = resource.get(id);
}
}
}]);
services.factory('AuthService', ['$resource', '$rootScope', '$http', '$location', 'AuthenticationService',
function ($resource, $rootScope, $http, $location, AuthenticationService) {
var authFactory = {
authData: undefined
};
authFactory.getAuthData = function () {
return this.authData;
};
authFactory.setAuthData = function (authData) {
this.authData = {
authId: authData.authId,
authToken: authData.authToken,
authPermission: authData.authPermission
};
// broadcast the event to all interested listeners
$rootScope.$broadcast('authChanged');
};
authFactory.isAuthenticated = function () {
return !angular.isUndefined(this.getAuthData());
};
authFactory.login = function (user, functionObj) {
return AuthenticationService.login(user, functionObj);
};
return authFactory;
}]);
services.factory('AuthenticationService', ['$resource',
function($resource){
return $resource('/myapp/rest/auth/',
{},
{
'login': { method: "POST" }
}
);
}]);
services.factory('authHttpRequestInterceptor', ['$injector',
function ($injector) {
var authHttpRequestInterceptor = {
request: function ($request) {
var authFactory = $injector.get('AuthService');
if (authFactory.isAuthenticated()) {
$request.headers['auth-id'] = authFactory.getAuthData().authId;
$request.headers['auth-token'] = authFactory.getAuthData().authToken;
}
return $request;
}
};
return authHttpRequestInterceptor;
}]);
コントローラ:
controllers.controller('LoginCtrl', ['$scope', '$rootScope', 'AuthService', 'UserService',
function LoginCtrl($scope, $rootScope, AuthService, UserService) {
$scope.login = function () {
AuthService.login($scope.userInfo, function (data) {
AuthService.setAuthData(data);
// set user info on user service to reflect on all UI components
UserService.setCurrentUser(data.user);
$location.path('/home/');
});
};
$scope.isLoggedIn = function () {
return AuthService.isAuthenticated();
}
$scope.user = UserService.getCurrentUser();
}])
EJSなどのテンプレートライブラリを使用して、ユーザーのセッションデータをindex.html内に追加できます。
Ejsミドルウェアを追加するだけです。
var ejs = require('ejs');
// Register ejs as .html.
app.engine('.html', ejs.__express);
そして、index.htmlを返すときに、セッションデータを応答にレンダリングします。
res.render( "/index.html", {
session : {
user_data : JSON.stringify(req.user)
}
});
これで、index.htmlのこのデータにアクセスできるようになりました。これをAngular app。にロードする必要があります。 preload-resource の例を使用しましたが、独自の方法を使用できます。
現在のセッション外でログインを保持したい場合は、$ localStorageを使用することもできます。このライブラリは、このような状況に非常に役立つことがわかりました。 ( https://github.com/grevory/angular-local-storage )