详解Angular开发中的登陆与身份验证

由于 Angular 是单页应用,会在一开始,就把大部分的资源加载到浏览器中,所以就更需要注意验证的时机,并保证只有通过了验证的用户才能看到对应的界面。

本篇文章中的身份验证,指的是如何确定用户是否已经登陆,并确保在每次与服务器的通信中,都能够满足服务器的验证需求。注意,并不包括对具体是否具有某一个权限的判断。

对于登陆,主要是接受用户的用户名密码输入提交到服务器进行验证处理验证响应在浏览器端构建身份验证数据

实现身份验证的两种方式

目前,实现身份验证的方法,主要有两个大类:

Cookies

传统的浏览器网页,都是使用 Cookies 来验证身份,实际上,浏览器端的应用层里,基本不用去管身份验证的事情,Cookies 的设置,由服务器端完成,在提交请求的时候,由浏览器自动附加对应的 Cookies 信息,所以在 JavaScript 代码中,不需要为此编写专门的代码。但每次请求的时候,都会带上全部的 Cookies 数据,

随着 CDN 的应用,移动端的逐渐兴起, Cookies 越来越不能满足复杂的、多域名下的身份验证需求。

密钥

实际上基于密钥的身份验证并不是最近才兴起,它一直存在,甚至比 Cookies 历史更长。当浏览器在请求服务器的时候,将密钥以特定的方式附加在请求中,比如放在请求的头部( headers )。为此,需要编写专门的客户端代码来管理。

最近出现的基于 JSON 的 Web 密钥(JSON Web Token)标准,便是典型的使用密钥来实现的身份验证。

在 Web 应用中,如果是构造 API ,则应优先考试使用密钥方式。

处理登陆

登陆是身份验证第一步,通过登陆,才能够组织起来对应的身份验证数据。

需要使用单独的登陆页吗?

登陆页的处理,有两种方式:

单独的登陆页,在登陆完成后,跳转到单页应用之中,这样做可以对单页应用的资源进行访问控制,防止非登陆用户访问,适合后台或者管理工具的应用场景。但实际上降低了单页应用的用户体验
在单页应用之内执行登陆,这样更符合单页应用的设计理念,比较适合大众产品的场景,因为恶意的人总是能够拿到你单页应用的前端代码

单独的登陆页

一般情况下,使用单独的登陆页的目的在于保护登陆后跳转的页面不被匿名用户访问。因此,在登陆页里,构造一个表单,直接采用传统的表彰提交方式(非 Ajax),后端验证用户名密码成功后,输出登陆后单面应用页面的 HTML 。

在这种情况下,可以直接将身份验证信息放在输出的 HTML 里,比如,可以使用 Jade 构造一个这样的页面:

<!-- dashboard.jade --> doctype html html head link(rel="stylesheet", href="https://www.jb51.net/assets/app.e1c2c6ea9350869264da10de799dced1.css") body script. window.token = !{JSON.stringify(token)}; div.md-padding(ui-view) script(src="/assets/app.84b1e53df1b4b23171da.js")


后端在用户名密码验证成功之后,可以采用如下的方式来渲染输出 HTML :

return res.render('dashboard', { token: token });

Angular 应用一启动,便可以进行需要使用身份验证的通信。而且还保证了只有登陆成功的用户才可以进入这个页面。

单页应用内登陆的组织

对于多视图的 Angular 应用,一般会采用路由,在页面之内,一般有固定的侧边栏菜单,或者顶部导航菜单,正文区域由路由模块来控制。

下面的示例代码,使用的是 Angular Material 来组织页面,路由模块使用的是 ui-router 。在应用打开的时候,有专门的加载动画,加载完成之后,显示的页面,使用 AppController 这个控制器,对于没有登陆的用户,会显示登陆表单,登陆完成之后,页面分为三大部分,一是顶部面包屑导航二是侧边栏菜单,另外就是路由控制的正文部分

代码如下:

<body ng-app="app" layout="row"> <div> <!--页面加载的提示--> </div> <div flex layout="row" ng-cloak ng-controller="AppController" ng-init="load()"> <div ng-if="!isUserAuth", ng-controller="LoginController"> <!--登陆表单--> </div> <div ng-if="isUserAuth" flex layout="row"> <md-sidenav flex="15" md-is-locked-open="true"> <!--侧边栏菜单--> </md-sidenav> <md-content flex layout="column" role="main"> <md-toolbar> <!--顶部菜单--> </md-toolbar> <md-content> <!--路由--> <div ui-view></div> </md-content> </md-content> </div> </div> </body>

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wzxspg.html