如何在 Angular JS 应用程序中处理身份验证
Posted
技术标签:
【中文标题】如何在 Angular JS 应用程序中处理身份验证【英文标题】:How to handle authentication in Angular JS application 【发布时间】:2013-08-19 17:54:46 【问题描述】:我正在我的 Angular js 应用程序中实现一个身份验证系统。
我的计划如下:
-
获取用户信息(登录表单中的姓名和密码)
检查用户是否存在
如果存在服务器响应会话 cookie,前端将重定向到某个页面。
然后用户将执行一些将生成 API 请求的任务
API 请求应包含在步骤 3 中发送的 cookie 信息
服务器检查 cookie 是否生成,如果找到 cookie,则返回 API 请求结果。在我的服务中,我正在做类似的事情
提交登录表单后,我将调用 checkAuth 并从我的服务器取回我的会话 cookie,我如何在进行下一次 REST 调用时添加 cookie 信息,以及当用户在登录后浏览整个应用程序时我确实想要每次检查isAuthenticaed真或假,在Angularjs中,当它导航到另一个页面时,它是否在第一次调用设置为真后重置?我的方法 1-6 好还是你有什么具体建议? 顺便说一句,我检查了以前的条目,但这些不是我想知道的。
【问题讨论】:
检查这个问题about auth 检查用户是否通过身份验证...您的服务器端需要返回 401 请求并重定向到登录页面。要检查这一点,你不能在 $http 上放置一个拦截器来监听这个 HTTP 401 响应。 【参考方案1】:我不确定你的后端,但我会这样做
创建一个单独的登录页面(专用 url 不是角度子视图或 模态对话框)。 如果用户未通过身份验证重定向到此登录 页。这是通过服务器重定向完成的。此页面可能会或可能不会使用 角度框架,因为它只涉及发送用户\密码到 服务器。 从登录页面发出 POST(不是 AJAX 请求),并在服务器上进行验证。 在服务器上设置身份验证 cookie。 (不同框架的做法不同。ASP.Net 设置表单身份验证 cookie。) 用户通过身份验证后,将用户重定向到实际的 Angular 应用并加载其所有组件。这节省了在 Angular 中管理客户端身份验证所需的任何代码。如果用户登陆此页面,则他已通过身份验证并拥有 cookie。
此外,默认浏览器行为是在每次请求时发送与域关联的所有 cookie,因此您不必担心 Angular 是否发送了一些 cookie。
【讨论】:
这是一个非常好的建议,不仅简化了流程,而且开辟了获得更好性能的新机会。如果有人对上述回答方法感兴趣,请查看ng-conf video 关于这个主题。 @Nobita 精彩视频 在 Angular 中,我可能会在不刷新页面的情况下加载许多视图。使用 Angular 如何在不重新加载页面的情况下检查会话? 当您在 Angular 应用程序中会话到期时会出现问题。而且您不想离开登录网址而失去应用程序的状态。【参考方案2】:我使用 http-auth-interceptor。 http://ngmodules.org/modules/http-auth-interceptor
在我的后端 (asp.net mvc) 中,我构建了一个简单的身份验证服务,如果用户未通过身份验证,则返回一个 http 错误 401
。
然后我在 SPA 站点中使用登录视图处理错误。
【讨论】:
我正在使用拦截器添加身份验证后的cookie来调用REST请求,我不清楚的一件事。注销应该如何工作。我将会话数据(cookie)保存到文件中,当用户发送任何新请求时,我会检查保存的 cookie。当用户发送注销请求时,我是否需要删除 cookie? 我在服务器端使用 ASP.NET MVC,并修改了表单身份验证。在注销时,我的客户端向服务器发送注销请求,服务器会删除身份验证 cookie。 这个模块是最好的选择,原始博客文章解释了如何在单页应用程序中使用 /login 或 /logout 路由不再有意义(尽管它在后端)。刚开始使用 http-auth-interceptor 并看到它做什么/不做什么 - 所以从整体方法的角度来看,这个答案似乎是最好的,但没有涵盖登录流程的所有方面(从 spa/前端到后端并返回,失败和成功)。 frederiknakstad.com/… 提供了很多缺失的细节。【参考方案3】:前面的答案提出的想法会奏效,但我认为它们有点矫枉过正。你不需要这么复杂的东西。
如何在进行下一次 REST 调用时添加 cookie 信息
在$httpProvider
中默认打开withCredentials
,如下所示:
app.config(['$httpProvider', function($httpProvider)
$httpProvider.defaults.withCredentials = true;
]);
然后从与 CORS 相关的标头中删除通配符(如果有的话),并在服务器端设置允许凭据。就我而言,使用 Python + Flask + Flask-Restful,非常简单,看起来像这样:
import Flask
from flask_restful import Api
app = Flask(__name__)
api = Api(app)
api.decorators = [cors.crossdomain(origin='http://localhost:8100', credentials=True)]
现在 cookie 将由浏览器自动且透明地设置和返回。有关详细信息,请参阅这些主题:
$http response Set-Cookie not accessible Angularjs $http does not seem to understand "Set-Cookie" in the response当用户在登录后浏览整个应用程序时,我确实想检查每次 isAuthenticaed 是真是假
如上所述,如果身份验证会话过期或被删除,则让服务器返回 401,并在 Angular 中使用 $httpInterceptor
像这样捕获:
app.config(function($httpProvider)
var interceptor =
function($q, $rootScope)
return
'response': function(response)
return response;
,
'responseError': function(rejection)
if (rejection.status==401)
// Modify this part to suit your needs.
// In my case I broadcast a message which is
// picked up elsewhere to show the login screen.
if (!rejection.config.url.endsWith('/login'))
$rootScope.$broadcast('auth:loginRequired');
return $q.reject(rejection)
;
$httpProvider.interceptors.push(interceptor);
);
【讨论】:
为什么要去掉通配符?请解释一下。【参考方案4】:(披露:我是 UserApp 的开发者之一)
您可以为此使用第三方服务UserApp,以及AngularJS module。
查看getting started guide,或拨打course on Codecademy。以下是其工作原理的一些示例:
带有错误处理的登录表单:
<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>
使用user
服务访问用户信息:user.current.email
或者在模板中:<span> user.email </span>
带有错误处理的注册表单:
<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>
ua-is-email
表示用户名与邮箱相同。
如何指定哪些路由应该是公开的,哪些路由是登录表单:
$routeProvider.when('/login', templateUrl: 'partials/login.html', public: true, login: true);
$routeProvider.when('/signup', templateUrl: 'partials/signup.html', public: true);
.otherwise()
路由应设置为您希望用户在登录后重定向到的位置。示例:
$routeProvider.otherwise(redirectTo: '/home');
退出链接:
<a href="#" ua-logout>Log Out</a>
隐藏仅在登录时才可见的元素:
<div ng-show="user.authorized">Welcome user.first_name !</div>
要对您的后端服务进行身份验证,只需使用user.token()
获取会话令牌并将其与 AJAX 请求一起发送。在后端,使用UserApp API 来检查令牌是否有效。
如果您需要任何帮助,请告诉我 :)
【讨论】:
以上是关于如何在 Angular JS 应用程序中处理身份验证的主要内容,如果未能解决你的问题,请参考以下文章
如何在同一个 Angular JS 应用程序中使用具有不同身份验证标头的不同 API
如何使基本身份验证作为 Angular JS/Spring 启动应用程序中 keycloak 的替代品
在 Angular 6 + 节点 js 中使用令牌的身份验证问题