单点登录

单点登录

  多系统,单一位置登录,实现多系统同时登录的一种技术。常出现在互联网应用和企业级平台中。

  如:京东。单点登录一般是用于互相授信的系统,实现单一位置登录,全系统有效的。三方登录:某系统,使用其他系统的用户,实现本系统登录的方式。如,在京东中使用微信登录。解决信息孤岛和用户不对等的实现方案。

  实现单点登录主要有以下几种方式:

一、Session跨域

  所谓Session 跨域就是摒弃了系统(Tomcat)提供的Session,而使用自定义的类似Session的机制来保存客户端数据的一种解决方案。

  如:通过设置cookie 的domain 来实现cookie 的跨域传递。在cookie 中传递一个自定义的session_id。这个session_id 是客户端的唯一标记。将这个标记作为key,将客户端需要保存的数据作为value,在服务端进行保存(数据库保存或NoSQL 保存)。这种机制就是Session的跨域解决。

  什么跨域: 客户端请求的时候,请求的服务器,不是同一个IP,端口,域名,主机名的时候,都称为跨域。

  什么是域:在应用模型,一个完整的,有独立访问路径的功能集合称为一个域。如:百度称为一个应用或系统。百度下有若干的域,如:搜索引擎(www.baidu.com),百度贴吧(tie.baidu.com),百度知道(zhidao.baidu.com),百度地图(map.baidu.com)等。域信息,有时也称为多级域名。域的划分: 以IP,端口,域名,主机名为标准,实现划分。

  例如:让位于a.taotao.com的服务器能够读取b.taotao.com设置的cookie值。如果b.taotao.com的页面创建的cookie把 它的path属性设置为”/”,把domain属性设置成”.taotao.com”,那么所有位于b.taotao.com的网页和所有位于 a.taotao.com的网页,以及位于taotao.com域的其他服务器上的网页都可以访问(或者说是得到)这个cookie。

  使用cookie 跨域共享,是session 跨域的一种解决方案。jsessionid 是和servlet 绑定的httpsession 的唯一标记。

  cookie 应用- new Cookie("", "").

  request.getCookies() -> cookie[] -> 迭代找到需要使用的cookie

  response.addCookie().

  cookie.setDomain() - 为cookie 设定有效域范围。

  cookie.setPath() - 为cookie 设定有效URI 范围。

二、SpringSession共享

  spring-session 技术是spring 提供的用于处理集群会话共享的解决方案。spring-session技术是将用户session 数据保存到三方存储容器中,如:mysql,redis 等。

Spring-session 技术是解决同域名下的多服务器集群session 共享问题的。不能解决跨域session 共享问题。

  使用: 配置一个Spring 提供的Filter,实现数据的拦截保存,并转换为spring-session需要的会话对象。必须提供一个数据库的表格信息( 由spring-session 提供, 找spring-session-jdbc.jar/org/springframework/session/jdbc/*.sql, 根据具体的数据库找对应的SQL 文件,做表格的创建)。

  spring-session 表:保存客户端session 对象的表格。

  spring-session-attributes 表:保存客户端session 中的attributes 属性数据的表格。

  spring-session 框架,是结合Servlet 技术中的HTTPSession 完成的会话共享机制。在代码中是直接操作HttpSession 对象的。

三、Nginx Session共享

  nginx 中的ip_hash 技术能够将某个ip 的请求定向到同一台后端,这样一来这个ip 下的某个客户端和某个后端就能建立起稳固的session,ip_hash 是在upstream 配置中定义的,具体如下:

 1 upstream nginx.example.com
 2 {
 3   server 127.0.0.1:8080;
 4   server 127.0.0.1:808;
 5   ip_hash;
 6 }
 7 server
 8 {
 9   listen 80;
10   location /
11   {
12     proxy_pass
13     http://nginx.example.com;
14     proxy_set_header Host $http_host;
15     proxy_set_header Cookie $http_cookie;
16     proxy_set_header X-Real-IP $remote_addr;
17     proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
18     proxy_set_header X-Forwarded-Proto $scheme;
19     client_max_body_size 100m;
20   }
21 }

  ip_hash 是容易理解的,但是因为仅仅能用ip 这个因子来分配后端,因此ip_hash 是有缺陷的,不能在一些情况下使用:

  nginx 不是最前端的服务器。ip_hash 要求nginx 一定是最前端的服务器,否则nginx 得不到正确ip,就不能根据ip作hash。譬如使用的是squid 为最前端,那么nginx 取ip 时只能得到squid 的服务器ip 地址,用这个地址来作分流是肯定错乱的。

  nginx 的后端还有其它方式的负载均衡。假如nginx 后端又有其它负载均衡,将请求又通过另外的方式分流了,那么某个客户端的请求肯定不能定位到同一台session 应用服务器上。

四、Token机制

1,传统身份认证

  HTTP 是一种没有状态的协议,也就是它并不知道是谁是访问应用。这里我们把用户看成是客户端,客户端使用用户名还有密码通过了身份验证,不过下回这个客户端再发送请求时候,还得再验证一下。

  解决的方法就是,当用户请求登录的时候,如果没有问题,我们在服务端生成一条记录,这个记录里可以说明一下登录的用户是谁,然后把这条记录的ID 号发送给客户端,客户端收到以后把这个ID 号存储在Cookie 里,下次这个用户再向服务端发送请求的时候,可以带着这个Cookie ,这样服务端会验证一个这个Cookie 里的信息,看看能不能在服务端这里找到对应的记录,如果可以,说明用户已经通过了身份验证,就把用户请求的数据返回给客户端。

  上面说的就是Session,我们需要在服务端存储为登录的用户生成的Session ,这些Session 可能会存储在内存,磁盘,或者数据库里。我们可能需要在服务端定期的去清理过期的Session 。

  这种认证中出现的问题是:

  Seesion:每次认证用户发起请求时,服务器需要去创建一个记录来存储信息。当越来越多的用户发请求时,内存的开销也会不断增加。

  可扩展性:在服务端的内存中使用Seesion 存储登录信息,伴随而来的是可扩展性问题。

  CORS(跨域资源共享):当我们需要让数据跨多台移动设备上使用时,跨域资源的共享会是一个让人头疼的问题。在使用Ajax 抓取另一个域的资源,就可以会出现禁止请求的情况。

  CSRF(跨站请求伪造):用户在访问银行网站时,他们很容易受到跨站请求伪造的攻击,并且能够被利用其访问其他的网站。

  在这些问题中,可扩展性是最突出的。因此我们有必要去寻求一种更有行之有效的方法。

2,Token身份认证

  使用基于Token 的身份验证方法,在服务端不需要存储用户的登录记录。大概的流程是这样的:

  客户端使用用户名、密码请求登录

  服务端收到请求,去验证用户名、密码

  验证成功后,服务端会签发一个Token,再把这个Token 发送给客户端

  客户端收到Token 以后可以把它存储起来,比如放在Cookie 里或者Local Storage 里

  客户端每次向服务端请求资源的时候需要带着服务端签发的Token

  服务端收到请求,然后去验证客户端请求里面带着的Token,如果验证成功,就向客户

  端返回请求的数据

  使用Token 验证的优势:无状态、可扩展

  在客户端存储的Tokens 是无状态的,并且能够被扩展。基于这种无状态和不存储Session信息,负载负载均衡器能够将用户信息从一个服务传到其他服务器上。安全性请求中发送token 而不再是发送cookie 能够防止CSRF(跨站请求伪造)。即使在客户端使用cookie 存储token,cookie 也仅仅是一个存储机制而不是用于认证。不将信息存储在Session中,让我们少了对session 操作。

原文地址:https://www.cnblogs.com/guanghe/p/10911492.html