序列化任何自定义 WCF SecurityToken 的好方法吗?
这让我发疯...我试图拥有一个派生自 System.IdentityModel.Tokens.SecurityToken 的自定义 WCF 身份验证令牌,例如:
public class TestSecurityToken : SecurityToken
{
public override string Id
{ get { return "123"; } }
public override ReadOnlyCollection<SecurityKey> SecurityKeys
{ get { return new ReadOnlyCollection<SecurityKey>(new List<SecurityKey>(0)); } }
public override DateTime ValidFrom
{ get { return DateTime.MinValue; } }
public override DateTime ValidTo
{get { return DateTime.MaxValue; } }
public string Property1 { get; set; }
}
我知道我可以为其编写一个自定义序列化程序扩展了 WSSecurityTokenSerializer
,但我试图找到一种通用的方法来做到这一点,我可以制作一个可以序列化任何
以下是我尝试过的方法,但失败了:
尝试 1:将 SecurityToken 设为 DataContract
[DataContract]
public class TestSecurityToken : SecurityToken
失败,因为您不能拥有从非基类派生的 DataContract DataContract,而 SecurityToken 不是。
尝试 2:使用 XmlSerializer 进行序列化
public class SecurityTokenSerializer<T> : WSSecurityTokenSerializer where T : SecurityToken
{
private readonly XmlSerializer serializer;
public SecurityTokenSerializer()
{
serializer = new XmlSerializer(typeof (T));
}
protected override void WriteTokenCore(XmlWriter writer, SecurityToken token)
{
serializer.Serialize(writer, token);
}
失败并出现错误:
System.InvalidOperationException:存在反映类型“PartsSource.Services.Core.ServiceModel.SecurityTokenSerializerTest.TestSecurityToken”的错误。 ---> System.InvalidOperationException:要实现 XML 可序列化,从 ICollection 继承的类型必须在其继承层次结构的所有级别都具有 Add(System.IdentityModel.Tokens.SecurityKey) 的实现。 System.Collections.ObjectModel.ReadOnlyCollection`1[[System.IdentityModel.Tokens.SecurityKey, System.IdentityModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]] 未实现 Add(System.IdentityModel.Tokens.SecurityKey )。
由于我的自定义 SecurityToken
上的此属性:
public override ReadOnlyCollection<SecurityKey> SecurityKeys
{ get { return new ReadOnlyCollection<SecurityKey>(new List<SecurityKey>(0)); } }
尝试 3:与上面相同,但尝试告诉 XmlSerializer 忽略该 SecurityKeys 属性:
public class SecurityTokenSerializer<T> : WSSecurityTokenSerializer where T : SecurityToken
{
private readonly XmlSerializer serializer;
public SecurityTokenSerializer()
{
var xOver = new XmlAttributeOverrides();
xOver.Add(typeof(T), "SecurityKeys", new XmlAttributes { XmlIgnore = true });
serializer = new XmlSerializer(typeof (T), xOver);
}
此错误的消息与之前的尝试。它不会忽略这个属性。
有谁对如何将任何 SecurityToken 序列化为 XmlReader / XmlWriter 有任何其他想法吗?看起来应该很简单,但是……
This is making me crazy... I'm trying to have a custom WCF auth token that derives from System.IdentityModel.Tokens.SecurityToken
for example:
public class TestSecurityToken : SecurityToken
{
public override string Id
{ get { return "123"; } }
public override ReadOnlyCollection<SecurityKey> SecurityKeys
{ get { return new ReadOnlyCollection<SecurityKey>(new List<SecurityKey>(0)); } }
public override DateTime ValidFrom
{ get { return DateTime.MinValue; } }
public override DateTime ValidTo
{get { return DateTime.MaxValue; } }
public string Property1 { get; set; }
}
I know I can write a custom serializer for it that extends WSSecurityTokenSerializer
, but I am trying to find a way to do that in a generic way, where I can make a serializer that can serialize any <T> where T : SecurityToken
Here is what I have tried, and failed:
Attempt 1: Make the SecurityToken a DataContract
[DataContract]
public class TestSecurityToken : SecurityToken
Fails because you cant have a DataContract that derives from a base class that isn't a DataContract, which SecurityToken is not.
Attempt 2: Serialize with an XmlSerializer
public class SecurityTokenSerializer<T> : WSSecurityTokenSerializer where T : SecurityToken
{
private readonly XmlSerializer serializer;
public SecurityTokenSerializer()
{
serializer = new XmlSerializer(typeof (T));
}
protected override void WriteTokenCore(XmlWriter writer, SecurityToken token)
{
serializer.Serialize(writer, token);
}
This fails with the error:
System.InvalidOperationException: There was an error reflecting type 'PartsSource.Services.Core.ServiceModel.SecurityTokenSerializerTest.TestSecurityToken'. ---> System.InvalidOperationException: To be XML serializable, types which inherit from ICollection must have an implementation of Add(System.IdentityModel.Tokens.SecurityKey) at all levels of their inheritance hierarchy. System.Collections.ObjectModel.ReadOnlyCollection`1[[System.IdentityModel.Tokens.SecurityKey, System.IdentityModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]] does not implement Add(System.IdentityModel.Tokens.SecurityKey).
Due to this property on my custom SecurityToken
:
public override ReadOnlyCollection<SecurityKey> SecurityKeys
{ get { return new ReadOnlyCollection<SecurityKey>(new List<SecurityKey>(0)); } }
Attempt 3: Same as above, but try to tell the XmlSerializer to ignore that SecurityKeys property:
public class SecurityTokenSerializer<T> : WSSecurityTokenSerializer where T : SecurityToken
{
private readonly XmlSerializer serializer;
public SecurityTokenSerializer()
{
var xOver = new XmlAttributeOverrides();
xOver.Add(typeof(T), "SecurityKeys", new XmlAttributes { XmlIgnore = true });
serializer = new XmlSerializer(typeof (T), xOver);
}
This errors with the same message as the previous attempt. It does not ignore this property.
Does anyone have any other ideas on how to just serialize any SecurityToken to an XmlReader / XmlWriter? It seems like it should have been dead simple, but no...
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
由于我没有找到其他好的方法来做到这一点,所以我最终所做的就是让我的自定义 SecurityToken 也实现 IXmlSerialized,然后将我的序列化器的定义更改为:
然后我的自定义安全令牌定义为:
然后序列化器可以将序列化委托给自定义安全令牌。它可能不是最干净的解决方案(我想说它违反了单一职责原则),但它似乎确实有效,让我不必为每个自定义令牌编写序列化器。
Since I found no other good way to do this, what I ended up doing was making my custom SecurityToken also implement
IXmlSerializable
, and then changed the definition of my serializer to:My custom security token is then defined as:
Then the serializer can delegate serialization to the custom security token. It probably isn't the cleanest solution (I'd say it violates the single-responsibility principal), but it does seem to work and let me not have to write a serializer for every custom token.