http 3 web session management methods

HTTP is stateless. When a request ends, the connection is disconnected. The next time the server receives a request, it does not know which user sent the request. Of course it knows which client address is sent from, but for our application, we rely on the user to manage, not the client. So for our application, it needs state management, so that the server can know exactly which user initiated the http request, so as to determine whether he has permission to continue the request. This process is often referred to as session management. It can also be simply understood as a period from when a user logs in to exit the application. This article summarizes 3 common ways to implement web application session management:

1) Based on server-side session management

2) How to manage cookie-base

3) How to manage token-base

These contents can help deepen the understanding of the user login mechanism in the web, and also have reference value for actual project development. Welcome to read and correct.

1. Based on server-side session management

In early web applications, server-side sessions were usually used to manage user sessions. Quickly understand the server session:

1) The server session is an object created by the server when the user accesses the application for the first time, representing a session of the user and can be used to store data. The server assigns a unique sessionid to each session to ensure that each user has a different session object.

2) After the server creates the session, it will return the sessionid to the user's browser through the cookie, so that when the user sends a request to the server for the second time or later, the sessionid will be sent back to the server through the cookie, so that the server can The session object corresponding to the user can be found according to the sessionid.

3) The session usually has an expiration time setting, such as 2 hours. When the expiration time expires, the server will destroy the previous session and create a new session to return to the user. However, as long as the user sends a new request to the server within the expiration time, usually the server will extend the expiration time of his corresponding session by another 2 hours according to the current request time.

4) Session does not have the function of session management at the beginning. It can only be used to manage the session after the user's login authentication is successful, and the user's successful login credentials are put into the session object. The logic of managing sessions is also very simple. As long as you get the user's session object and see if there is a successful login credential in it, you can determine whether the user has logged in. When the user actively logs out, the login credentials in its session object will be cleared. Therefore, before the user logs in or after logging out, or when the session object fails, the required login credentials must not be obtained.

The above process can be simply described using a flowchart as follows: 
image

Mainstream web development platforms (java, .net, php) natively support this method of session management, and it is very simple to develop. I believe that most back-end developers know and use it when they get started. It also has a big advantage of good security, because the medium for maintaining the session state between the browser and the server is always a sessionid string. As long as the string is random enough, an attacker cannot easily pretend to be someone else's sessionid to operate; Unless the method of CSRF or http hijacking is used, it is possible to pretend to be someone else to operate; even if the impersonation is successful, the impersonated user session must contain valid login credentials. But before you really decide to use it to manage sessions, you have to consider the following issues according to your application:

1) In this way, the session information is stored in the web server, so when the user is online at the same time, the session information will occupy more memory;

2) When the application is deployed in a cluster, it will encounter the problem of how to share sessions between multiple web servers. Because the session is created by a single server, but the server processing the user request is not necessarily the server that created the session, so he can't get information such as login credentials that have been put into the session before;

3) When multiple applications want to share sessions, in addition to the above problems, they will also encounter cross-domain problems, because different applications may be deployed on different hosts, and cross-domain cookie processing needs to be done in each application.

For problem 1 and problem 2, the solution I have seen is to use an intermediate server such as redis to manage the addition, deletion, modification and checking of sessions, which reduces the burden on the web server and solves the problem of session sharing between different web servers. For problem 3, since the session on the server side relies on cookies to transmit sessionid, in actual projects, it is only necessary to solve how to implement cross-domain cookie access of sessionid in each project. This can be achieved, but it is more troublesome, and it is possible for the front and back ends. have to be dealt with.

If the above three issues are not considered, this management method is worth using, especially for some small web applications. But once the application needs to be extended in the future, the first three issues must be treated with caution. If you really want to use this method in a project, it is recommended to use it in conjunction with a single sign-on framework such as CAS, which will make the application more scalable.

2. cookie-based management

Since the former method will increase the burden on the server and the complexity of the architecture, someone later came up with a scheme to directly store the user's login credentials to the client. When the user logs in successfully, the login credentials are written into the cookie, and the Set a validity period for the cookie, and subsequent requests can directly verify whether the cookie with the login credentials exists and whether the credentials are valid to determine the user's login status. The overall flow of using it to implement session management is as follows:

1) The user initiates a login request, and the server verifies whether the user meets the login conditions according to the incoming identity information such as the user password. If so, it creates a login credential based on the user information. This login credential is simply an object. In its simplest form, it can contain only three values: user id, credential creation time and expiration time.

2) The server uses the login credential created in the previous step, first digitally signs it, and then encrypts it with a symmetric encryption algorithm, and writes the signed and encrypted string into the cookie. The name of the cookie must be fixed (such as ticket), because when you get it later, you have to get the cookie value based on this name. The purpose of adding a digital signature in this step is to prevent the information in the login credentials from being tampered with, because once the information is tampered with, the signature verification in the next step will definitely fail. The purpose of encryption is to prevent the user information from being easily read when the cookie is intercepted by others.

3)用户登录后发起后续请求,服务端根据上一步存登录凭证的cookie名字,获取到相关的cookie值。然后先做解密处理,再做数字签名的认证,如果这两步都失败,说明这个登录凭证非法;如果这两步成功,接着就可以拿到原始存入的登录凭证了。然后用这个凭证的过期时间和当前时间做对比,判断凭证是否过期,如果过期,就需要用户再重新登录;如果未过期,则允许请求继续。

image

这种方式最大的优点就是实现了服务端的无状态化,彻底移除了服务端对会话的管理的逻辑,服务端只需要负责创建和验证登录cookie即可,无需保持用户的状态信息。对于第一种方式的第二个问题,用户会话信息共享的问题,它也能很好解决:因为如果只是同一个应用做集群部署,由于验证登录凭证的代码都是一样的,所以不管是哪个服务器处理用户请求,总能拿到cookie中的登录凭证来进行验证;如果是不同的应用,只要每个应用都包含相同的登录逻辑,那么他们也是能轻易实现会话共享的,不过这种情况下,登录逻辑里面数字签名以及加密解密要用到的密钥文件或者密钥串,需要在不同的应用里面共享,总而言之,就是需要算法完全保持一致。

这种方式由于把登录凭证直接存放客户端,并且需要cookie传来传去,所以它的缺点也比较明显:

1)cookie有大小限制,存储不了太多数据,所以要是登录凭证存的消息过多,导致加密签名后的串太长,就会引发别的问题,比如其它业务场景需要cookie的时候,就有可能没那么多空间可用了;所以用的时候得谨慎,得观察实际的登录cookie的大小;比如太长,就要考虑是非是数字签名的算法太严格,导致签名后的串太长,那就适当调整签名逻辑;比如如果一开始用4096位的RSA算法做数字签名,可以考虑换成1024、2048位;

2)每次传送cookie,增加了请求的数量,对访问性能也有影响;

3)也有跨域问题,毕竟还是要用cookie。

相比起第一种方式,cookie-based方案明显还是要好一些,目前好多web开发平台或框架都默认使用这种方式来做会话管理,比如php里面yii框架,这是我们团队后端目前用的,它用的就是这个方案,以上提到的那些登录逻辑,框架也都已经封装好了,实际用起来也很简单;asp.net里面forms身份认证,也是这个思路,这里有一篇好文章把它的实现细节都说的很清楚:

http://www.cnblogs.com/fish-li/archive/2012/04/15/2450571.html

前面两种会话管理方式因为都用到cookie,不适合用在native app里面:native app不好管理cookie,毕竟它不是浏览器。这两种方案都不适合用来做纯api服务的登录认证。要实现api服务的登录认证,就要考虑下面要介绍的第三种会话管理方式。

3. token-based的管理方式

这种方式从流程和实现上来说,跟cookie-based的方式没有太多区别,只不过cookie-based里面写到cookie里面的ticket在这种方式下称为token,这个token在返回给客户端之后,后续请求都必须通过url参数或者是http header的形式,主动带上token,这样服务端接收到请求之后就能直接从http header或者url里面取到token进行验证:

image

这种方式不通过cookie进行token的传递,而是每次请求的时候,主动把token加到http header里面或者url后面,所以即使在native app里面也能使用它来调用我们通过web发布的api接口。app里面还要做两件事情:

1)有效存储token,得保证每次调接口的时候都能从同一个位置拿到同一个token;

2)每次调接口的的代码里都得把token加到header或者接口地址里面。

看起来麻烦,其实也不麻烦,这两件事情,对于app来说,很容易做到,只要对接口调用的模块稍加封装即可。

这种方式同样适用于网页应用,token可以存于localStorage或者sessionStorage里面,然后每发ajax请求的时候,都把token拿出来放到ajax请求的header里即可。不过如果是非接口的请求,比如直接通过点击链接请求一个页面这种,是无法自动带上token的。所以这种方式也仅限于走纯接口的web应用。

这种方式用在web应用里也有跨域的问题,比如应用如果部署在a.com,api服务部署在b.com,从a.com里面发出ajax请求到b.com,默认情况下是会报跨域错误的,这种问题可以用CORS(跨域资源共享)的方式来快速解决,相关细节可去阅读前面给出的CORS文章详细了解。

这种方式跟cookie-based的方式同样都还有的一个问题就是ticket或者token刷新的问题。有的产品里面,你肯定不希望用户登录后,操作了半个小时,结果ticket或者token到了过期时间,然后用户又得去重新登录的情况出现。这个时候就得考虑ticket或token的自动刷新的问题,简单来说,可以在验证ticket或token有效之后,自动把ticket或token的失效时间延长,然后把它再返回给客户端;客户端如果检测到服务器有返回新的ticket或token,就替换原来的ticket或token。

4. 安全问题

在web应用里面,会话管理的安全性始终是最重要的安全问题,这个对用户的影响极大。

首先从会话管理凭证来说,第一种方式的会话凭证仅仅是一个session id,所以只要这个session id足够随机,而不是一个自增的数字id值,那么其它人就不可能轻易地冒充别人的session id进行操作;第二种方式的凭证(ticket)以及第三种方式的凭证(token)都是一个在服务端做了数字签名,和加密处理的串,所以只要密钥不泄露,别人也无法轻易地拿到这个串中的有效信息并对它进行篡改。总之,这三种会话管理方式的凭证本身是比较安全的。

然后从客户端和服务端的http过程来说,当别人截获到客户端请求中的会话凭证,就能拿这个凭证冒充原用户,做一些非法操作,而服务器也认不出来。这种安全问题,可以简单采用https来解决,虽然可能还有http劫持这种更高程度的威胁存在,但是我们从代码能做的防范,确实也就是这个层次了。

最后的安全问题就是CSRF(跨站请求伪造)。这个跟代码有很大关系,本质上它就是代码的漏洞,只不过一般情况下这些漏洞,作为开发人员都不容易发现,只有那些一门心思想搞些事情的人才会专门去找这些漏洞,所以这种问题的防范更多地还是依赖于开发人员对这种攻击方式的了解,包括常见的攻击形式和应对方法。不管凭证信息本身多么安全,别人利用CSRF,就能拿到别人的凭证,然后用它冒充别人进行非法操作,所以有时间还真得多去了解下它的相关资料才行。举例来说,假如我们把凭证直接放到url后面进行传递,就有可能成为一个CSRF的漏洞:当恶意用户在我们的应用内上传了1张引用了他自己网站的图片,当正常的用户登录之后访问的页面里面包含这个图片的时候,由于这个图片加载的时候会向恶意网站发送get请求;当恶意网站收到请求的时候,就会从这个请求的Reffer header里面看到包含这个图片的页面地址,而这个地址正好包含了正常用户的会话凭证;于是恶意用户就拿到了正常用户的凭证;只要这个凭证还没失效,他就能用它冒充用户进行非法操作。

5. 总结

前面这三种方式,各自有各自的优点及使用场景,我觉得没有哪个是最好的,做项目的时候,根据项目将来的扩展情况和架构情况,才能决定用哪个是最合适的。本文的目的也就是想介绍这几种方式的原理,以便掌握web应用中登录验证的关键因素。

As a front-end developer, although this article introduces three methods of session management, the third method is most closely related to the front-end. After all, front-end development of SPA applications and hybrid applications has become very popular, so master this method. The authentication process and usage are obviously very helpful for the front end. Fortunately, the technology of this method has been implemented for a long time, and there is a ready-made standard available. This standard is JWT (json-web-token).

JWT itself does not do any technical implementation, it just defines how to implement the token-based management method, it specifies the standard content that the token should contain, and the token generation process and method. At present, there are many technologies that implement this standard:

image

More can be found here: https://jwt.io/#libraries-io

In order to have a more comprehensive understanding of the implementation of the third session management method, I choose to use express and jsonwebtoken in many of the above JWT implementations to study. I will introduce the relevant content in detail in the next blog. This concludes the content of this article, thank you for reading, and welcome to pay attention to the content of the next blog.

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=326583133&siteId=291194637