访问WCF USERNAMEPASSWORDValidator中的当前InstanceContext
-
27-09-2020 - |
题
我有一个使用自定义usernamepasswordvalidator的WCF服务。验证器需要访问我的实体框架上下文。
我想为整个服务调用创建一个ObjectContext,然后在呼叫结束时销毁/将其丢弃。所以我创建了一个单身静态类,提供了这个功能,但是,现在正在发生的事情是,如果两个服务调用同时发生,其中一个呼叫处置单例。
我要么保留本地引用,要么将其使用它的第二个服务,它会将其视为设置并抛出和错误,或者,我在所有我需要的地方围绕单身级围绕单身级包装属性。更改被抛弃,因为如果另一个呼叫已经配置了该对象的新实例。
所以基本上我的问题是我如何实例化每个服务调用的ObjectContext?
注意:该实例需要在服务代码和自定义usernamepasswastvalidator代码中可接近。
我不能只在构造函数中执行或使用语句,因为自定义usernamepasswasswardator没有访问它。有没有办法每次呼叫拥有静态课程?它听起来不可能,但这遍布这一点是什么?我应该在会话中缓存对象吗?
我的服务在IIS中托管。
更新:
所以我用IExtension对象将此缩小到InstanceContext中的状态。但是如何在UsernamePasswordValidator中访问当前的InstanceContext?
解决方案
我不确定这是做事的最佳方式,但这允许我每请求使用一个ObjectContext,所以我没有旋转太多,这也意味着我不必使用锁定如果许多用户使用该服务,那将成为噩梦的对象。
public static class MyContextProvider
{
public static MyModel Context
{
get
{
if (HttpContext.Current.Items["context"].IsNull())
{
HttpContext.Current.Items["context"] = new MyModel();
}
return HttpContext.Current.Items["context"] as MyModel;
}
}
}
.
然后我需要在应用程序中需要一个ObjectContext,我只需拨打
var context = MyContextProvider.Context;
. 其他提示
每个呼叫有一个实例,每个实例也有1个呼叫。
所以它应该非常简单,在TopleVel的TopleVel中使用using () { }
块。 public static class EntityModelProvider
{
private static readonly Dictionary<OperationContext, MyEntityModel> _entityModels = new Dictionary<OperationContext, MyEntityModel>();
public static MyEntityModel GetEntityModel()
{
if (OperationContext.Current == null)
throw new Exception("OperationContext is missing");
lock (_entityModels)
{
if (!_entityModels.ContainsKey(OperationContext.Current))
{
_entityModels[OperationContext.Current] = new MyEntityModel();
OperationContext.Current.OperationCompleted += delegate
{
lock (_entityModels)
{
_entityModels[OperationContext.Current].Dispose();
_entityModels.Remove(OperationContext.Current);
}
};
}
return _entityModels[OperationContext.Current];
}
}
. 对于您的服务,您可以指定一个服务行为,详细说明服务的实例模式:
[ServiceBehaviour(InstanceContextMode = InstanceContextMode.PerCall)]
public class MyService : IMyService {
ObjectContext context;
}
. 更清晰的方式可以使用ServiceAuthenticationManager,该管理员在.NET 4中。
http://msdn.microsoft.com/cn -us / library / system.servicemodel.serviceauthenticationmanager.aspx
从Authenticate
方法(您将覆盖),您可以访问消息对象并在其上设置属性。我没有用它愤怒,所以ymmv :)
编辑此方法的问题是您没有用户名和密码,所以仍需要自定义身份验证。
看看UserNameEcurityTokenauthenticator ... http:// msdn .microsoft.com / en-US / Library / System.identityModel.Selectors.UsernamesEecurityTokenauthenticator(v= vs.90).aspx
从我的研究进一步阅读:
这个问题的答案给出了一些关于如何使用它的提示:
使用system.servicemodel.serviceauthenticationManager? < / p>
如果可以读取(或忽略)俄语,我发现了有用的提示:
http://www.sql.ru/forum/actualthread.aspx ?TID= 799046
这个相当好的codeproject文章进一步(加密和压缩以及自定义授权)
http://www.codeproject .com /文章/ 165844 / wcf-client-server-products-with-custom-authenti
为什么在将上下文中传递到CustomValidator时分配给服务时 - 将您的对象上下文存储在验证器中,并且在覆盖验证方法中,如果需要。然后您仍然可以通过Services CutomuserNameValidator访问该对象..
取决于您要求的内容: 创建单独的ObjectContext类作为动态对象 - 将其添加为CustomValidator的属性。 在您的自定义验证器中 - 您现在可以检查对象是否被配置并再次创建对象。 否则,如果这不是您的追踪 - 只是将上下文存储在验证器中 - 您仍然可以在服务器端访问。 这里的代码只是概括的想法 - 我只是把它发布为一个参考框架,这样你就可以了解我在谈论的内容。
public DynamicObjectContextObjectClass
{
ObjectContext internalObjectContext;
}
public class ServiceUserNamePasswordValidator : UserNamePasswordValidator
{
public DynamicObjectContextObjectClass dynamiccontext;
public override void Validate(string userName, string password)
{
if(dynamiccontext.internalObjectContext.isdisposed)
{
dynamiccontext.internalObjectContext = new Context;
}
try
{
if (string.IsNullOrEmpty(userName) || password == null)
{
//throw new ArgumentNullException();
throw new FaultException("Username cannot be null or empty; Password cannot be null and should not be empty");
}
}
}
}
.