为什么在Restful Implementations中使用$ _SESSION不好?

时间:2010-03-09 03:54:19

标签: php performance authentication rest authorization

原始问题:

  

我读过RESTful网站的内容。使用$ _SESSION是不好的。为什么不好?那么如何在不查找数据库的情况下对用户进行适当的身份验证以检查用户的角色?


我读到使用$ _SESSION是不好的。

http://www.recessframework.org/page/towards-restful-php-5-basic-tips

我正在创建一个网站,而不是PHP中的Web服务。而我正在努力使它更加RESTful。至少在精神上。

现在我正在重写使用表单标签POST的所有操作,并添加一个名为_method的隐藏值,删除操作为“delete”,更新操作为“put”。

但是,我不确定为什么建议不要使用$ _SESSION。我想知道为什么以及如何改进。

为了便于授权检查,我做的是登录用户后,用户名存储在$ _SESSION中。

每次用户导航到某个页面时,该页面都会检查用户名是否存储在$ _SESSION中,然后根据$ _SESSION检索包括数据库权限在内的所有信息,然后评估基于以下权限访问页面的权限检索到的信息。

我实施的方式是不是很糟糕?不RESTful?我如何提高性能和安全性?

谢谢。

3 个答案:

答案 0 :(得分:8)

正如文章中所写,这条“规则”是完全无稽之谈。作者诅咒$_SESSION,但对存储身份验证信息的cookie完全没问题。他接着说:

  

如果您需要的不仅仅是cookie的数据,请将其存储在中央数据库中,并且身份验证仍在cookie中。

将会话中的数据与cookie中的令牌一起存储,并将数据存储在cookie中的身份验证数据库之间有什么区别?除了使用令牌之外,没有任何区别,您不会在每次请求时以明文形式传输身份验证数据。

与每个请求一起传输附加信息与传输表示其他数据的令牌之间没有区别,但需要通过服务器上的会话解决。这只是安全性和实用性的问题。

论证通常是服务器应该是“无状态的”。由于RESTfulness与HTTP协议有关,“无状态”并不意味着“服务器不存储任何状态”。从协议的角度来看,无状态意味着我可以按任意顺序发出任意数量的请求,并且我会收到相同请求的相同资源

GET  /index.html
POST /someaction
GET  /index.html  -> should return the same *resource* as before

与真实的状态保持协议(如FTP)对比:

LS       -> gets list of files in current directory
CD /dir  -> changes directory, i.e. changes state
LS       -> same command gets list of files for a different directory

这是RESTful协议和状态保持协议之间的真正区别。服务器是否存储与用户有关的任何数据完全是服务器的实现细节,与RESTfulness无关。如果服务器返回相同的资源作为对完全相同的请求的响应,则无论在其间发生了什么类型的请求,它都是无状态的,因此是RESTful。

这与身份验证或存储其他数据无关,也不排除请求或URL最终可能会过期。

如果网址/请求执行过期,则有一种特殊方法可以使用HTTP来处理:使用适当的状态代码进行响应。如果用户发送的请求包含已过期的令牌/登录信息,则服务器应该使用所请求网址的登录屏幕进行回答。这会违反RESTfulness。

不是RESTful:

GET /restricted/page

200 OK

Please log in here:
Name: _____
Password: _____

----------------------

POST /restricted/page
[name, password]

200 OK

Content of restricted page.

----------------------

GET /restricted/page

200 OK

Content of restricted page.

<强>的RESTful:

GET /restricted/page

401 Unauthorized

GET /restricted/page

307 Temporary Redirect
Location: /login

----------------------

GET /login

200 OK

----------------------

POST /login
[name, password]

307 Temporary Redirect
Location: /restricted/page

----------------------

GET /restricted/page

200 OK

这不会“替换”资源 /restricted/page,就像糟糕的例子那样,保持服务器RESTful。 正确地向客户发出请求有效的信号,而不是现在。请注意,始终使用术语 resource ,而不是响应。服务器以不同的方式响应是可以的,但是在同一个URL上提供不同的资源(内容*)是不可取的。如果是这种情况,客户端还需要跟踪会话的当前状态(如FTP),以便能够分辨出正在发生的事情。无状态更多的是客户端无状态而不是服务器。它并不妨碍服务器跟踪客户端正在做什么。


*)请注意,内容不等同于资源。可以更改和更新资源的内容。

进一步注意,反对使用$_SESSION的正当理由,最显着的是跨多个服务器的可扩展性。保持服务器RESTful 是一个正当理由。如果您需要任何类型的状态,例如过期登录或购物篮,您需要在某处跟踪该信息。服务器会话与cookie一样有效,在许多情况下是更好的选择。是否使用$_SESSION或数据库或笔和纸实现该会话是一个实现细节。

答案 1 :(得分:1)

通常实现的会话不是RESTful,因为它们只在客户端存储一个小令牌,而客户端的实际“状态”(登录,购物车内容等)存储在服务器上。 REST要求Web遵循它的“无状态”原始设计,这意味着每个请求都与其他任何请求相同 - 服务器不必跟踪任何事情。

如果所有数据都存储在cookie中 - 实际数据,而不仅仅是令牌 - 可以与REST保持一致。我倾向于让服务器将所有状态作为加密文本块返回给客户端,在下次调用时由服务器解密以确认用户已登录,购物车中的内容等等。

答案 2 :(得分:1)

您发布的链接提供了一个解决方案:

  

实际上这意味着存储   cookie中的身份验证信息   带有时间戳和校验和。

但我个人不同意校验和就足够了。我更喜欢身份验证cookie包含时间戳,原始登录IP(以防止cookie劫持)并使用站点密钥完全加密。