繁体   English   中英

如何在不提供凭据的情况下将安全rss订阅源读入SyndicationFeed?

[英]How do I read a secure rss feed into a SyndicationFeed without providing credentials?

无论出于何种原因,IBM都使用https(不需要凭据)来获取RSS源。 我正在尝试使用.NET 4 SyndicationFeed来使用https://www.ibm.com/developerworks/mydeveloperworks/blogs/roller-ui/rendering/feed/gradybooch/entries/rss?lang=en 我可以在浏览器中打开这个Feed,它加载得很好。 这是代码:

        using (XmlReader xml = XmlReader.Create("https://www.ibm.com/developerworks/mydeveloperworks/blogs/roller-ui/rendering/feed/gradybooch/entries/rss?lang=en"))
        {
            var items = from item in SyndicationFeed.Load(xml).Items
                        select item;
        }

这是例外:

System.Net.WebException was unhandled by user code
Message=The remote server returned an error: (500) Internal Server Error.
Source=System
StackTrace:
   at System.Net.HttpWebRequest.GetResponse()
   at System.Xml.XmlDownloadManager.GetNonFileStream(Uri uri, ICredentials credentials, IWebProxy proxy, RequestCachePolicy cachePolicy)
   at System.Xml.XmlDownloadManager.GetStream(Uri uri, ICredentials credentials, IWebProxy proxy, RequestCachePolicy cachePolicy)
   at System.Xml.XmlUrlResolver.GetEntity(Uri absoluteUri, String role, Type ofObjectToReturn)
   at System.Xml.XmlReaderSettings.CreateReader(String inputUri, XmlParserContext inputContext)
   at System.Xml.XmlReader.Create(String inputUri, XmlReaderSettings settings, XmlParserContext inputContext)
   at System.Xml.XmlReader.Create(String inputUri)
   at EDN.Util.Test.FeedAggTest.LoadFeedInfoTest() in D:\cdn\trunk\CDN\Dev\Shared\net\EDN.Util\EDN.Util.Test\FeedAggTest.cs:line 126

如何配置阅读器以使用https源?

我不认为它与安全有任何关系。 500错误是服务器端错误。 XmlReader.Create(url)生成的请求中的某些内容让ibm网站感到困惑。 如果它只是一个安全问题,正如您的问题中所建议的那样,那么您可能会收到403错误或“授权被拒绝”。 但你有500,这是一个应用程序错误。

即便如此,也许客户端应用可以做一些事情,以避免混淆服务器。

我使用Fiddler查看了传出的HTTP请求标头。 对于IE生成的请求,标题如下所示:

GET https://www.ibm.com/developerworks/mydeveloperworks/blogs/roller-ui/rendering/feed/gradybooch/entries/rss?lang=en HTTP/1.1
Accept: image/gif, image/jpeg, image/pjpeg, application/x-ms-application, application/vnd.ms-xpsdocument, application/xaml+xml, application/x-ms-xbap, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, application/x-silverlight, application/x-shockwave-flash, application/x-silverlight-2-b2, */*
Accept-Language: en-us
User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; Trident/4.0; .NET CLR 3.5.30729;)
Accept-Encoding: gzip, deflate
Host: www.ibm.com
Connection: Keep-Alive
Cookie: UnicaNIODID=Ww06gyvyPpZ-WPl6K7y; conxnsCookie=en; IBMPOLLCOOKIE=""; UnicaNIODID=QridYHCNf7M-WYM8Usr

对于来自XmlReader.Create(url)的请求,标头如下所示:

GET https://www.ibm.com/developerworks/mydeveloperworks/blogs/roller-ui/rendering/feed/gradybooch/entries/rss?lang=en HTTP/1.1
Host: www.ibm.com
Connection: Keep-Alive

相当不同。 另外,在对后者的响应中,我在500响应中得到了一个Set-Cookie标头,这在IE的响应中没有出现。

基于此,我认为它是请求标题的差异,特别是cookie,令ibm.com感到困惑。


我不知道如何说服XmlReader.Create()嵌入我想要的所有请求标头,包括cookie。 但我知道如何使用HttpWebRequest做到这一点。 所以我用过它。

我必须清除一些障碍。

  1. 我需要ibm.com的持久cookie。 为此我不得不求助于Win32 InternetGetCookie的 ap / invoke。 有关如何执行此操作,请参阅WebRequest文档页面底部的用户提供内容中附加的PersistentCookies类。 附加cookie后,我不再收到500个错误。 万岁!

  2. 但是XmlReader.Create()无法读取生成的流。 它对我来说看起来很二元 我意识到我需要解压缩gzip或缩小的内容。 为此,我必须 围绕收到的响应流包装GZipStream或DeflateStream,并将解压缩流用于XmlReader。 在HttpWebRequest上设置AutomaticDecompression属性。 我可以通过在出站请求中的Accept-Encoding标头上不包括“gzip,deflate”来避免这种需要。 实际上,在设置AutomaticDecompression属性后,这些标头将在出站HTTP请求中隐式设置。

  3. 当我这样做时,我得到了实际的文字。 但有些字节代码已关闭。 接下来,我需要在TextReader中使用正确的文本编码,如HttpWebResponse中所示。

  4. 在这之后,我得到了一个合理的字符串,但是生成的解压缩的rss流导致XmlReader被阻塞,

    ReadElementString method can only be called on elements with simple or empty content. Line 11, position 25.

    我查看并在rss文档的<copyright>元素内的该位置找到了一个小的<script>块。 似乎IBM试图通过附加将在浏览器中运行的逻辑来格式化日期,从而使浏览器“本地化”版权日期。 对我来说似乎有点过分,甚至是IBM的错误。 但是因为元素的文本节点中的尖括号支撑着XmlReader,所以我删除了带有Regex替换的脚本块。


在清除了这些障碍之后,它起了作用。 .NET应用程序能够从该https URL读取RSS流。

我没有做任何进一步的测试 - 看看是否改变Accept标头或Accept-Encoding标头会改变行为。 如果你关心的话,那就是你要弄清楚的。

结果代码如下。 它比你的简单3线更难听。 我不知道如何使它变得更简单。

public void Run()
{
    string url;
    url = "https://www.ibm.com/developerworks/mydeveloperworks/blogs/roller-ui/rendering/feed/gradybooch/entries/rss?lang=en";

    HttpWebRequest hwr = (HttpWebRequest) WebRequest.Create(url);
    // attach persistent cookies
    hwr.CookieContainer =
        PersistentCookies.GetCookieContainerForUrl(url);
    hwr.Accept = "text/xml, */*";
    hwr.Headers.Add(HttpRequestHeader.AcceptLanguage, "en-us");
    hwr.UserAgent = "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; .NET CLR 3.5.30729;)";
    hwr.KeepAlive = true;
    hwr.AutomaticDecompression = DecompressionMethods.Deflate |
                                 DecompressionMethods.GZip;

    using (var resp = (HttpWebResponse) hwr.GetResponse())
    {
        using(Stream s = resp.GetResponseStream())
        {            
            string cs = String.IsNullOrEmpty(resp.CharacterSet) ? "UTF-8" : resp.CharacterSet;
            Encoding e = Encoding.GetEncoding(cs);

            using (StreamReader sr = new StreamReader(s, e))
            {
                var allXml = sr.ReadToEnd();

                // remove any script blocks - they confuse XmlReader
                allXml = Regex.Replace( allXml,
                                        "(.*)<script type='text/javascript'>.+?</script>(.*)",
                                        "$1$2",
                                        RegexOptions.Singleline);

                using (XmlReader xmlr = XmlReader.Create(new StringReader(allXml)))
                {
                    var items = from item in SyndicationFeed.Load(xmlr).Items
                        select item;
                }
            }
        }
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM