前端之家
  • 首页
  • 技术问答
  • 编程语言
  • 前端开发
  • 移动开发
  • 开发工具
  • 程序设计
  • 行业应用
  • CMS系统
  • 服务器
  • ▸ PHP
  • ▸ Java
  • ▸ Java SE
  • ▸ Python
  • ▸ C#
  • ▸ C&C++
  • ▸ Ruby
  • ▸ VB
  • ▸ asp.Net
  • ▸ Go
  • ▸ Perl
  • ▸ netty
  • ▸ Django
  • ▸ Delphi
  • ▸ Jsp
  • ▸ .NET Core
  • ▸ Spring
  • ▸ Flask
  • ▸ Springboot
  • ▸ SpringMVC
  • ▸ Lua
  • ▸ Laravel
  • ▸ Mybatis
  • ▸ Asp
  • ▸ Groovy
  • ▸ ThinkPHP
  • ▸ Yii
  • ▸ swoole
  • ▸ HTML
  • ▸ HTML5
  • ▸ JavaScript
  • ▸ CSS
  • ▸ jQuery
  • ▸ Bootstrap
  • ▸ Angularjs
  • ▸ TypeScript
  • ▸ Vue
  • ▸ Dojo
  • ▸ Json
  • ▸ Electron
  • ▸ Node.js
  • ▸ extjs
  • ▸ Express
  • ▸ XML
  • ▸ ES6
  • ▸ Ajax
  • ▸ Flash
  • ▸ Unity
  • ▸ React
  • ▸ Flex
  • ▸ Ant Design
  • ▸ Web前端
  • ▸ 微信小程序
  • ▸ 微信公众号
  • ▸ iOS
  • ▸ Android
  • ▸ Swift
  • ▸ Hybrid
  • ▸ Cocos2d-x
  • ▸ Flutter
  • ▸ Xcode
  • ▸ Silverlight
  • ▸ cocoa
  • ▸ Cordova
  • 前端之家
  • JavaScript
  • 详解Angular开发中的登陆与身份验证

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

2019-01-05 JavaScript 前端之家
前端之家收集整理的这篇文章主要介绍了详解Angular开发中的登陆与身份验证,前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

前言

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

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

对于登陆,主要是接受

用户的用户名密码输入

,

提交到服务器进行验证

,

处理验证响应

,

在浏览器端构建身份验证数据

。

实现身份验证的两种方式

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

Cookies

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

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

密钥

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

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

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

处理登陆

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

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

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

单独的登陆页

,在登陆完成后,跳转到单页应用之中,这样做可以对单页应用的资源进行访问控制,防止非登陆用户访问,适合后台或者管理工具的应用场景。但实际上降低了单页应用的用户体验

在单页应用之内执行登陆

,这样更符合单页应用的设计理念,比较适合大众产品的场景,因为恶意的人总是能够拿到你单页应用的前端代码

单独的登陆页

一般情况下,使用单独的登陆页的目的在于保护登陆后跳转的页面不被匿名用户访问。因此,在登陆页里,构造一个表单,直接采用传统的表彰提交方式

(非 Ajax),

后端验证用户名密码成功后,输出登陆后单面应用页面的 HTML 。

在这种情况下,可以直接将身份验证信息放在输出的 HTML 里,比如,可以使用

Jade

构造一个这样的页面:

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

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

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

单页应用内登陆的组织

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

下面的示例代码,使用的是 Angular Material 来组织页面,路由模块使用的是 ui-router 。在应用打开的时候,有专门的加载动画,加载完成之后,显示的页面,使用 AppController 这个控制器,对于没有登陆的用户,会显示登陆表单,登陆完成之后,页面分为三大部分,

一是顶部面包屑导航

,

二是侧边栏菜单

,另外就是

路由控制的正文部分

。

代码如下:

对于 Loading 动画,是在 AppController 之外的,可以在 AppController 的代码中,对其进行隐藏。这样达到了所有 CSS / JavaScript 加载完成之后 Loading 就消失的目的。

AppController 中有一个变量 isUserAuth ,初始化的时候是 false ,当本地存储的会话信息验证有效,或者登陆完成之后,这个值便会置为 ture ,由于 ng-if 的控制,便可以实现隐藏登陆表单、显示应用内容的目的。要注意,这里只有使用 ng-if 而不是 ng-show/ng-hide ,前者才会真正的删除和增加 DOM 元素,而后者只是修改某个 DOM 元素的 CSS 属性,这点很重要,只有这样,才能够保证登陆完成之后,再加载单页应用中的内容,防止还没有登陆,当前路由中的控制器代码就直接执行了。

为什么客户端也要加密密码

一个比较理想的基于用户名和密码的登陆流程是这样的:

1.浏览器端获取用户输入的密码,使用 MD5 一类的哈希算法,生成固定长度的新密码,如 md5(username + md5(md5(password))) ,再将密码哈希值和用户名提交给后端

2.后端根据用户名获取对应的盐,使用用户名和密码哈希值,算出一个密文,根据用户名和密文去数据库查询

3.如果查询成功,则生成密钥,返回给浏览器,并执行第 4 步

4.后端生成新的盐,根据新的盐和浏览器提交的密码哈希值,生成新的密文。在数据库中更新盐和密文

可能有 80% 的人无法理解为什么要把一个登陆做得这么复杂。这可能要写一篇专门的文章才解释得清楚。在这里先解释一下为什么浏览器端要对密码做哈希,原因如下:

1.从源头上保护用户的密码,保证只有做按键记录才可以拿到用户的原始密码 2.就算网络被窃听,又没有使用 https ,那么被偷走的密码,也只是哈希之后的,最多影响用户在这个服务器里的数据,而不影响使用相同密码的其它网站 3.就算是服务器的所有者,都无法获取用户的原始密码 这种做法,使得用户的最大风险,也只是当前这个应用中的数据被窃取。不会扩大损失范围,绝不会出现 CSDN 之流的问题。

登陆成功的通知

对于有些应用,并不是所有的页面都需要用户登陆的,可能是进行某些操作的时候,才需要登陆。在这种情况下,登陆完成之后,必须要通知整个应用。这可以使用广播这个功能。

简易代码如下:

function LoginController($rootScope) {
// 登陆成功之后调用的函数
function afterLoginSuccess() {
$rootScope.$broadcast('user.login.success',{
// 需要传输的数据
});
}
}

在其它的控制器中,便可以监听这个广播,并执行登陆成功之后需要进行的操作,如获取列表或者详情:

身份验证信息

登陆成功之后,服务器返回了密钥,之后的 API 请求都需要带上密钥,而且请求返回的响应,还需要检查是否是关于身份信息失效的错误。这一系列的工作比较繁琐,应该是自动完成才行。

保存

密钥的保存,大概有如下几个办法:

1.Cookies:

前面已经提到了,这个并不推荐使用。同时,它还有最大 4k 的限制

2.sessionStorage:

tab 页内有效,一旦关闭,或者打开了新的 tab 页,sessionStorage 是不能共享的

3.localStorage:

较为理想的存储方式,除非清理浏览器数据,否则 localStorage 存储的数据会一直存在

4.Angular 单例 Service:

存储在应用之内得话,刷新后数据会丢失,当然也不能 tab 页之间共享 比较好的办法是,身份验证信息存储在 localStorage 里,但在应用启动时,初始化到 Angular 的单例 Service 中。

在请求中加入身份验证信息

身份验证信息的目的,是为了向服务器表明身份,获取数据。所以,在请求中需要附加身份验证信息。

一般的应用中,身份验证信息都是放在请求的 headers 头部中。如果在每次请求的时候,一一设置 headers ,那就太费时费力了。Angular 中的 $httpProvider 提供了一个拦截器 interceptors ,通过它可以实现对每一个请求和响应的统一处理。

添加拦截器的方式如下:

HttpInterceptor 的定义方式如下:

function HttpInterceptor($q) {
return {
// 请求发出之前,可以用于添加各种身份验证信息
request: function(config){
if(localStorage.token) {
config.headers.token = localStorage.token;
}
return config;
},// 请求发出时出错
requestError: function(err){
return $q.reject(err);
},// 成功返回了响应
response: function(res){
return res;
},// 返回的响应出错,包括后端返回响应时,设置了非 200 的 http 状态码
responseError: function(err){
return $q.reject(err);
}
};
}

拦截器提供了对发出请求到返回响应的全生命周期处理,一般可以用来做下面几个事情:

1.统一在发出的请求中添加数据,如添加身份验证信息

2.统一处理错误,包括请求发出时出的错(如浏览器端的网络不通),还有响应时返回的错误

3.统一处理响应,比如缓存一些数据等

4.显示请求进度条

在上面的示例代码中,当 localStorage 中包括 token 这个值时,就在每一个请求的头部,添加一个 token 值。

失效及处理

一般的,后端应该在 token 验证失败时,将响应的 http 状态码设置为 401 ,这样,在拦截器的 responseError 中便可以统一处理:

错误一般是用于身份验证失败,具体要看后端对身份验证失败时抛出的错误 } else if(404 === err.status) { // 服务器返回了 404 } return $q.reject(err); }

总结

其实,只要服务器返回的状态码不是 200 ,都会调用 responseError ,可以在这里,统一处理并显示错误。

以上内容是关于Angular开发应用中的登陆与身份验证的相关知识,希望对大家学习Angular有所帮助。

angularangularangularjs登陆验证登陆验证身份验证
  • 上一篇:AngularJS 指令详细介绍下一篇:AngularJS 模型详细介绍及实例代码

猜你在找的JavaScript相关文章

Javascript中的事件冒泡与捕获
事件冒泡和事件捕获 起因:今天在封装一个bind函数的时候,发现el.addEventListener函数支...
作者:前端之家 时间:2021-02-22
搞懂js中小数运算精度问题原因及解决办法
js小数运算会出现精度问题 js number类型 JS 数字类型只有number类型,number类型相当于其...
作者:前端之家 时间:2021-02-22
搞懂:前端跨域问题JS解决跨域问题VUE代理解决跨域问题原理
什么是跨域 跨域 : 广义的跨域包含一下内容 : 1.资源跳转(链接跳转,重定向跳转,表单提...
作者:前端之家 时间:2021-02-22
前端对base64编码的理解,原生js实现字符base64编码
@ "TOC" 常见对base64的认知(不完全正确) 首先对base64常见的认知,也是...
作者:前端之家 时间:2021-02-22
搞懂:MVVM模型以及VUE中的数据绑定数据劫持发布订阅模式
搞懂:MVVM模式和Vue中的MVVM模式 MVVM MVVM : 的缩写,说都能直接说出来 :模型, :视图...
作者:前端之家 时间:2021-02-22
js判断浏览器是否支持webGL
起因是我之前开发的网页,用到了three.js制作了一个3d的旋转球体效果。 在各种浏览器上运行...
作者:前端之家 时间:2021-02-14
js判断undefined和null
js判断undefined js判断null js判断null和undefined
作者:前端之家 时间:2021-02-14
将文字自动转为banner打印形式的工具
http://patorjk.com/software/taag/
作者:前端之家 时间:2021-02-14
聊一聊 bootstrap 的轮播图插件
今天做工作的时候,轻车熟路的做完,又用到了bootstrap的轮播图,觉得有必要安利一下这个插...
作者:前端之家 时间:2021-02-14
js实现图片无缝循环跑马灯
html 代码 css js代码 function mylsRunHorseLight() { if (mylsTimer != null) { clearIn...
作者:前端之家 时间:2021-02-14
HTMLHTML5JavaScriptCSSjQueryBootstrapAngularjsTypeScriptVueDojoJsonElectronNode.jsextjsExpress XMLES6AjaxFlashUnityReactFlexAnt DesignWeb前端微信小程序微信公众号
  • • Javascript中的事件冒泡与
  • • 搞懂js中小数运算精度问题
  • • 搞懂:前端跨域问题JS解决
  • • 前端对base64编码的理解,
  • • 搞懂:MVVM模型以及VUE中的
  • • js实现横向跑马灯效果
  • • js判断浏览器是否支持webG
  • • js判断undefined和null
  • • 将文字自动转为banner打印
  • • 聊一聊 bootstrap 的轮播图
关闭广告单独headers封装代码提示错误整数正则非0开头跳页出页码antd table提示URL未注册公众号支付vue hash模式iSlider车牌键盘循环图片echarts 双折左右布局DllPlugin对象创建打字游戏圈选两栏云函数蒙版ES2020橱窗无缝滚动轮播色块碰撞组件销毁文档操作
最近更新
· 小米手机重装系统价格多少?专业维修服务详解02-05
· 手把手教你重装电脑系统,让你的电脑焕然一新!02-05
· 教你一步步重装XP系统,让你的电脑重获新生02-05
· 从备份到上网:一步步教你重装电脑系统02-05
· Sony笔记本电脑一键重装系统详细图文教程02-05
· Lenovo笔记本重装系统超详细教程,小白也能轻松...02-05
· 联想笔记本一键重装Win10系统详细教程02-05
· 电脑系统故障无需愁,专业维修店帮你重装旧貌换新...02-05
· 联想笔记本一键重装Win10系统图文教程,小白也能...02-05
· 笔记本重装系统图文教程:从光盘启动一步到位02-05
好站推荐
菜鸟教程
编程之家
前端之家
商务合作
联系我们
Copyright © 2019 前端之家. 当前版本 V7.0.16
前端之家 版权所有 闽ICP备13020303号-10