• 【夯实基础】-浅谈"单点登录"的几种实现方式


    单点登录

    一、Session跨域

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

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

    二、Spring Session共享

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

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

    三、Nginx Session共享

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

    upstream nginx.example.com
    {
        server 127.0.0.1:8080;
        server 127.0.0.1:808;
        ip_hash;
    }
    
    server
    {
        listen 80;
        location /
        {
            proxy_pass
            http://nginx.example.com;
            proxy_set_header Host  $http_host;
            proxy_set_header Cookie $http_cookie;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
            client_max_body_size  100m;
        }
    }

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

    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操作。

    五、JSON Web Token(JWT)机制

    JWT是一种紧凑且自包含的,用于在多方传递JSON对象的技术。传递的数据可以使用数字签名增加其安全行。可以使用HMAC加密算法或RSA公钥/私钥加密方式。

    紧凑:数据小,可以通过URL,POST参数,请求头发送。且数据小代表传输速度快。

    自包含:使用payload数据块记录用户必要且不隐私的数据,可以有效的减少数据库访问次数,提高代码性能。

    JWT一般用于处理用户身份验证或数据信息交换。

    用户身份验证:一旦用户登录,每个后续请求都将包含JWT,允许用户访问该令牌允许的路由,服务和资源。单点登录是当今广泛使用JWT的一项功能,因为它的开销很小,并且能够轻松地跨不同域使用。

    数据信息交换:JWT是一种非常方便的多方传递数据的载体,因为其可以使用数据前面来保证数据的有效性和安全性。

    1. JWT数据结构

    JWT的数据结构是 : A.B.C。 由字符点‘.’来分隔三部分数据。

    A - header 头信息

    B - payload (有效荷载?)

    C - Signature 签名

    1.1      header

    数据结构: {“alg”: “加密算法名称”, “typ” : “JWT”}

    alg是加密算法定义内容,如:HMAC SHA256 或 RSA

    typ是token类型,这里固定为JWT。

    1.2 payload

    在payload数据块中一般用于记录实体(通常为用户信息)或其他数据的。主要分为三个部分,分别是:已注册信息(registered claims),公开数据(public claims),私有数据(private claims)。

    payload中常用信息有:iss(发行者),exp(到期时间),sub(主题),aud(受众)。前面列举的都是已注册信息。

    公开数据部分一般都会在JWT注册表中增加定义。避免和已注册信息冲突。

    公开数据和私有数据可以由程序员任意定义。

    注意:即使JWT有签名加密机制,但是payload内容都是明文记录,除非记录的是加密数据,否则不排除泄露隐私数据的可能。不推荐在payload中记录任何敏感数据。

    1.3 Signature

    签名信息。这是一个由开发者提供的信息。是服务器验证的传递的数据是否有效安全的标准。在生成JWT最终数据的之前。先使用header中定义的加密算法,将header和payload进行加密,并使用点进行连接。如:加密后的head.加密后的payload。再使用相同的加密算法,对加密后的数据和签名信息进行加密。得到最终结果。

    2. JWT执行流程

    六、基于JWT机制的单点登录

    1. 实现

    详见代码

    2. 注意

    使用JWT实现单点登录时,需要注意token时效性。token是保存在客户端的令牌数据,如果永久有效,则有被劫持的可能。token在设计的时候,可以考虑一次性有效或一段时间内有效。如果设置有效时长,则需要考虑是否需要刷新token有效期问题。

    3.  token保存位置

    使用JWT技术生成的token,客户端在保存的时候可以考虑cookie或localStorage。cookie保存方式,可以实现跨域传递数据。localStorage是域私有的本地存储,无法实现跨域。

    4. webstorage

    webstorage可保存的数据容量为5M。且只能存储字符串数据。

    webstorage分为localStorage和sessionStorage。

    localStorage的生命周期是永久的,关闭页面或浏览器之后localStorage中的数据也不会消失。localStorage除非主动删除数据,否则数据永远不会消失。

    sessionStorage是会话相关的本地存储单元,生命周期是在仅在当前会话下有效。sessionStorage引入了一个“浏览器窗口”的概念,sessionStorage是在同源的窗口中始终存在的数据。只要这个浏览器窗口没有关闭,即使刷新页面或者进入同源另一个页面,数据依然存在。但是sessionStorage在关闭了浏览器窗口后就会被销毁。同时独立的打开同一个窗口同一个页面,sessionStorage也是不一样的。

    七、Restful接口设计

    1. Rest简述

    REST(英文:Representational State Transfer,简称REST)描述了一个架构样式的网络系统,比如 web 应用程序。它首次出现在 2000 年 Roy Fielding 的博士论文中,他是 HTTP 规范的主要编写者之一。在目前主流的三种Web服务交互方案中,REST相比于SOAP(Simple Object Access protocol,简单对象访问协议)以及XML-RPC更加简单明了,无论是对URL的处理还是对Payload的编码,REST都倾向于用更加简单轻量的方法设计和实现。值得注意的是REST并没有一个明确的标准,而更像是一种设计的风格。

    2. Restful简述

    对应的中文是rest式的;Restful web service是一种常见的rest的应用,是遵守了rest风格的web服务;rest式的web服务是一种ROA(The Resource-Oriented Architecture)(面向资源的架构).

    3. Restful特性

    3.1 普通架构

    每次请求的接口或者地址,都在做描述,例如查询的时候用了query,新增的时候用了save。如:

    http://127.0.0.1/user/query/1  GET 根据用户id查询用户数据

    http://127.0.0.1/user/save  POST 新增用户

    3.2  Restful架构

    使用get请求,就是查询.使用post请求,就是新增的请求,意图明显,没有必要做描述,这就是restful。

    http://127.0.0.1/user/1  GET 根据用户id查询用户数据

    http://127.0.0.1/user  POST 新增用户

    3.3  Restful操作方式

    HTTP方法

    资源操作

    幂等性

    是否安全

    GET

    查询

    POST

    新增

    PUT

    修改

    DELETE

    删除

    幂等性:多次访问,结果资源状态是否相同

    安全:访问是否会变更服务器资源状态

    3.4  响应状态码

    编码

    HTTP方法

    响应体内容

    描述

    200

    get/put

    资源数据

    操作成功

    201

    post

    源数据

    创建成功

    202

    post/put/delete

    请求已接受

    204

    delete/put

    请求已处理,无返回数据

    301

    get

    link 链接

    资源已被移除

    303

    get

    link

    重定向

    304

    get

    资源没有被修改

    400

    get/post/put/delete

    错误提示消息

    参数错误(缺少,格式错误等)

    401

    get/post/put/delete

    错误提示消息

    未授权

    403

    get/post/put/delete

    错误提示消息

    访问受限、授权过期

    404

    get/post/put/delete

    错误提示消息

    资源、服务未找到

    405

    get/post/put/delete

    错误提示消息

    不允许的HTTP方法

    409

    get/post/put/delete

    错误提示消息

    资源冲突或资源被锁定

    415

    get/post/put/delete

    错误提示消息

    不支持的数据类型或媒体类型

    429

    get/post/put/delete

    错误提示消息

    请求过多被限制

    500

    get/post/put/delete

    错误提示消息

    系统错误

    501

    get/post/put/delete

    错误提示消息

    接口未实现

    4. SpringMVC使用Restful实例

    详见代码

    八、接口安全机制

    1. DES加密

    2. AES加密

  • 相关阅读:
    一个简单的进程察看器
    查找素数的程序
    两种动态创建对象的方法
    我对企业管理信息系统的看法
    下定决心,准备买dopod535,做基于M$ smartphone 2003(ce.net 4.2)的开发了
    工作流中对于事务处理的思考
    第二次安装.net2005地感受
    贴一个Microsoft Business Framework的图片上来,可能有些兄弟还不知道。
    SizeOf与Structure与Managed Code
    校园招聘技术面试方面的小题目
  • 原文地址:https://www.cnblogs.com/juihai/p/11835057.html
Copyright © 2020-2023  润新知