我对delphi不太满意,但是基于一些示例,我设法创建了一个不超过10个用户的简单http服务器。
有2个主要问题,我尚不知道如何解决。
验证,管理用户的正确方法-会话
主要问题是,连接必须安全,因此需要SSL加密,如何实现?
我发现的与idhttpserver和openssl有关的任何示例都不十分完整,也与Indy的旧版本无关。
我目前正在使用带有Indy 10组件的Delphi XE2。
最佳答案
验证,管理用户的正确方法-会话
如果将TIdHTTPServer
属性设置为true(默认情况下为false),则TIdHTTPServer.SessionState
将为您管理HTTP会话。 TIdHTTPServer
使用cookie进行会话管理,因此您的客户端需要启用cookie。
身份验证必须手动执行,但是如何执行取决于您的客户端使用的是基于HTTP的身份验证还是基于HTML的身份验证。
对于HTTP身份验证,有ARequestInfo.UserName
和ARequestInfo.Password
属性可用。如果无效,则将适当的401响应发送回客户端(如果将AResponseInfo.AuthRealm
属性设置为非空白字符串,则TIdHTTPServer
将为您发送401响应)。默认情况下,TIdHTTPServer
仅支持BASIC
身份验证。如果要支持其他身份验证方案,则必须使用TIdHTTPServer.OnParseAuthentication
事件,并手动发送401答复,以便可以发送回适当的WWW-Authenticate
标头。无论哪种方式,如果客户端均已验证,则可以使用HTTP会话来使客户端在两次请求之间保持登录状态。 AResponseInfo.Session
和AResponseInfo.Session
属性指向当前会话。如果TIdHTTPServer.AutoStartSession
为true(默认情况下为false),则TIdHTTPServer
自动创建新会话。否则,您可以在需要时自行呼叫TIdHTTPServer.CreateSession()
。 TIdHTTPSession
具有一个Content
属性,您可以在其中存储特定于会话的数据。或者,您可以从TIdHTTPSession
派生一个新类,然后使用TIdHTTPServer.OnCreateSession
事件创建该类的实例。
对于HTML身份验证,根据配置HTML的方式,您有两种选择:
如果您的HTML <form>
标记没有enctype
属性,或者将其设置为application/x-www-webform-urlencoded
,则TIdHTTPServer
会将原始Web表单数据存储在ARequestInfo.FormParams
属性中,并且TIdHTTPServer.ParseParams
为true( (默认情况下),数据也将为您解析为ARequestInfo.Params
属性。
如果您的HTML <form>
标记的enctype
属性设置为multipart/form-data
,则必须手动解析ARequestInfo.PostStream
的内容,因为TIdHTTPServer
尚未为您解析该数据(示例已发布)之前在许多不同的论坛上有很多次关于如何使用Indy的TIdMessageDecoderMIME
类手动解析数据的信息)。默认情况下,ARequestInfo.PostStream
指向TMemoryStream
对象。如果需要,可以使用TIdHTTPServer.OnCreatePostStream
事件创建不同的TStream
派生类的实例。
主要问题是,连接必须安全,因此需要SSL加密,如何实现?
激活服务器之前:
将TIdServerIOHandlerSSLBase
派生的组件(例如TIdServerIOHandlerSSLOpenSSL
)分配给TIdHTTPServer.IOHandler
属性,并根据需要进行配置(证书,对等验证,SSL版本等)。对于OpenSSL,如果尚未在目标OS上预先安装2个OpenSSL库二进制文件libeay32.dll
和ssleay32.dll
(或非Windows平台等效文件),则必须在应用程序中部署它们。希望确保您的应用使用特定版本的OpenSSL。目前,OpenSSL是Indy本地支持的唯一加密方法,但是存在与Indy兼容的第三方解决方案,例如EldoS SecureBlackbox。
在TIdHTTPServer.Binding
属性中填写所需的HTTPS端口的绑定(443是默认的HTTPS端口)。通常,您应该创建2个绑定,一个用于HTTP端口80,一个用于HTTPS端口443。在您的OnCommand...
处理程序中,如果您收到要求进行SSL / TLS加密的请求,则可以检查该请求的端口( AContext.Binding.Port
),如果不是HTTPS,则重定向(AResponseInfo.Redirect()
)客户端,以在HTTPS端口上重试该请求。
为TIdHTTPServer.OnQuerySSLPort
事件分配一个处理程序,并在其VUseSSL
参数与您的HTTPS端口匹配时,将其APort
参数设置为True。如果您的唯一HTTPS端口是443,则从SVN版本5461(为OnQuerySSLPort
处理程序is no longer needed)开始的UPDATE。