使用cookie
cookie是一种允许应用程序在无状态HTTP协议之上维护状态的机制。
cookie是一种name/value存储,其中的名称和值以纯文本形式存储。它们会在浏览器关闭或延迟后过期。它们可以配置在特定的域名或路径上,并限制为安全资源(通过HTTPS发送或下载),或限制为服务器(不允许客户端脚本访问)。
Cookie名称实际上是区分大小写的。
cookie存储在客户端,并随着与存储它们的域和路径相匹配的每个后续请求一起发送,直到它们过期。这将产生不可忽略的成本。
不应该认为cookie是安全的。它们以明文形式存储在用户的计算机上,可以被任何程序读取。当使用清除连接时,代理也可以读取它们。在使用之前一定要验证值,并且不要在其中存储任何敏感信息。
服务器设置的cookie仅在客户端接收到包含它们的响应后的请求中可用。
cookie可能会被重复发送。这对于更新过期时间和避免丢失cookie通常是有用的。
设置cookie
默认情况下,cookie是在session期间定义的:
SessionID = generate_session_id(),
Req = cowboy_req:set_resp_cookie(<<"sessionid">>, SessionID, Req0).
它们也可以设置一个持续时间以秒为单位:
SessionID = generate_session_id(),
Req = cowboy_req:set_resp_cookie(<<"sessionid">>, SessionID, Req0,
#{max_age => 3600}).
删除cookie,设置max_age为0。
SessionID = generate_session_id(),
Req = cowboy_req:set_resp_cookie(<<"sessionid">>, SessionID, Req0,
#{max_age => 0}).
要将cookie限制在特定的域和路径,可以使用相同名称的选项:
Req = cowboy_req:set_resp_cookie(<<"inaccount">>, <<"1">>, Req0,
#{domain => "my.example.org", path => "/account"}).
cookie将与请求一起发送到该域及其所有子域,并发送到该路径上或路径层次结构中更深层的资源。
将cookie限制为安全通道(通常是通过HTTPS提供的资源):
SessionID = generate_session_id(),
Req = cowboy_req:set_resp_cookie(<<"sessionid">>, SessionID, Req0,
#{secure => true}).
防止客户端脚本访问cookie:
SessionID = generate_session_id(),
Req = cowboy_req:set_resp_cookie(<<"sessionid">>, SessionID, Req0,
#{http_only => true}).
cookie也可以在客户端设置,例如使用Javascript。
读取cookie
客户机只返回cookie名称和值。所有其他可以设置的选项都不会被发送回去。
Cowboy提供了两个读取cookie的功能。两者都涉及解析cookie报头,因此不应该重复调用。
你可以得到所有的cookie作为一个key/value列表:
Cookies = cowboy_req:parse_cookies(Req),
{_, Lang} = lists:keyfind(<<"lang">>, 1, Cookies).
或者,您可以对cookie执行匹配,只检索您需要的cookie,同时使用约束执行任何必需的post处理。这个函数返回一个映射:
#{id := ID, lang := Lang} = cowboy_req:match_cookies([id, lang], Req).
您可以在匹配值时使用约束来验证这些值。如果id cookie不是整数或lang cookie为空,以下代码片段将崩溃。此外,id cookie值将转换为整数项:
CookiesMap = cowboy_req:match_cookies([{id, int}, {lang, nonempty}], Req).
注意,如果两个cookie共享相同的名称,那么map值将是两个cookie值的列表。
可以提供一个默认值。如果没有找到lang cookie,将使用默认值。如果找到了cookie,但它的值为空,则不会使用它:
#{lang := Lang} = cowboy_req:match_cookies([{lang, [], <<"en-US">>}], Req).
如果没有提供默认值,且缺少该值,则抛出异常。