聊聊鉴权那些事(推荐)(2)

const Http = require("http"); let session = {}; const app = Http.createServer((req,res) => { const sessionKey = "uId"; if(req.url === "/favicon.ico"){ return; }else{ const uId = parseInt(Math.random() * 10e10); const cookie = req.headers.cookie; if(cookie && cookie.indexOf(sessionKey) !== -1){ let _uId = cookie.split("=")[1]; res.end(`${session[_uId].name} Come back`); } else{ res.setHeader("Set-Cookie",`${sessionKey}=${uId}`); session[uId] = {"name":"Aaron"}; res.end("hello cookie"); } }; }); app.listen(3000);

代码中解析cookie只是用了和很简单的方式,只是为了完成Dome而已,在实际项目中获取cookie比这个要复杂很多。

Session/Cookie认证主要分四步:

服务器在接受客户端首次访问时在服务器端创建seesion,然后保存seesion(我们可以将seesion保存在内存中,也可以保存在redis中,推荐使用后者),然后给这个session生成一个唯一的标识字符串,然后在响应头中种下这个唯一标识字符串。

签名。这一步只是对sid进行加密处理,服务端会根据这个secret密钥进行解密。(非必需步骤)

浏览器中收到请求响应的时候会解析响应头,然后将sid保存在本地cookie中,浏览器在下次http请求的时候,请求头中会带上该域名下的cookie信息,

服务器在接受客户端请求时会去解析请求头cookie中的sid,然后根据这个sid去找服务器端保存的该客户端的session,然后判断该请求是否合法。

聊聊鉴权那些事(推荐)

利用服务器端的session和浏览器端的cookie来实现前后端的认证,由于http请求时是无状态的,服务器正常情况下是不知道当前请求之前有没有来过,这个时候我们如果要记录状态,就需要在服务器端创建一个会话(seesion),将同一个客户端的请求都维护在各自得会会话中,每当请求到达服务器端的时候,先去查一下该客户端有没有在服务器端创建seesion,如果有则已经认证成功了,否则就没有认证。

与redis结合使用:

const koa = require("koa"); const session = require("koa-session"); const redisStore = require("koa-redis"); const redis = require("redis"); const wrapper = require("co-redis"); const app = new koa(); const redisClient = redis.createClient(6379,"localhost"); const client = wrapper(redisClient); // 类似于密钥 app.keys = ["Aaron"]; const SESSION_CONFIG = { // 所设置的session的key key:"sId", // 最大有效期 maxAge:8640000, // 是否防止js读取 httpOnly:true, // cookie二次签名 signed:true, // 存储方式 stroe:redisStore({client}) }; app.use(session(SESSION_CONFIG,app)); app.use((ctx) => { redisClient.keys("*",(err,keys) => { keys.forEach(key => { redisClient.get(key,(err,val) => { console.log(val); }); }) }) if(ctx.path === "/favicon.ico") return; let n = ctx.session.count || 0; ctx.session.count = ++n; ctx.body = `第${n}次访问` }); app.listen(3000);

虽然Session/Cookie可以解决鉴权问题,但是会有很大的问题,对于服务端来说说是一个巨大的开销,严重的限制了服务器扩展能力,比如说我用两个机器组成了一个集群,小F通过机器A登录了系统,那sessionId会保存在机器A上,假设小F的下一次请求被转发到机器B怎么办?机器B可没有小F的sessionId,有时候会采用一点小伎俩:session sticky,就是让小F的请求一直粘连在机器A上,但是这也不管用,要是机器A挂掉了, 还得转到机器B去。那只好做session的复制了,把sessionId在两个机器之间搬来搬去,再好的服务器也经不起这样的折腾。

Token或Jwt

在计算机身份认证中是令牌(临时)的意思,在词法分析中是标记的意思。一般作为邀请、登录系统使用。现在前后端分离火热,Token混的风生水起,很多项目开发过程中都会用到Token,其实Token是一串字符串,通常因为作为鉴权凭据,最常用的使用场景是API鉴权。

聊聊鉴权那些事(推荐)

客户端使用用户名跟密码请求登录服务端收到请求,去验证用户名与密码验证成功后,服务端会签发一个Token,再把这个Token发送给客户端客户端收到Token以后可以把它存储起来,比如放在Cookie里或者Local Storage里客户端每次向服务端请求资源的时候需要带着服务端签发的Token服务端收到请求,然后去验证客户端请求里面带着的Token,如果验证成功,就向客户端返回请求的数据

示例:

前端

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

转载注明出处:http://www.heiqu.com/f5af62cbc84424f6828ecb3604701384.html