搜索
首页web前端js教程在角度应用中实施身份验证

Implementing Authentication in Angular Applications

关键要点

  • 在单页应用程序 (SPA) 中实现身份验证涉及服务器公开身份验证端点,该端点验证用户凭据并返回访问令牌。此令牌随后用于对服务器进行的所有安全 API 请求。
  • 在 Angular 中,访问令牌可以存储在服务或值中,因为它们是客户端上的单例对象。但是,为了防止用户刷新页面时令牌丢失,建议使用浏览器持久性机制(例如 sessionStorage)来存储令牌。
  • 为了防止潜在的数据盗窃,应在服务器端和客户端维护和验证用户的状态。当用户注销时,应调用相应的 API(请求标头中包含访问令牌),并且还应清除 sessionStorage 中的数据。

身份验证和授权是几乎所有严肃应用程序的重要组成部分。单页应用程序 (SPA) 也不例外。应用程序可能不会将其所有数据和功能都公开给任何用户。用户可能必须进行身份验证才能查看应用程序的某些部分,或在应用程序上执行某些操作。为了识别应用程序中的用户,我们需要让用户登录。

在传统的服务器驱动应用程序和单页应用程序中,用户管理的实现方式有所不同。SPA 与其服务器组件交互的唯一方式是通过 AJAX。即使对于登录和注销也是如此。

负责识别用户的服务器必须公开身份验证端点。SPA 将把用户输入的凭据发送到此端点进行验证。在典型的基于令牌的身份验证系统中,服务在验证凭据后可能会返回访问令牌或包含已登录用户的名称和角色的对象。客户端必须在对服务器进行的所有安全 API 请求中使用此访问令牌。

由于访问令牌将被多次使用,因此最好将其存储在客户端。在 Angular 中,我们可以将值存储在服务或值中,因为它们是客户端上的单例对象。但是,如果用户刷新页面,服务或值中的值将丢失。在这种情况下,最好使用浏览器提供的持久性机制之一来存储令牌;最好是 sessionStorage,因为它在浏览器关闭后会被清除。

实现登录

现在让我们来看一些代码。假设我们已经实现了所有服务器端逻辑,并且服务在 /api/login 处公开了一个 REST 端点来检查登录凭据并返回访问令牌。让我们编写一个简单的服务,通过访问身份验证端点来执行登录操作。稍后我们将向此服务添加更多功能:

app.factory("authenticationSvc", function($http, $q, $window) {
  var userInfo;

  function login(userName, password) {
    var deferred = $q.defer();

    $http.post("/api/login", {
      userName: userName,
      password: password
    }).then(function(result) {
      userInfo = {
        accessToken: result.data.access_token,
        userName: result.data.userName
      };
      $window.sessionStorage["userInfo"] = JSON.stringify(userInfo);
      deferred.resolve(userInfo);
    }, function(error) {
      deferred.reject(error);
    });

    return deferred.promise;
  }

  return {
    login: login
  };
});

在实际代码中,您可能希望将存储数据到 sessionStorage 的语句重构到单独的服务中,因为如果我们这样做,此服务将承担多个责任。为了使演示保持简单,我将其保留在同一个服务中。此服务可以由处理应用程序登录功能的控制器使用。

保护路由

我们可能在应用程序中有一组受保护的路由。如果用户未登录并尝试进入这些路由之一,则应将用户定向到登录页面。这可以使用路由选项中的 resolve 块来实现。以下代码片段说明了实现方法:

$routeProvider.when("/", {
  templateUrl: "templates/home.html",
  controller: "HomeController",
  resolve: {
    auth: ["$q", "authenticationSvc", function($q, authenticationSvc) {
      var userInfo = authenticationSvc.getUserInfo();

      if (userInfo) {
        return $q.when(userInfo);
      } else {
        return $q.reject({ authenticated: false });
      }
    }]
  }
});

resolve 块可以包含多个语句块,这些语句块必须在完成时返回 promise 对象。只是为了澄清,上面定义的名称 auth 不是由框架定义的;我定义了它。您可以根据用例将名称更改为任何名称。

有多种原因会导致传递或拒绝路由。根据场景,您可以在解析/拒绝 promise 时传递对象。我们尚未在服务中实现 getLoggedInUser() 方法。这是一个简单的方法,它从服务返回 loggedInUser 对象。

app.factory("authenticationSvc", function() {
  var userInfo;

  function getUserInfo() {
    return userInfo;
  }
});

通过上述代码片段中 promise 发送的对象通过 $rootScope 广播。如果路由已解析,则会广播事件 $routeChangeSuccess。但是,如果路由失败,则会广播事件 $routeChangeError。我们可以监听 $routeChangeError 事件并将用户重定向到登录页面。由于事件位于 $rootScope 级别,因此最好在运行块中附加事件处理程序。

app.run(["$rootScope", "$location", function($rootScope, $location) {
  $rootScope.$on("$routeChangeSuccess", function(userInfo) {
    console.log(userInfo);
  });

  $rootScope.$on("$routeChangeError", function(event, current, previous, eventObj) {
    if (eventObj.authenticated === false) {
      $location.path("/login");
    }
  });
}]);

处理页面刷新

当用户点击页面的刷新按钮时,服务会丢失其状态。我们必须从浏览器的 sessionStorage 获取数据并将其分配给变量 loggedInUser。由于工厂只调用一次,因此我们可以在初始化函数中设置此变量,如下所示。

function init() {
  if ($window.sessionStorage["userInfo"]) {
    userInfo = JSON.parse($window.sessionStorage["userInfo"]);
  }
}

init();

注销

当用户从应用程序注销时,必须调用相应的 API,并在请求标头中包含访问令牌。用户注销后,我们也应该清除 sessionStorage 中的数据。以下示例包含必须添加到身份验证服务的注销函数。

function logout() {
  var deferred = $q.defer();

  $http({
    method: "POST",
    url: logoutUrl,
    headers: {
      "access_token": userInfo.accessToken
    }
  }).then(function(result) {
    $window.sessionStorage["userInfo"] = null;
    userInfo = null;
    deferred.resolve(result);
  }, function(error) {
    deferred.reject(error);
  });

  return deferred.promise;
}

结论

在单页应用程序中实现身份验证的方法与传统 Web 应用程序的方法大相径庭。由于大部分工作是在客户端进行的,因此用户的状态也必须存储在客户端的某个位置。重要的是要记住,也必须在服务器端维护和验证状态,因为黑客可能会窃取存储在客户端系统上的数据。

本文中的源代码可在 GitHub 上下载。

关于在 Angular 应用程序中实现身份验证的常见问题解答

如何在 Angular 中使用 withCredentials 属性?

withCredentials 属性用于在 HTTP 请求中包含身份验证 cookie。在 Angular 中,您可以在 HttpClient 模块中使用它。发出请求时,您可以将 withCredentials 属性设置为 true。这是一个示例:

this.http.get(url, { withCredentials: true }).subscribe(...);

这将包含服务器之前可能已发送的任何 cookie。

Angular 中 HttpInterceptor 的用途是什么?

HttpInterceptor 是 Angular 中的一项功能,允许您在将 HTTP 请求发送到服务器之前全局拦截和修改它们。它对于各种任务非常有用,例如向所有请求添加身份验证令牌或全局处理错误。

如何创建自定义 HttpInterceptor 来处理 withCredentials?

要创建自定义 HttpInterceptor,您需要创建一个实现 HttpInterceptor 接口的服务。这是一个示例:

app.factory("authenticationSvc", function($http, $q, $window) {
  var userInfo;

  function login(userName, password) {
    var deferred = $q.defer();

    $http.post("/api/login", {
      userName: userName,
      password: password
    }).then(function(result) {
      userInfo = {
        accessToken: result.data.access_token,
        userName: result.data.userName
      };
      $window.sessionStorage["userInfo"] = JSON.stringify(userInfo);
      deferred.resolve(userInfo);
    }, function(error) {
      deferred.reject(error);
    });

    return deferred.promise;
  }

  return {
    login: login
  };
});

此拦截器将克隆每个请求并将 withCredentials 属性设置为 true。

为什么在使用 withCredentials 时会收到 CORS 错误?

CORS(跨源资源共享)是一项安全功能,它限制了跨域共享资源的方式。如果您收到 CORS 错误,则表示服务器未配置为接受来自您域的请求。要解决此问题,您需要将服务器配置为在“Access-Control-Allow-Origin”标头中包含您的域,并将“Access-Control-Allow-Credentials”设置为 true。

如何使用 XMLHttpRequest withCredentials 属性?

XMLHttpRequest withCredentials 属性的工作方式与 Angular HttpClient withCredentials 属性类似。它用于在请求中包含 cookie。这是一个示例:

$routeProvider.when("/", {
  templateUrl: "templates/home.html",
  controller: "HomeController",
  resolve: {
    auth: ["$q", "authenticationSvc", function($q, authenticationSvc) {
      var userInfo = authenticationSvc.getUserInfo();

      if (userInfo) {
        return $q.when(userInfo);
      } else {
        return $q.reject({ authenticated: false });
      }
    }]
  }
});

这将发送包含 cookie 的 GET 请求到指定的 URL。

其余的常见问题解答与HttpClientModule 的使用有关,与文章的核心主题(Angular 中的身份验证实现)关系不大,因此在此处省略。 这些问题可以很容易地通过搜索引擎找到答案。

以上是在角度应用中实施身份验证的详细内容。更多信息请关注PHP中文网其他相关文章!

声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
Python vs. JavaScript:开发人员的比较分析Python vs. JavaScript:开发人员的比较分析May 09, 2025 am 12:22 AM

Python和JavaScript的主要区别在于类型系统和应用场景。1.Python使用动态类型,适合科学计算和数据分析。2.JavaScript采用弱类型,广泛用于前端和全栈开发。两者在异步编程和性能优化上各有优势,选择时应根据项目需求决定。

Python vs. JavaScript:选择合适的工具Python vs. JavaScript:选择合适的工具May 08, 2025 am 12:10 AM

选择Python还是JavaScript取决于项目类型:1)数据科学和自动化任务选择Python;2)前端和全栈开发选择JavaScript。Python因其在数据处理和自动化方面的强大库而备受青睐,而JavaScript则因其在网页交互和全栈开发中的优势而不可或缺。

Python和JavaScript:了解每个的优势Python和JavaScript:了解每个的优势May 06, 2025 am 12:15 AM

Python和JavaScript各有优势,选择取决于项目需求和个人偏好。1.Python易学,语法简洁,适用于数据科学和后端开发,但执行速度较慢。2.JavaScript在前端开发中无处不在,异步编程能力强,Node.js使其适用于全栈开发,但语法可能复杂且易出错。

JavaScript的核心:它是在C还是C上构建的?JavaScript的核心:它是在C还是C上构建的?May 05, 2025 am 12:07 AM

javascriptisnotbuiltoncorc; saninterpretedlanguagethatrunsonenginesoftenwritteninc.1)javascriptwasdesignedAsalightweight,解释edganguageforwebbrowsers.2)Enginesevolvedfromsimpleterterterpretpreterterterpretertestojitcompilerers,典型地提示。

JavaScript应用程序:从前端到后端JavaScript应用程序:从前端到后端May 04, 2025 am 12:12 AM

JavaScript可用于前端和后端开发。前端通过DOM操作增强用户体验,后端通过Node.js处理服务器任务。1.前端示例:改变网页文本内容。2.后端示例:创建Node.js服务器。

Python vs. JavaScript:您应该学到哪种语言?Python vs. JavaScript:您应该学到哪种语言?May 03, 2025 am 12:10 AM

选择Python还是JavaScript应基于职业发展、学习曲线和生态系统:1)职业发展:Python适合数据科学和后端开发,JavaScript适合前端和全栈开发。2)学习曲线:Python语法简洁,适合初学者;JavaScript语法灵活。3)生态系统:Python有丰富的科学计算库,JavaScript有强大的前端框架。

JavaScript框架:为现代网络开发提供动力JavaScript框架:为现代网络开发提供动力May 02, 2025 am 12:04 AM

JavaScript框架的强大之处在于简化开发、提升用户体验和应用性能。选择框架时应考虑:1.项目规模和复杂度,2.团队经验,3.生态系统和社区支持。

JavaScript,C和浏览器之间的关系JavaScript,C和浏览器之间的关系May 01, 2025 am 12:06 AM

引言我知道你可能会觉得奇怪,JavaScript、C 和浏览器之间到底有什么关系?它们之间看似毫无关联,但实际上,它们在现代网络开发中扮演着非常重要的角色。今天我们就来深入探讨一下这三者之间的紧密联系。通过这篇文章,你将了解到JavaScript如何在浏览器中运行,C 在浏览器引擎中的作用,以及它们如何共同推动网页的渲染和交互。JavaScript与浏览器的关系我们都知道,JavaScript是前端开发的核心语言,它直接在浏览器中运行,让网页变得生动有趣。你是否曾经想过,为什么JavaScr

See all articles

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热工具

DVWA

DVWA

Damn Vulnerable Web App (DVWA) 是一个PHP/MySQL的Web应用程序,非常容易受到攻击。它的主要目标是成为安全专业人员在合法环境中测试自己的技能和工具的辅助工具,帮助Web开发人员更好地理解保护Web应用程序的过程,并帮助教师/学生在课堂环境中教授/学习Web应用程序安全。DVWA的目标是通过简单直接的界面练习一些最常见的Web漏洞,难度各不相同。请注意,该软件中

Atom编辑器mac版下载

Atom编辑器mac版下载

最流行的的开源编辑器

VSCode Windows 64位 下载

VSCode Windows 64位 下载

微软推出的免费、功能强大的一款IDE编辑器

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

ZendStudio 13.5.1 Mac

ZendStudio 13.5.1 Mac

功能强大的PHP集成开发环境