web登录方式/单点登录SSO/Cookie详解与安全问题

web登录方式

为什么会有登陆态

因为http协议无状态,两次请求服务器无法分辨是否为同一账号请求。登录就是用某种方法让服务器识别不同的请求都是谁发出的。

从登录到登出的过程中,服务器维护了一个可以识别用户信息的数据结构,广义上来说,这个过程叫session,就是保持了一个会话

区别于狭义的session,狭义session指的是登录成功后服务端存储的用户信息

服务端session和客户端sessionId 存储于cookie的方式

web登录方式/单点登录SSO/Cookie详解与安全问题_第1张图片

过程:

  1. 客户端带着用户名和密码去访问 /login 接口,服务器端收到后校验正确就会在服务器端存储一个sessionId和session的映射关系
  2. 服务器端返回response,并且将sessionId以set-cookie的方式种在客户端
  3. 客户端发起非登录请求时,服务端通过cookie中的sessionId找到对应的session来知道此次请求是谁发出的。
将sessionId存在cookie并不是一种强制的方案,而是大家一般都这么做,而且发请求的时候符合domain和path的时候,会自动带上cookie,省去了手动塞的过程。

token / jwt 方式

两者区别:

  • sessionId的方式本质是把用户状态信息维护在server端,cookie传输。虽然方便但有安全问题。
  • token的方式把用户信息生成一串token传给前端,前端每次发请求时带上token,传回给服务器端;服务器端收到请求之后,解析token并且验证相关信息;
  • 最本质的区别是通过解析token的计算时间换取了session的存储空间

以jwt(json web token)为例:

主要由三部分组成

header 头部 描述签名算法和token的类型,类型一般都是JWT
{
  "alg": "HS256",
  "typ": "JWT"
}
payload 负载  用户信息
{
  "sub": "1234567890",
  "name": "John Doe",
  "iat": 1516239022,
  "exp": 1555341649998
}
signature 签名  对前两部分的签名,实现需要一个密钥(secret)这个secret只有服务器才知道,然后使用header里面的算法按照如下方法来签名:
HMACSHA256(
  base64UrlEncode(header) + "." +
  base64UrlEncode(payload),
  secret)

最后的 jwt = base64url(header) + "." + base64url(payload) + "." + signature

jwt可以放在response中返回,也可以放在cookie中返回。客户端发起请求时,官方推荐放在HTTP header中:

Authorization: Bearer 

存在的问题

  • session需要存储,多机存储和用户量增多时,对存储空间有要求
  • session+cookie里面存sessionId的方式可能会有csrf攻击的问题,常见的方式是使用csrf_token来解决
  • jwt的过期时间需要结合业务做设置,而且jwt一旦派发出去,后端无法强行使其作废

跨页面登陆态同步方法

单点登录(Single Sign On),简称为 SSO.

定义是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统。

同域下的单点登录

一个企业一般情况下只有一个域名,通过二级域名区分不同的系统。比如我们有个域名叫做:a.com,同时有两个业务系统分别为:app1.a.com和app2.a.com。我们要做单点登录(SSO),需要一个登录系统,叫做:sso.a.com。

问题一:在sso.a.com登陆后,因为cookie不能跨域,所以无法在app1.a.com和app2.a.com这两个域名发送请求时携带cookie

解决方法:sso登录以后,可以将Cookie的域设置为顶域,即.a.com,这样所有子域的系统都可以访问到顶域的Cookie。

问题二:sso、app1和app2是不同的应用,它们的session存在自己的应用内,是不共享的

解决办法:把3个系统的Session共享。共享Session的解决方案有很多,例如:Spring-Session。

不同域下的单点登录

说到单点登录,就肯定会见到这个名词:CAS (Central Authentication Service)

web登录方式/单点登录SSO/Cookie详解与安全问题_第2张图片

上图是CAS官网上的标准流程,具体流程如下:

  1. 用户访问app系统,app系统是需要登录的,但用户现在没有登录。
  2. 跳转到CAS server,即SSO登录系统,以后图中的CAS Server我们统一叫做SSO系统。 SSO系统也没有登录,弹出用户登录页。
  3. 用户填写用户名、密码,SSO系统进行认证后,将登录状态写入SSO的session,浏览器(Browser)中写入SSO域下的Cookie。
  4. SSO系统登录完成后会生成一个ST(Service Ticket),然后跳转到app系统,同时将ST作为参数传递给app系统。
  5. app系统拿到ST后,从后台向SSO发送请求,验证ST是否有效。
  6. 验证通过后,app系统将登录状态写入session并设置app域下的Cookie。

app1登陆后访问app2的流程

  1. 用户访问app2系统,app2系统没有登录,跳转到SSO。
  2. 由于SSO已经登录了,不需要重新登录认证。
  3. SSO生成ST,浏览器跳转到app2系统,并将ST作为参数传递给app2。
  4. app2拿到ST,后台访问SSO,验证ST是否有效。
  5. 验证成功后,app2将登录状态写入session,并在app2域下写入Cookie。

业务系统拿ST再次访问SSO进行验证,这个步骤是为了保证安全。如果业务系统不确认一下这个用户收否是伪造的,那直接在浏览器中敲入回调地址带上用户信息即可登录。

cookie相关知识点及安全性问题

是什么,存在哪儿,怎么传输

Cookie既指整个状态保存机制,也指用户保存状态的数据本身,由String类型的name和value以及若干属性组成。

Cookie由服务端生成,保存在浏览器。通过两个Http Header:Set-Cookie和Cookie进行传输。

web登录方式/单点登录SSO/Cookie详解与安全问题_第3张图片

很多浏览器会提供读Cookie和写Cookie的api给运行在其上Javascript脚本使用,通常的api是操作docment.cookie:

    document.cookie=“SID=31d4d; domain=example.com; path=/;”;

关键属性和不同类型的cookie

Domain、Path、Name三者唯一确定一个cookie。

其它属性仅用作读写时的权限控制,不作为cookie标识。

DomainPath 标识定义了Cookie的作用域:即Cookie应该发送给哪些URL。

Domain 标识指定了哪些主机可以接受Cookie。如果不指定,默认为当前文档的主机不包含子域名)。如果指定了Domain,则一般包含子域名。

例如,如果设置 Domain=mozilla.org,则Cookie也包含在子域名中(如developer.mozilla.org)。

Path 标识指定了主机下的哪些路径可以接受Cookie(该URL路径必须存在于请求URL中)。以字符 %x2F ("/") 作为路径分隔符,子路径也会被匹配。

例如,设置 Path=/docs,则以下地址都会匹配:

  • /docs
  • /docs/Web/
  • /docs/Web/HTTP

domain向上通配,path向下通配

cookie分为会话期cookie和持久性cookie

会话期Cookie:浏览器关闭之后会被自动删除,仅在会话期内有效。不需要指定过期时间(Expires)或者有效期(Max-Age)。

持久性Cookie:可以指定一个特定的过期时间(Expires)或有效期(Max-Age)。

Set-Cookie: id=a3fWa; Expires=Wed, 21 Oct 2015 07:28:00 GMT;

提示:当Cookie的过期时间被设定时,设定的日期和时间只与客户端相关,而不是服务端。

需要注意的是,有些浏览器提供了会话恢复功能,这种情况下即使关闭了浏览器,会话期Cookie也会被保留下来,就好像浏览器从来没有关闭一样。

Cookie的有效期过长可能导致通行证泄露。比如用户使用了公用电脑,关闭浏览器时,没有点击注销。这样Cookie就留存在这台电脑上,其它人只需打开浏览器即可获取其在网站上的cookie。

一般保存通行证的cookie应该设置为session有效的cookie,并在用户选择记住登录状态时,提醒用户,不要再公用电脑上做这样的勾选。

安全问题

明文传输的HTTP流量

HTTP明文传输数据的特性,使得攻击者可从网路上抓包获取Cookie。

解决方案:

  • 服务端使用HTTPS
  • 指定cookie的secure属性,该属性使cookie只能在HTTPS请求中带出。

利用XSS漏洞读取保存在cookie的通行证

假如网站存在XSS漏洞,那么恶意JS可直接读取Cookie中的通行证。可以通过指定Cookie的HttpOnly属性。对于指定了HttpOnly的Cookie,浏览器会拒绝JS读写

XSS仍有可能利用服务端漏洞获取cookie: - 服务端有可能在请求的正常响应中包含通行证。不要笑,这真的有,尤其现在很多公司app和web共用一套后台; - 服务端可能有漏洞导致cookie包含在请求响应中,从而被窃取。比如:Apache CEV-2012-005

所以HttpOnly不是银弹,XSS也有很多其它的危害。但至少,HttpOnly可以避免通行证在浏览器被JS直接读取

跨站请求伪造(CSRF)

比如在不安全聊天室或论坛上的一张图片,它实际上是一个给你银行服务器发送提现的请求:

当你打开含有了这张图片的HTML页面时,如果你之前已经登录了你的银行帐号并且Cookie仍然有效(还没有其它验证步骤),你银行里的钱很可能会被自动转走。有一些方法可以阻止此类事件的发生:

  • 设置Cookie的SameSite属性。该属性规定cookie只会在当前正在访问(浏览器地址栏)的域名与cookie的domain可匹配时,才会带出。
  • 任何敏感操作都需要确认;
  • 用于敏感信息的Cookie只能拥有较短的生命周期;
  • 更多方法可以查看OWASP CSRF prevention cheat sheet_Prevention_Cheat_Sheet)。

参考资料:

前端应该知道的web登录

session和cookie

单点登录(SSO)看这一篇就够了

Cookie与Passport安全

HTTP cookies

你可能感兴趣的:(javascript,sso,cookie)