专栏介绍
SSO单点登录专栏主要对比浏览器-服务端会话机制,阐述实现思路,结合在项目中应用单点登录引发的总结和思考,后续也会不断更新其他实用的知识点~
引言
我们知道,web应用采用browser/server架构,采用http作为通信协议。http是无状态协议,浏览器的每一次请求,都会被服务器独立处理。
但项目的某些资源或请求并不是每个用户都能去访问,需要保存浏览器会话对象。Cookie机制应运而生。
Cookie机制
cookie是浏览器用来存储少量数据的一种机制,数据以”key/value“形式存储,浏览器发送http请求时会自动附带cookie信息。
大体流程
- 浏览器在第一次访问后台服务器的时候,后台服务器会在服务端创建session对象,并存储到map中。key是session的id【JSESSIONID】,value是session对象本身.
- 服务端在响应后会把session的id通过cookie的方式写到客户端浏览器中.
而浏览器会把JSESSIONID写入到本地的cookie中. - 在后续的请求中,都会读取本地的cookie中的内容,并在请求的时候带上对应的cookie。即“一次登录,”
- 服务端可以通过cookie中的JSESSIONID,找到对应的session对象,相当于找到了浏览器那边的登录状态和身份信息,这样就实现了保持登录状态的作用
我们可以在服务器端通过这样的设置指定cookie
HttpSession session = req.getSession();
session.setAttribute("userId", user.getId());
//获取sessionid
String sessionid = session.getId();
//new一个cookie,cookie的名字是JSESSIONID跟带id的cookie一样
Cookie cookie = new Cookie("JSESSIONID", sessionid);
//设置cookie应用范围。getContextPath是获取当前项目的名字。
cookie.setPath(req.getContextPath());
// 以秒为单位 设置为1天有效
cookie.setMaxAge(60 * 60 * 24);
//用这个cookie把带id的cookie覆盖掉
resp.addCookie(cookie);
使用Cookie通常会带来以下问题
- 登录状态保存时间
- 跨域问题
- 安全问题
- 内存占用
下面我们来逐一论证一下
登录状态
默认情况下 session保存的有效时间为30min 当然 我们可以通过修改有效时间达到诸如7天免登录的效果
cookie.setMaxAge(60 * 60 * 24);
也可以主动销毁session会话 也就是我们常说的登出
req.getSession().invalidate();
也就是 登录状态可以由我们开发人员简单的设定 就可以实现对登录状态的掌控
跨域问题
cookie携带会话id在浏览器与服务器之间维护会话状态,但cookie会局限于当前网站的域名。相当于每个网页都可以有对应的cookie,但彼此互不相通。
早期工程师多采用同域名共享cookie的方式实现多系统登录。比如设置分级域名如a.baidu.com,映射到顶级域名baidu.com上
可以在cookie中设置域名
cookie.setDomain(“baidu.com”);
但同时 也带来其他方面的困扰 比如
- 需要在主域名上解析出子域名,但同时也使耦合度更高
- 各集群服务器要采用同种形式的cookie机制 比如tomcat的key为JSESSIONID 不然可能无法通过其他服务器产生的有效cookie
- 无法实现跨语言平台 只能使用同种语言
安全问题
cookie本身不安全 有CRSF攻击风险
关于CRSF理解
- 跨站请求伪造
跨站请求伪造(英语: Cross-site requestforgery),也被称为 one-clickattack 或者 session riding,通常缩写为 CSRF 或者 XSRF,是一种挟制用户在当前已登录的 Web 应用程序上执行非本意的操作的攻击方法。跟跨网站脚本 (XSS)相比,XSS利用的是用户对指定网站的信任,CSRF 利用的是网站对用户网页浏览器的信任。“ - 跨站请求攻击
跨站请求攻击,简单地说,是攻击者通过一些技术手段欺骗用户的浏览器去访问一个 I自己曾经认证过的网站并运行一些操作(如发邮件,发消息,甚至财产操作如转账和购买商品)。由于浏览器曾经认证过,所以被访问的网站会认为是真正的用户操作而去运行。相当于拿到别人的cookie,就拿到了别人的身份证 “为所欲为”。
CRSF利用了 web 中用户身份验证的一个漏洞: 简单的身份验证只能保证请求发自某个用户的浏览器,却不能保证请求本身是用户自愿发出的。”
内存占用
- 服务端需要存储session,占用内存高
- 不同服务器,无法共享session【分布式的场景】,这种情况下通常需要借助redis等数据库来做存储
下篇预告
本篇主要讲述传统会话机制的弊端 下篇将带来SSO的简介和实现思路 我们下篇再见~