我刚刚开始使用ServiceStack,作为测试用例,我希望重新编写使用标准ASP.Net处理程序构建的现有服务.我已经成功地将它全部工作,因为我想要它,但有某些方面利用ASP.Net Session对象.
我已经尝试将IRequiresSessionState添加到服务接口中:
public class SessionTestService : RestServiceBase, IRequiresSessionState { public override object OnPost(SessionTest request) { // Here I want to use System.Web.HttpContext.Current.Session } }
问题是我似乎无法使其工作,因为Session对象始终为null.
我做了很多谷歌搜索,并对https://github.com/mythz/ServiceStack/blob/master/tests/ServiceStack.WebHost.IntegrationTests/Services/Secure.cs和类似问题感到困惑,但我找不到任何执行此操作的示例代码(令我感到惊讶).任何人都可以解释为什么以上不起作用,并建议我需要做什么才能使它工作?
注意:最终我可能希望用Redis替换它或者尝试删除任何服务器端会话要求,但我认为我暂时使用ASP.Net实现,以使工作正常并避免重新处理它在这一点上超过必要的.
使用ServiceStack ISession
ServiceStack有一个新的ISession
界面支持,ICacheClient
它允许您ISession
在MVC控制器,ASP.NET基页和ServiceStack的Web服务之间共享相同的Cookie,这些Web服务共享相同的Cookie ID,允许您在这些Web框架之间自由共享数据.
注意:ISession是一个干净的实现,它完全绕过现有的ASP.NET会话和ServiceStack自己的组件,如ServiceStack的MVC PowerPack中所述,并在Sessions wiki页面中详细解释.
要轻松使用ServiceStack的Session(Cache和JSON Serializer),您的控制器将继承自ServiceStackController(在MVC中)或PageBase(在ASP.NET中)
ServiceStack中还添加了新的身份验证/验证功能,您可以在Wiki上阅读:
身份验证和授权
验证
使用ASP.NET Session
本质上,ServiceStack只是一组在ASP.NET或HttpListener主机上运行的轻量级IHttpHandler.如果托管在IIS/ASP.NET(最常见)中,它就像普通的ASP.NET请求一样工作.
ServiceStack中的任何内容都不会访问或影响底层ASP.NET应用程序中已配置的缓存和会话提供程序.如果要启用它,则需要在ASP.NET中正常配置它(即在ServiceStack之外),请参阅:
http://msdn.microsoft.com/en-us/library/ms178581.aspx
配置完成后,您可以通过单例访问ServiceStack Web服务中的ASP.NET会话:
HttpContext.Current.Session
或者通过底层的ASP.NET HttpRequest:
var req = (HttpRequest)base.RequestContext.Get().OriginalRequest; var session = req.RequestContext.HttpContext.Session;
虽然由于强制依赖XML配置并且默认情况下性能下降,但我更倾向于避免使用ASP.NET的Session,而是选择使用ServiceStack附带的更清晰的Cache Clients.
基本上,Sessions的工作方式(包括ASP.NET)是一个包含唯一ID的cookie,它被添加到唯一标识浏览器会话的Response中.此id指向服务器上匹配的Dictionary/Collection,表示浏览器的Session.
您链接到的IRequiresSession接口默认情况下不执行任何操作,它只是向自定义请求筛选器或基本Web服务发出信号通知此请求需要进行身份验证的方式(即,您应该放置验证/身份验证逻辑的两个位置)在ServiceStack中).
这是一个Basic Auth实现,它查看Web服务是否安全,如果是,请确保它们已经过身份验证.
这是另一个身份验证实现,它将验证标记有[Authenticate]属性的所有服务,以及如何通过在Request DTO上添加Attribute 来为您的服务启用身份验证.
上述实现是ServiceStack下一版本中包含的多身份验证提供程序模型的一部分.以下是显示如何在应用程序中注册和配置新Auth模型的参考示例.
新的Auth模型完全是一种选择性的便利,因为您可以不使用它并使用请求过滤器或基类(通过重写OnBeforeExecute)实现类似的行为.事实上,新的Auth服务实际上并没有内置到ServiceStack中.整个实现位于可选的ServiceStack.ServiceInterfaces项目中,并使用自定义请求筛选器实现.
以下是我多年来使用的不同身份验证策略:
标记需要使用[Attribute]进行身份验证的服务.可能是最惯用的C#方式,非常适合通过Cookie传递session-id.
特别是在Web上下文之外,有时使用更明确的IRequiresAuthentication接口更好,因为它提供对身份验证所需的User和SessionId的强类型访问.
您可以在每个需要它的服务上使用1-liner进行身份验证 - 在特定的基础上.当您很少需要身份验证的服务时,这是一种合适的方法
这是@mythz的一个伟大而全面的答案.但是,当尝试通过HttpContext.Current.Session
ServiceStack Web服务访问ASP.NET会话时,它总是返回null
给我.这是因为ServiceStack中的HttpHandler都没有用IRequiresSessionState
接口装饰,因此.NET Framework不向我们提供会话对象.
为了解决这个问题,我实现了两个新类,它们都使用装饰器模式为我们提供了所需的东西.
首先,新的IHttpHandler
需要会话状态.它包装了IHttpHandler
ServiceStack提供的并将调用传递给它...
public class SessionHandlerDecorator : IHttpHandler, IRequiresSessionState { private IHttpHandler Handler { get; set; } internal SessionHandlerDecorator(IHttpHandler handler) { this.Handler = handler; } public bool IsReusable { get { return Handler.IsReusable; } } public void ProcessRequest(HttpContext context) { Handler.ProcessRequest(context); } }
接下来,在将返回的处理程序包装到新的... 之前,一个新的IHttpHandlerFactory
委托生成IHttpHandler
ServiceStack 的职责SessionHandlerDecorator
.
public class SessionHttpHandlerFactory : IHttpHandlerFactory { private readonly static ServiceStackHttpHandlerFactory factory = new ServiceStackHttpHandlerFactory(); public IHttpHandler GetHandler(HttpContext context, string requestType, string url, string pathTranslated) { var handler = factory.GetHandler(context, requestType, url, pathTranslated); return handler == null ? null : new SessionHandlerDecorator(handler); } public void ReleaseHandler(IHttpHandler handler) { factory.ReleaseHandler(handler); } }
然后,只需将type
Web.config中处理程序中的属性更改为SessionHttpHandlerFactory
而不是ServiceStack.WebHost.Endpoints.ServiceStackHttpHandlerFactory, ServiceStack
,您的Web服务现在应该具有可用于它们的ASP.NET会话.
尽管如此,我完全赞同ISession
ServiceStack提供的新实现.但是,在某些情况下,在成熟的产品上,用新的实现替换ASP.NET会话的所有用途似乎太大了,因此这种解决方法!