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

Kim*_*cks 2 php authentication rest performance authorization

原始问题:

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


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

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

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

现在我正在重写使用Form标签POST的所有操作,并添加一个名为_method的隐藏值,删除操作将为"delete",更新操作将为"put".

但是,我不确定为什么建议不要使用$ _SESSION.我想知道为什么以及我该怎么做才能改进.

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

每当用户导航到页面时,页面将检查用户名是否存储在$ _SESSION中,然后基于$ _SESSION检索包括数据库特权在内的所有信息,然后根据检索到的信息评估访问页面的授权.

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

谢谢.

dec*_*eze 8

正如文章中所写,这条"规则" 完全胡说八道.作者很诅咒$_SESSION,但对存储身份验证信息的cookie完全没问题.他继续说:

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

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

在每个请求中传输附加信息与发送代表附加数据的令牌之间没有区别,但需要通过服务器上的会话来解决.这只是安全性和实用性的问题.

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

GET  /index.html
POST /someaction
GET  /index.html  -> should return the same *resource* as before
Run Code Online (Sandbox Code Playgroud)

与使用真实的状态保持协议(如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
Run Code Online (Sandbox Code Playgroud)

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

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

如果网址/请求到期了,有来处理HTTP使用一种特殊的方式,即用合适的状态码响应.如果用户发送带有过期令牌/登录的请求,则服务器应该使用所请求URL的登录屏幕进行应答.这会违反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.
Run Code Online (Sandbox Code Playgroud)

REST风格:

GET /restricted/page

401 Unauthorized
Run Code Online (Sandbox Code Playgroud)

要么

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
Run Code Online (Sandbox Code Playgroud)

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


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

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