在Angular.js和node.js项目中用cookie验证账号登录的详细说明
序
在最近的新项目中,用户需要cookie来记住用户,并在登录时验证他们的身份。所以总结一下实现过程,分享给大家,让有需要的朋友可以参考学习。
使用标题中的authId登录
在以前的旧项目中,cookie不用于记录用户登录状态,而是在请求头中携带一个标识进行验证。总体方案如下:
客户端使用post请求向服务器提交用户和密码进行登录操作;服务器验证用户是否合法,如果合法,会生成一个唯一的身份authId,返回给客户端,客户端将这个authId存储在本地(比如本地存储);客户端添加这个authId每次它需要验证其身份时发送到报头;服务器检测当前authId是否有效,如果有效,则表示当前用户合法,允许操作;客户端用户注销时,发送删除请求,告知服务器用户注销并删除本地authId信息;收到注销请求后,服务器删除当前的authId数据。上述方案,如果其他客户端知道这个authId,可以在其他客户端模拟身份,不安全,所以放弃。
记住有cookie的用户
在新项目中,将采用本文介绍的方案——用cookie记住用户。主要过程是:
客户端使用post请求向服务器提交用户和密码进行登录操作;服务器验证用户是否合法,如果合法,会生成唯一的身份authId,以cookie的形式返回给客户端;当客户端再次请求服务器时,会将之前获取的cookie带到服务器,服务器会检查是否合法,如果合法,可以继续操作;当客户端用户注销时,会发送一个删除请求,告诉服务器用户注销,服务器会删除登录id。整个过程可以简单地用下图来表示:
前台使用angular构建单页客户端应用程序,后台使用node构建服务器,数据存储在mongodb中。这三项技术和cookie的基本知识本文不做介绍,感兴趣的同学可以自己了解一下。
以下代码是最简单的get/post请求,但它们也是核心部分。感兴趣的同学可以补充其他与登录相关的繁琐操作。
从头到尾,遇到的问题
首先,我使用最基本的post请求,服务器只是返回数据。一些简单但相对核心的代码如下:
//客户端$http({ method : 'POST ',URL : ' http://127 . 0 . 0 . 1:8888/rest/user ',数据: {name: 'xxx ',password:'***'} })。success(function(data){ console . log(' log in success,data is : ' data);}).错误(函数(数据){ console.log('登录错误');}).然后(function(){ console . log(arguments));});//server var cookie=' AuthID=' AuthID;res.setHeader('Content-Type ',' application/JSON;charset=utf-8 ');res.setHeader('Set-Cookie ',Cookie ';最大年龄=3600;HttpOnly=false路径=/;');res.writeHead(200,{ ' Content-Type ' : ' text/plain ' });RES . end();看chrome调试,发现服务器上的cookie虽然被推了过去,但整体还是有问题的,提示如下:
XMLHttpRequest无法加载http://127 . 0 . 0 . 1:8888/rest/user。对预检请求的响应未通过访问控制检查:请求的资源上不存在“访问控制-允许-来源”标头。origin ' http://localhost :62427 '不允许访问。分析问题后发现,来自客户端的请求无法跨域访问服务器的请求,请求的资源头中没有携带允许请求跨域的信息。根据这个提示,我们稍微改进了服务器代码,如下所示:
//服务器var cookie=' AuthID=' AuthIDres.setHeader('Content-Type ',' application/JSON;charset=utf-8 ');res.setHeader('Set-Cookie ',Cookie ';最大年龄=3600;HttpOnly=false路径=/;');//添加允许跨越的头信息res.setHeader('访问控制-允许-源',' *);res.setHeader('访问控制-允许-方法、“获取、投放、发布、删除、选项”);res.writeHead(200,{ ' Content-Type ' : ' text/plain ' });RES . end();解释下上面代码什么意思,第一句主要是允许来自任何域的请求访问,第二句是允许哪些类型的请求访问。加上后再次运行,提示如下:
XMLHttpRequest
无法加载http://127 .0 .0 .1:8888/休息/用户.预检响应中的访问控制-允许-标题不允许请求标题字段内容-类型。原因是来自客户端的请求中,内容类型头字段,在服务端的响应信息的头中,没有携带,再次修改代码如下:
//服务器var cookie=' AuthID=' AuthIDres.setHeader('Content-Type ',' application/JSON;charset=utf-8 ');res.setHeader('Set-Cookie ',Cookie ';最大年龄=3600;HttpOnly=false路径=/;');//添加允许跨越的头信息res.setHeader('访问控制-允许-源',' *);res.setHeader('访问控制-允许-方法、“获取、投放、发布、删除、选项”);//添加支持内容类型允许的头信息res.setHeader('访问控制-允许-头','内容类型');res.writeHead(200,{ ' Content-Type ' : ' text/plain ' });RES . end();再次运行代码,发现没有错误提示,但是当我们再次请求服务器时,发现客户端的请求并没有携带甜饼干信息,这显然不是我们想要的效果:
在查阅了一段时间后了解到,客户端是会默认携带甜饼干给服务端的,但是当客户端的请求是跨域请求时,由于跨域请求本身就有风险,而携带给甜饼干同样有风险。
因此在进行跨域访问时,客户端不会将服务端返回的甜饼干携带。此时,我们需要同时在客户端和服务端都设置"带密码"为没错,代码如下:
//客户端$http({ method : 'POST ',URL : ' http://127。0 .0 .1:8888/rest/user ',凭据:真实数据: { name : ' XXX ',password:'***'}).成功(功能(数据){控制台。日志('登录成功,数据为: '数据);}).错误(函数(数据){ console.log('登录错误');}).然后(函数(){控制台。日志(参数));});//服务器var cookie=' AuthID=' AuthIDres.setHeader('Content-Type ',' application/JSON;charset=utf-8 ');res.setHeader('Set-Cookie ',Cookie ';最大年龄=3600;HttpOnly=false路径=/;');//添加允许跨越的头信息res.setHeader('访问控制-允许-源',' *);res.setHeader('访问控制-允许-方法、“获取、投放、发布、删除、选项”);//添加支持内容类型允许的头信息res.setHeader('访问控制-允许-头','内容类型');//设置已携带凭证为true//res.setHeader('访问控制-允许-凭据,真);res.writeHead(200,{ ' Content-Type ' : ' text/plain ' });RES . end();运行后,发现又有错误提示,如下:
XMLHttpRequest无法加载http://127 .0 .0 .1:8888/休息/用户.对预检请求的响应未通过访问控制检查:当凭据标志为真时,不能在"访问控制-允许-原始"标头中使用通配符"*"。因此,不允许访问origin ' http://localhost :62427 ' .分析错误后发现,原因是当设置了已携带凭证参数为真实的时,允许跨域请求的源不能设置为泛型的"*",因此我们再次修改代码如下:(最终代码)
//客户端$http({ method : 'POST ',URL : ' http://127。0 .0 .1:8888/rest/user ',凭据:真实数据: { name : ' XXX ',password:'***'}).成功(功能(数据){控制台。日志('登录成功,数据为: '数据);}).错误(函数(数据){ console.log('登录错误');}).然后(函数(){控制台。日志(参数));});//服务器var cookie=' AuthID=' AuthIDres.setHeader('Content-Type ',' application/JSON;charset=utf-8 ');res.setHeader('Set-Cookie ',Cookie ';最大年龄=3600;HttpOnly=false路径=/;');//添加允许跨越的头信息//res.setHeader('访问控制-允许-起源',' *);//用当前的客户端起源来取代泛型的“*”RES . set header('访问控制-允许-源,' http://localhost :62427 ');res.setHeader('访问控制-允许-方法、“获取、投放、发布、删除、选项”);//添加支持内容类型允许的头信息res.setHeader('访问控制-允许-头','内容类型');//设置已携带凭证为' trueres.setHeader('访问控制-允许-凭据,真);res.writeHead(200,{ ' Content-Type ' : ' text/plain ' });RES . end();此时,第一次请求服务端时,服务端返回甜饼干信息,以后每次客户端请求服务端,客户端的页眉中都会携带甜饼干信息,效果如下图:
最后
以上就是在使用甜饼干记住用户身份时遇到的一些问题及简单解决方法,一般在有角的应用中,可能使用较多的是资源进行超文本传送协议(超文本传输协议的缩写)通信,此时只要在获取/发布/放入/删除等请求的参数中,将"带密码"设置为真实的即可。希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流。
版权声明:在Angular.js和node.js项目中用cookie验证账号登录的详细说明是由宝哥软件园云端程序自动收集整理而来。如果本文侵犯了你的权益,请联系本站底部QQ或者邮箱删除。