我是AngularJS的新手,并完成了他们的教程并感受到了它。
我有一个准备好项目的后端,每个REST
端点都需要进行身份验证。
我想做什么
a。)我想为我的项目http://myproject.com
设置一个页面
b。)一旦用户点击浏览器中的URL,根据用户是否登录,他将在同一网址http://myproject.com
下显示主页/视图或登录页面/视图。
c。)如果用户未登录,则填写表单并且服务器在会话中设置USER_TOKEN
,因此所有对端点的进一步请求将根据USER_TOKEN
我的困惑
a。)如何使用AngularJS处理客户端身份验证?我看到here和here,但不明白如何使用它们
b。)如何根据用户是否登录同一网址http://myproject.com
我第一次使用angular.js,真的很困惑如何开始。非常感谢任何建议和/或资源。
答案 0 :(得分:48)
我已经创建了一个github repo,基本上总结了这篇文章:https://medium.com/opinionated-angularjs/techniques-for-authentication-in-angularjs-applications-7bbf0346acec
我会尝试尽可能好地解释,希望我帮助你们中的一些人:
(1)app.js:在应用定义上创建身份验证常量
var loginApp = angular.module('loginApp', ['ui.router', 'ui.bootstrap'])
/*Constants regarding user login defined here*/
.constant('USER_ROLES', {
all : '*',
admin : 'admin',
editor : 'editor',
guest : 'guest'
}).constant('AUTH_EVENTS', {
loginSuccess : 'auth-login-success',
loginFailed : 'auth-login-failed',
logoutSuccess : 'auth-logout-success',
sessionTimeout : 'auth-session-timeout',
notAuthenticated : 'auth-not-authenticated',
notAuthorized : 'auth-not-authorized'
})
(2)身份验证服务:以下所有功能都在auth.js服务中实现。 $ http服务用于与服务器通信以进行身份验证过程。还包含授权功能,即允许用户执行某项操作。
angular.module('loginApp')
.factory('Auth', [ '$http', '$rootScope', '$window', 'Session', 'AUTH_EVENTS',
function($http, $rootScope, $window, Session, AUTH_EVENTS) {
authService.login() = [...]
authService.isAuthenticated() = [...]
authService.isAuthorized() = [...]
authService.logout() = [...]
return authService;
} ]);
(3)会话:用于保存用户数据的单例。这里的实施取决于你。
angular.module('loginApp').service('Session', function($rootScope, USER_ROLES) {
this.create = function(user) {
this.user = user;
this.userRole = user.userRole;
};
this.destroy = function() {
this.user = null;
this.userRole = null;
};
return this;
});
(4)家长控制器:将此视为" main"应用程序的功能,所有控制器都继承自此控制器,它是此应用程序身份验证的主干。
<body ng-controller="ParentController">
[...]
</body>
(5)访问控制:要拒绝某些路线的访问,必须执行两个步骤:
a)在ui路由器的$ stateProvider服务上添加允许访问每条路由的角色数据,如下所示(同样适用于ngRoute)。
.config(function ($stateProvider, USER_ROLES) {
$stateProvider.state('dashboard', {
url: '/dashboard',
templateUrl: 'dashboard/index.html',
data: {
authorizedRoles: [USER_ROLES.admin, USER_ROLES.editor]
}
});
})
b)在$ rootScope。$ on(&#39; $ stateChangeStart&#39;)上添加该功能,以防止用户未经授权进行状态更改。
$rootScope.$on('$stateChangeStart', function (event, next) {
var authorizedRoles = next.data.authorizedRoles;
if (!Auth.isAuthorized(authorizedRoles)) {
event.preventDefault();
if (Auth.isAuthenticated()) {
// user is not allowed
$rootScope.$broadcast(AUTH_EVENTS.notAuthorized);
} else {
// user is not logged in
$rootScope.$broadcast(AUTH_EVENTS.notAuthenticated);
}
}
});
(6)Auth拦截器这已实现,但无法检查此代码的范围。在每个$ http请求之后,此拦截器检查状态代码,如果返回以下之一,则它会广播一个事件以强制用户再次登录。
angular.module('loginApp')
.factory('AuthInterceptor', [ '$rootScope', '$q', 'Session', 'AUTH_EVENTS',
function($rootScope, $q, Session, AUTH_EVENTS) {
return {
responseError : function(response) {
$rootScope.$broadcast({
401 : AUTH_EVENTS.notAuthenticated,
403 : AUTH_EVENTS.notAuthorized,
419 : AUTH_EVENTS.sessionTimeout,
440 : AUTH_EVENTS.sessionTimeout
}[response.status], response);
return $q.reject(response);
}
};
} ]);
P.S。通过添加directives.js中包含的指令,可以轻松避免第1篇文章中所述的表单数据自动填充的错误。
P.S.2 用户可以轻松调整此代码,以允许查看不同的路径,或显示不打算显示的内容。逻辑必须在服务器端实现,这只是一种在ng-app上正确显示内容的方法。
答案 1 :(得分:25)
我喜欢这种方法并在服务器端实现它而不在前端执行任何与身份验证相关的事情
我最近的应用程序上的'技巧'是......客户不关心 验证。应用程序中的每一件事都需要先登录,所以 除非现有用户,否则服务器始终提供登录页面 在会话中检测到。如果找到session.user,那么服务器就是 发送index.html。巴姆:-o
寻找“Andrew Joslin”的评论。
答案 2 :(得分:14)
我在这里回答了类似的问题:AngularJS Authentication + RESTful API
我为AngularJS module写了一个UserApp,它支持受保护/公共路由,在登录/注销时重新路由,用于状态检查的心跳,将会话令牌存储在cookie中,事件等等。 / p>
你可以:
https://github.com/userapp-io/userapp-angular
如果您使用UserApp,则不必为用户填写任何服务器端代码(不仅仅是验证令牌)。拿course on Codecademy进行试用。
以下是一些如何运作的例子:
如何指定哪些路线应该是公开的,以及哪条路线是登录表单:
$routeProvider.when('/login', {templateUrl: 'partials/login.html', public: true, login: true});
$routeProvider.when('/signup', {templateUrl: 'partials/signup.html', public: true});
$routeProvider.when('/home', {templateUrl: 'partials/home.html'});
.otherwise()
路由应设置为您希望用户在登录后重定向到的位置。例如:
$routeProvider.otherwise({redirectTo: '/home'});
包含错误处理的登录表单
<form ua-login ua-error="error-msg">
<input name="login" placeholder="Username"><br>
<input name="password" placeholder="Password" type="password"><br>
<button type="submit">Log in</button>
<p id="error-msg"></p>
</form>
包含错误处理的注册表单
<form ua-signup ua-error="error-msg">
<input name="first_name" placeholder="Your name"><br>
<input name="login" ua-is-email placeholder="Email"><br>
<input name="password" placeholder="Password" type="password"><br>
<button type="submit">Create account</button>
<p id="error-msg"></p>
</form>
退出链接:
<a href="#" ua-logout>Log Out</a>
(结束会话并重定向到登录路线)
访问用户属性:
使用user
服务访问用户属性,例如:user.current.email
或在模板中:<span>{{ user.email }}</span>
隐藏仅在登录时可见的元素:
<div ng-show="user.authorized">Welcome {{ user.first_name }}!</div>
根据权限显示元素:
<div ua-has-permission="admin">You are an admin</div>
要对后端服务进行身份验证,只需使用user.token()
获取会话令牌并使用AJAX请求发送它。在后端,使用UserApp API(如果您使用UserApp)检查令牌是否有效。
如果您需要任何帮助,请告诉我们!
答案 3 :(得分:2)
在angularjs中,您可以创建UI部件,服务,指令以及代表UI的angularjs的所有部分。这是一项很好的技术。
任何进入这项技术的人都希望对“用户”进行身份验证,那么我建议使用c#web api的强大功能。为此,您可以使用OAuth规范,该规范将帮助您构建强大的安全机制来对用户进行身份验证。一旦使用OAuth构建WebApi,您需要为令牌调用该api:
var _login = function (loginData) {
var data = "grant_type=password&username=" + loginData.userName + "&password=" + loginData.password;
var deferred = $q.defer();
$http.post(serviceBase + 'token', data, { headers: { 'Content-Type': 'application/x-www-form-urlencoded' } }).success(function (response) {
localStorageService.set('authorizationData', { token: response.access_token, userName: loginData.userName });
_authentication.isAuth = true;
_authentication.userName = loginData.userName;
deferred.resolve(response);
}).error(function (err, status) {
_logOut();
deferred.reject(err);
});
return deferred.promise;
};
一旦获得令牌,您就可以在Token的帮助下从angularjs请求资源,并使用OAuth规范访问在Web Api中保持安全的资源。
请查看以下文章以获取更多帮助: -
答案 4 :(得分:1)
我认为每个JSON响应都应包含一个属性(例如{authenticated:false}),客户端必须每次都测试它:如果为false,则Angular控制器/服务将“重定向”到登录页面。
如果用户捕获de JSON并将bool更改为True会发生什么?
我认为你不应该依赖客户端来做这些事情。如果用户未经过身份验证,则服务器应该只重定向到登录/错误页面。
答案 5 :(得分:0)
var _login = function (loginData) {
var data = "grant_type=password&username=" + loginData.userName + "&password=" + loginData.password;
var deferred = $q.defer();
$http.post(serviceBase + 'token', data, { headers: { 'Content-Type': 'application/x-www-form-urlencoded' } }).success(function (response) {
localStorageService.set('authorizationData', { token: response.access_token, userName: loginData.userName });
_authentication.isAuth = true;
_authentication.userName = loginData.userName;
deferred.resolve(response);
}).error(function (err, status) {
_logOut();
deferred.reject(err);
});
return deferred.promise;
};
&#13;