序列化任何自定义 WCF SecurityToken 的好方法吗?

发布于 2024-12-10 15:19:16 字数 2963 浏览 0 评论 0原文

这让我发疯...我试图拥有一个派生自 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,但我试图找到一种通用的方法来做到这一点,我可以制作一个可以序列化任何 的序列化器。其中 T : SecurityToken

以下是我尝试过的方法,但失败了:


尝试 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

对你再特殊 2024-12-17 15:19:16

由于我没有找到其他好的方法来做到这一点,所以我最终所做的就是让我的自定义 SecurityToken 也实现 IXmlSerialized,然后将我的序列化器的定义更改为:

public class SecurityTokenSerializer<T> : WSSecurityTokenSerializer
    where T : SecurityToken, IXmlSerializable

然后我的自定义安全令牌定义为:

public class MySecurityToken : SecurityToken, IXmlSerializable

然后序列化器可以将序列化委托给自定义安全令牌。它可能不是最干净的解决方案(我想说它违反了单一职责原则),但它似乎确实有效,让我不必为每个自定义令牌编写序列化器。

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:

public class SecurityTokenSerializer<T> : WSSecurityTokenSerializer
    where T : SecurityToken, IXmlSerializable

My custom security token is then defined as:

public class MySecurityToken : SecurityToken, IXmlSerializable

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文