前言
由于 Angular 是单页应用,会在一开始,就把大部分的资源加载到浏览器中,所以就更需要注意验证的时机,并保证只有通过了验证的用户才能看到对应的界面。
本篇文章中的身份验证,指的是如何确定用户是否已经登陆,并确保在每次与服务器的通信中,都能够满足服务器的验证需求。注意,并不包括对具体是否具有某一个权限的判断。
对于登陆,主要是接受
用户的用户名密码输入
,提交到服务器进行验证
,处理验证响应
,在浏览器端构建身份验证数据
。实现身份验证的两种方式
目前,实现身份验证的方法,主要有两个大类:
Cookies
传统的浏览器网页,都是使用 Cookies 来验证身份,实际上,浏览器端的应用层里,基本不用去管身份验证的事情,Cookies 的设置,由服务器端完成,在提交请求的时候,由浏览器自动附加对应的 Cookies 信息,所以在 JavaScript 代码中,不需要为此编写专门的代码。但每次请求的时候,都会带上全部的 Cookies 数据,
随着 CDN 的应用,移动端的逐渐兴起, Cookies 越来越不能满足复杂的、多域名下的身份验证需求。
密钥
实际上基于密钥的身份验证并不是最近才兴起,它一直存在,甚至比 Cookies 历史更长。当浏览器在请求服务器的时候,将密钥以特定的方式附加在请求中,比如放在请求的头部( headers )。为此,需要编写专门的客户端代码来管理。
最近出现的基于 JSON 的 Web 密钥(JSON Web Token)
标准,便是典型的使用密钥来实现的身份验证。
在 Web 应用中,如果是构造 API ,则应优先考试使用密钥方式。
处理登陆
登陆是身份验证第一步,通过登陆,才能够组织起来对应的身份验证数据。
需要使用单独的登陆页吗?
登陆页的处理,有两种方式:
单独的登陆页
,在登陆完成后,跳转到单页应用之中,这样做可以对单页应用的资源进行访问控制,防止非登陆用户访问,适合后台或者管理工具的应用场景。但实际上降低了单页应用的用户体验在单页应用之内执行登陆
,这样更符合单页应用的设计理念,比较适合大众产品的场景,因为恶意的人总是能够拿到你单页应用的前端代码单独的登陆页
一般情况下,使用单独的登陆页的目的在于保护登陆后跳转的页面不被匿名用户访问。因此,在登陆页里,构造一个表单,直接采用传统的表彰提交方式
(非 Ajax),
后端验证用户名密码成功后,输出登陆后单面应用页面的 HTML 。在这种情况下,可以直接将身份验证信息放在输出的 HTML 里,比如,可以使用
Jade
构造一个这样的页面:后端在用户名密码验证成功之后,可以采用如下的方式来渲染输出 HTML :
Angular 应用一启动,便可以进行需要使用身份验证的通信。而且还保证了只有登陆成功的用户才可以进入这个页面。
单页应用内登陆的组织
对于多视图的 Angular 应用,一般会采用路由,在页面之内,一般有固定的侧边栏菜单,或者顶部导航菜单,正文区域由路由模块来控制。
下面的示例代码,使用的是 Angular Material 来组织页面,路由模块使用的是 ui-router 。在应用打开的时候,有专门的加载动画,加载完成之后,显示的页面,使用 AppController
这个控制器,对于没有登陆的用户,会显示登陆表单,登陆完成之后,页面分为三大部分,