【问题标题】:How to handle authentication in Angular JS application如何在 Angular JS 应用程序中处理身份验证
【发布时间】:2013-08-19 17:54:46
【问题描述】:

我正在我的 Angular js 应用程序中实现一个身份验证系统。

我的计划如下:

  1. 获取用户信息(登录表单中的姓名和密码)
  2. 检查用户是否存在
  3. 如果存在服务器响应会话 cookie,前端将重定向到某个页面。
  4. 然后用户将执行一些将生成 API 请求的任务
  5. API 请求应包含在步骤 3 中发送的 cookie 信息
  6. 服务器检查 cookie 是否生成,如果找到 cookie,则返回 API 请求结果。在我的服务中,我正在做类似的事情
MyApp.service('myAuth', function($http, $q) { this.authHeader = null; this.checkAuth = 函数(){ //做api调用,如果成功设置this.authHeader = response } this.isAuthenticaed = function(){ 这个.authHeader ?返回 this.authHeder :返回 false; }

提交登录表单后,我将调用 checkAuth 并从我的服务器取回我的会话 cookie,我如何在进行下一次 REST 调用时添加 cookie 信息,以及当用户在登录后浏览整个应用程序时我确实想要每次检查isAuthenticaed真或假,在Angularjs中,当它导航到另一个页面时,它是否在第一次调用设置为真后重置?我的方法 1-6 好还是你有什么具体建议? 顺便说一句,我检查了以前的条目,但这些不是我想知道的。

【问题讨论】:

  • 检查这个问题about auth
  • 检查用户是否通过身份验证...您的服务器端需要返回 401 请求并重定向到登录页面。要检查这一点,你不能在 $http 上放置一个拦截器来监听这个 HTTP 401 响应。

标签: session authentication angularjs cookies


【解决方案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 将由浏览器自动且透明地设置和返回。有关详细信息,请参阅这些主题:

当用户在登录后浏览整个应用程序时,我确实想检查每次 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

    或者在模板中:&lt;span&gt;{{ user.email }}&lt;/span&gt;

  • 带有错误处理的注册表单:

    <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'});

  • 退出链接:

    &lt;a href="#" ua-logout&gt;Log Out&lt;/a&gt;

  • 隐藏仅在登录时才可见的元素:

    &lt;div ng-show="user.authorized"&gt;Welcome {{ user.first_name }}!&lt;/div&gt;

要对您的后端服务进行身份验证,只需使用user.token() 获取会话令牌并将其与 AJAX 请求一起发送。在后端,使用UserApp API 来检查令牌是否有效。

如果您需要任何帮助,请告诉我 :)

【讨论】:

    猜你喜欢
    • 2013-03-13
    • 1970-01-01
    • 2014-07-15
    • 2016-11-15
    • 2020-06-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多