参考:https://blog.csdn.net/m0_50308467/article/details/134999017
cookie是什么
- HTTP1.0中协议是无状态的,但在WEB应用中,在多个请求之间共享会话是非常必要的,所以出现了Cookie
- cookie是为了辩别用户身份,进行会话跟踪而存储在客户端上的数据
Cookie的处理流程
使用步骤
服务器发送cookie
客户端第一次访问服务器的时候服务器通过响应头向客户端发送Cookie,属性之间用分号空格分隔
Set-Cookie:name=zhufeng; Path=/
客户端接收保存cookie
客户端接收到Cookie之后保存在本地
客户端发送cookie
以后客户端再请求服务器的时候会把此Cookie发送到服务器端
Cookie:name=zhufeng
cookie重要属性
name
是指Cookie的名称,用于标识特定的Cookie。value
是指与Cookie关联的具体数据。它是存储在Cookie中的值,代表了特定名称的Cookie所包含的信息。Domain
属性指定Cookie的有效域名。只有在匹配该域名或其子域名的请求中,浏览器才会发送相应的Cookie。Path
属性指定Cookie的有效路径。只有在请求的路径与Cookie的路径匹配时,浏览器才会发送相应的Cookie。默认情况下,路径为/
,表示在整个网站中都有效。maxAge
属性指定Cookie的最大存活时间(单位为秒),即在客户端上保持有效的时间长度。Expires
另一种设置Cookie过期时间的方式是使用Expires
属性,它是一个具体的日期和时间,表示Cookie的过期时间点。httpOnly
属性是一个布尔值,用于限制客户端JavaScript对Cookie的访问。如果设置为true
,则客户端无法通过JavaScript代码读取或修改Cookie,只能在HTTP请求中发送给服务器。Secure
属性是一个布尔值,用于指示是否只在通过HTTPS协议建立的安全连接中发送Cookie。如果设置为true
,则Cookie只会在通过HTTPS发送的请求中被浏览器发送到服务器。SameSite
属性用于控制跨站点请求中是否发送Cookie。它可以设置为Strict
、Lax
或None
。Strict
表示只在同一站点的请求中发送Cookie,Lax
表示在导航到目标站点的安全请求中发送Cookie,而None
表示始终在所有请求中发送Cookie。Partition Key
是一个概念,没有直接对应的Cookie属性。它通常用于将Cookie存储空间分割成不同的分区,以便不同的应用程序或组件可以独立管理和访问自己的Cookie。通过使用不同的分区键,可以隔离不同的Cookie存储,防止冲突和干扰。Priority
属性不是Cookie的属性,而是一个HTTP头字段(非Cookie属性),用于指示请求中的Cookie的优先级。优先级值可以是High
、Medium
或Low
,用于表示Cookie的重要程度或处理顺序。这个头字段通常由浏览器使用,以帮助服务器根据需要进行Cookie的处理和响应。
koa中读写cookie
server.js
const Koa = require('koa');
const app = new Koa();
const Router = require('koa-router');
const router = new Router();
const Cookies = require('./cookies');
app.keys = ['zhufeng'];
app.use(async function (ctx, next) {
ctx.cookies = new Cookies(ctx.req, ctx.res, { keys: app.keys });
await next();
});
router.get('/write', async (ctx) => {
//1.普通设置
ctx.cookies.set('name', 'name_value');
//2.设置过期时间
ctx.cookies.set('name_expire', 'name_expire_value', {
maxAge: 10 * 1000
});
//3.设置域名
ctx.cookies.set('name_domain', 'name_domain_value', {
domain: 'localhost'
});
//4.设置路径
ctx.cookies.set('name_path', 'name_path_value', {
path: '/read'
});
//5.设置httpOnly
ctx.cookies.set('name_httpOnly', 'name_httpOnly_value', {
httpOnly: true
});
ctx.body = '发送Cookie给客户端';
});
router.get('/read', async (ctx) => {
const name = ctx.cookies.get('name');
const name_expire = ctx.cookies.get('name_expire');
const name_domain = ctx.cookies.get('name_domain');
const name_path = ctx.cookies.get('name_path');
const name_httpOnly = ctx.cookies.get('name_httpOnly');
let values = [name, name_expire, name_domain, name_path, name_httpOnly]
//2.获取客户端发送过来的Cookie
ctx.body = values.join(',');
});
app.use(router.routes());
app.listen(3000, () => {
console.log('Server is running at http://localhost:3000');
});
cookie.js
function Cookies(req,res){
this.req = req;
this.res = res;
}
Cookies.prototype.set = function(name,value,attrs){
const headers = this.res.getHeader('Set-Cookie')||[];
let cookie = new Cookie(name,value,attrs);
headers.push(cookie.toHeader());
this.res.setHeader('Set-Cookie',headers);
}
Cookies.prototype.get = function(name){
let cookie = this.req.headers.cookie||'';
return getValueFromHeader(name,cookie);
}
function getValueFromHeader(name,cookie){
if(!cookie) return ;
let regexp = new RegExp("(?:^|;) *"+name+"=([^;]*)");
let match = cookie.match(regexp);
if(match){
return match[1];
}
}
function Cookie(name,value,attrs){
this.name = name;
this.value = value;
for(let name in attrs){
this[name]=attrs[name];
}
}
Cookie.prototype.toString = function(){
return this.name +'='+this.value;
}
Cookie.prototype.toHeader = function(){
let header = this.toString();
if(this.path) header += `; path=`+this.path;
if (this.maxAge) this.expires = new Date(Date.now() + this.maxAge);
if(this.expires) header += `; expires=`+this.expires.toUTCString();
if(this.domain) header += `; domain=`+this.domain;
if(this.httpOnly) header += `; httpOnly`;
console.log(header);
return header;
}
module.exports = Cookies
登录
const Koa = require('koa');
const app = new Koa();
const Router = require('koa-router');
const router = new Router();
const bodyParser = require('koa-bodyparser');
app.use(bodyParser());
router.get('/login', async ctx => {
ctx.body = `
<form action="/login" method="post">
<input type="text" name="username" />
<input type="submit" value="提交" />
</form>
`;
});
router.post('/login', async ctx => {
ctx.cookies.set('username', ctx.request.body.username);
ctx.redirect('/user');
});
router.get('/user', async ctx => {
if (ctx.cookies && ctx.cookies.get('username')) {
ctx.body = ctx.cookies.get('username');
} else {
return ctx.redirect('/login');
}
});
app.use(router.routes());
app.listen(8080, () => {
console.log('Server is running at http://localhost:8080');
});
cookie使用注意事项
- 可能被客户端篡改,使用前验证合法性
- 不要存储敏感数据,比如用户密码,账户余额
- 使用httpOnly保证安全
- 尽量减少cookie的体积
- 设置正确的domain和path,减少数据传输
sign
const Koa = require('koa');
const app = new Koa();
const Router = require('koa-router');
const router = new Router();
app.keys = ['zhufeng'];
router.get('/write', async (ctx) => {
ctx.cookies.set('username', 'zhangsan', {
signed: true
});
ctx.body = 'write ok';
});
router.get('/read', async (ctx) => {
const username = ctx.cookies.get('username', {
signed: true
});
ctx.body = "username:"+username;
});
app.use(router.routes());
app.listen(3000, () => {
console.log('Server running on http://localhost:3000');
});