Angular.js与node.js项目里用cookie校验账户登录详解

发布时间 - 2026-01-10 23:13:02    点击率:

前言

最近的新项目中,用户登录需要采用cookie来记住用户,校验身份。所以本文就把实现的过程总结出来分享给大家,需要的朋友们可以参考学习。

在header中携带authId登录

在之前老的项目里,没有采用cookie来记录用户登录状态,而是在请求的header中携带一个身份标识来校验,大致方案如下:

  1. 客户端使用post请求提交user、password给服务端进行登录操作;
  2. 服务端校验用户是否合法,如果合法将产生一个唯一的身份标识authId,返回给客户端,客户端将此authId存放本地(如localStorage);
  3. 客户端在每次需要校验身份的请求中,往header中加入这个authId;
  4. 服务端检测当前的authId是否有效,有效则表示当前用户合法,允许操作;
  5. 客户端用户登出的时候,发送一个delete请求,告诉服务端用户注销,同时删除本地的authId信息;
  6. 服务端收到注销请求后,删除当前的authId数据。

上面的方案,如果其他客户端知道了这个authId后,可以在其他客户端模拟身份,不安全,因此弃用。

用cookie记住用户

新项目中,将采用此文即将介绍的方案–利用cookie来记住用户。主要流程是:

  1. 客户端使用post请求提交user、password给服务端进行登录操作;
  2. 服务端校验用户是否合法,如果合法将产生一个唯一的身份标识authId,以cookie的形式返回给客户端;
  3. 客户端再次请求服务端时,会携带此前已经拿到的cookie给服务端,服务端校验是否合法,合法则可以继续操作;
  4. 客户端用户登出的时候,发送一个delete请求,告诉服务端用户注销,服务端删除登录标识。

     整个过程可以用下面这张图简单表示:


前台用angular搭建单页客户端应用,后台用node搭建服务器,数据存放在mongodb中,这三个技术及cookie基础知识本文不做介绍,感兴趣的同学可以自行了解。

以下的代码都是最简单的get/post请求,但也是最核心的部分,其他有关登录的繁琐操作,感兴趣的同学可以自行补充。

从开始–>结束,遇到的问题

首先,我用的是最基础的post请求,服务端也只是简单的返回数据,部分简单但比较核心的代码如下:

// client
$http({
 method   : 'POST',
 url   : 'http://127.0.0.1:8888/rest/user',
 data   : {name: 'xxx',password:'***'}
 }).success(function (data) {
 console.log('login success,data is:'+data);
}).error(function (data) {
 console.log('login error');
}).then(function () {
 console.log(arguments);
});

// server
var cookie = "authId=" + authId;
res.setHeader('Content-Type', 'application/json;charset=utf-8');
res.setHeader('Set-Cookie', cookie + ';Max-Age=3600;HttpOnly=false;Path=/;');
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end();

查看chrome调试,发现虽然服务端的cookie推过来了,但整体出了问题,提示如下:

XMLHttpRequest cannot load http://127.0.0.1:8888/rest/user. Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:62427' is therefore not allowed access.

分析问题后,发现原因是来自客户端的请求不能跨域访问服务端的请求,请求的资源header中没有携带允许跨越请求的信息。根据这个提示,我们把服务端的代码稍加改进后,如下:

// server
var cookie = "authId=" + authId;
res.setHeader('Content-Type', 'application/json;charset=utf-8');
res.setHeader('Set-Cookie', cookie + ';Max-Age=3600;HttpOnly=false;Path=/;');

// 添加允许跨越的头信息
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');

res.writeHead(200, {'Content-Type': 'text/plain'});
res.end();

解释下上面代码什么意思,第一句主要是允许来自任何域的请求访问,第二句是允许哪些类型的请求访问。加上后再次运行,提示如下:

XMLHttpRequest

cannot load http://127.0.0.1:8888/rest/user. Request header field Content-Type is not allowed by Access-Control-Allow-Headers in preflight response.

原因是来自客户端的请求中,Content-Type头字段,在服务端的响应信息的头中,没有携带,再次修改代码如下:

// server
var cookie = "authId=" + authId;
res.setHeader('Content-Type', 'application/json;charset=utf-8');
res.setHeader('Set-Cookie', cookie + ';Max-Age=3600;HttpOnly=false;Path=/;');

// 添加允许跨越的头信息
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');

// 添加支持Content-Type允许的头信息
res.setHeader('Access-Control-Allow-Headers', 'Content-Type');

res.writeHead(200, {'Content-Type': 'text/plain'});
res.end();

再次运行代码,发现没有错误提示,但是当我们再次请求服务器时,发现客户端的请求并没有携带cookie信息,这显然不是我们想要的效果:

在查阅了一段时间后了解到,客户端是会默认携带cookie给服务端的,但是当客户端的请求是跨域请求时,由于跨域请求本身就有风险,而携带给cookie同样有风险。

因此在进行跨域访问时,客户端不会将服务端返回的cookie携带。此时,我们需要同时在客户端和服务端都设置“withCredentials”为true,代码如下:

// client
$http({
 method   : 'POST',
 url   : 'http://127.0.0.1:8888/rest/user',
 withCredentials: true
 data   : {name: 'xxx',password:'***'}
 }).success(function (data) {
 console.log('login success,data is:'+data);
}).error(function (data) {
 console.log('login error');
}).then(function () {
 console.log(arguments);
});

// server
var cookie = "authId=" + authId;
res.setHeader('Content-Type', 'application/json;charset=utf-8');
res.setHeader('Set-Cookie', cookie + ';Max-Age=3600;HttpOnly=false;Path=/;');

// 添加允许跨越的头信息
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');

// 添加支持Content-Type允许的头信息
res.setHeader('Access-Control-Allow-Headers', 'Content-Type');

// 设置已携带凭证为true
//res.setHeader('Access-Control-Allow-Credentials', true);

res.writeHead(200, {'Content-Type': 'text/plain'});
res.end();

运行后,发现又有错误提示,如下:

XMLHttpRequest cannot load http://127.0.0.1:8888/rest/user. Response to preflight request doesn't pass access control check: A wildcard '*' cannot be used in the 'Access-Control-Allow-Origin' header when the credentials flag is true. Origin 'http://localhost:62427' is therefore not allowed access.

分析错误后发现,原因是当设置了已携带凭证参数为true时,允许跨域请求的源不能设置为泛型的“*”,因此我们再次修改代码如下:(最终代码)

// client
$http({
 method   : 'POST',
 url   : 'http://127.0.0.1:8888/rest/user',
 withCredentials: true
 data   : {name: 'xxx',password:'***'}
 }).success(function (data) {
 console.log('login success,data is:'+data);
}).error(function (data) {
 console.log('login error');
}).then(function () {
 console.log(arguments);
});

// server
var cookie = "authId=" + authId;
res.setHeader('Content-Type', 'application/json;charset=utf-8');
res.setHeader('Set-Cookie', cookie + ';Max-Age=3600;HttpOnly=false;Path=/;');

// 添加允许跨越的头信息
// res.setHeader('Access-Control-Allow-Origin', '*');
// 用当前的客户端origin来取代泛型的“*”
res.setHeader('Access-Control-Allow-Origin', 'http://localhost:62427');

res.setHeader('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');

// 添加支持Content-Type允许的头信息
res.setHeader('Access-Control-Allow-Headers', 'Content-Type');

// 设置已携带凭证为true
res.setHeader('Access-Control-Allow-Credentials', true);

res.writeHead(200, {'Content-Type': 'text/plain'});
res.end();

此时,第一次请求服务端时,服务端返回cookie信息,以后每次客户端请求服务端,客户端的header中都会携带cookie信息,效果如下图:

最后

以上就是在使用cookie记住用户身份时遇到的一些问题及简单解决方法,一般在angular应用中,可能使用较多的是resoure进行http通信,此时只要在GET/POST/PUT/DELETE等请求的参数中,将“withCredentials”设置为true即可。希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流。


# angularjs  # 操作cookie  # angular  # cookie  # 用法  # nodejs  # 登录  # js实现登录注册框手机号和验证码校验(前端部分)  # JavaScript 完成注册页面表单校验的实例  # JavaScript注册时密码强度校验代码  # js简单实现用户注册信息的校验代码  # JS校验与最终登陆界面功能完整示例  # 详解AngularJs HTTP响应拦截器实现登陆、权限校验  # jsp登陆校验演示 servlet、login、success  # 拦截JSP页面  # 校验是否已登录详解及实现代码  # ASP.NET MVC结合JavaScript登录、校验和加密  # javascript使用正则表达式实现注册登入校验  # 服务端  # 客户端  # 的是  # 感兴趣  # 是否合法  # 设置为  # 用户登录  # 可以自行  # 错误提示  # 都是  # 是在  # 放在  # 出了  # 一句  # 就有  # 可以用  # 又有  # 朋友们  # 我用  # 就把 


相关栏目: 【 网站优化151355 】 【 网络推广146373 】 【 网络技术251813 】 【 AI营销90571


相关推荐: 免费网站制作appp,免费制作app哪个平台好?  深圳网站制作培训,深圳哪些招聘网站比较好?  如何用虚拟主机快速搭建网站?详细步骤解析  无锡营销型网站制作公司,无锡网选车牌流程?  Laravel如何处理异常和错误?(Handler示例)  Laravel怎么做缓存_Laravel Cache系统提升应用速度的策略与技巧  Laravel全局作用域是什么_Laravel Eloquent Global Scopes应用指南  如何为不同团队 ID 动态生成多个独立按钮  Gemini手机端怎么发图片_Gemini手机端发图方法【步骤】  如何在自有机房高效搭建专业网站?  如何在腾讯云服务器快速搭建个人网站?  如何在IIS7中新建站点?详细步骤解析  Laravel如何处理JSON字段_Eloquent原生JSON字段类型操作教程  如何撰写建站申请书?关键要点有哪些?  Laravel Blade组件怎么用_Laravel可复用视图组件的创建与使用  Laravel怎么使用Blade模板引擎_Laravel模板继承与Component组件复用【手册】  html5audio标签播放结束怎么触发事件_onended回调方法【教程】  如何在 Pandas 中基于一列条件计算另一列的分组均值  什么是javascript作用域_全局和局部作用域有什么区别?  如何快速完成中国万网建站详细流程?  Laravel如何配置和使用队列处理异步任务_Laravel队列驱动与任务分发实例  php静态变量怎么调试_php静态变量作用域调试技巧【解答】  Laravel怎么生成二维码图片_Laravel集成Simple-QrCode扩展包与参数设置【实战】  使用spring连接及操作mongodb3.0实例  利用python获取某年中每个月的第一天和最后一天  Laravel怎么写单元测试_PHPUnit在Laravel项目中的基础测试入门  如何快速搭建安全的FTP站点?  html5的keygen标签为什么废弃_替代方案说明【解答】  laravel怎么实现图片的压缩和裁剪_laravel图片压缩与裁剪方法  Laravel中间件起什么作用_Laravel Middleware请求生命周期与自定义详解  Laravel如何使用Socialite实现第三方登录?(微信/GitHub示例)  济南网站建设制作公司,室内设计网站一般都有哪些功能?  Laravel如何使用Collections进行数据处理?(实用方法示例)  微信推文制作网站有哪些,怎么做微信推文,急?  Win11搜索栏无法输入_解决Win11开始菜单搜索没反应问题【技巧】  Bootstrap CSS布局之列表  如何用VPS主机快速搭建个人网站?  如何在Windows服务器上快速搭建网站?  jQuery validate插件功能与用法详解  详解Android——蓝牙技术 带你实现终端间数据传输  网站优化排名时,需要考虑哪些问题呢?  UC浏览器如何设置启动页 UC浏览器启动页设置方法  PHP 500报错的快速解决方法  ,在苏州找工作,上哪个网站比较好?  如何在不使用负向后查找的情况下匹配特定条件前的换行符  Laravel项目怎么部署到Linux_Laravel Nginx配置详解  Win11搜索不到蓝牙耳机怎么办 Win11蓝牙驱动更新修复【详解】  Laravel如何使用集合(Collections)进行数据处理_Laravel Collection常用方法与技巧  香港服务器网站搭建教程-电商部署、配置优化与安全稳定指南  Laravel怎么实现支付功能_Laravel集成支付宝微信支付