如何从WCF服务获取令牌

时间:2014-08-14 17:39:56

标签: xml wcf wcf-security ws-security

我的组织托管一个WCF服务,外部用户可以向我们发送数据。我们有几个完全可以运作的发件人,但我正在帮助一个遇到麻烦的人。发件人没有使用Microsoft技术,所以我正在协助他们构建一个连接到我们服务的XML数据包。

目前我正在尝试构建XML以在我的服务上调用RequestSecurityToken。以下是我发送的XML示例,其中删除了安全性详细信息:

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://www.w3.org/2003/05/soap-envelope"
   xmlns:SOAP-ENC="http://www.w3.org/2003/05/soap-encoding"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns:xsd="http://www.w3.org/2001/XMLSchema"
   xmlns:us="our namespace url"
   xmlns:arrays="http://schemas.microsoft.com/2003/10/Serialization/Arrays"
   xmlns:addr="http://www.w3.org/2005/08/addressing"
   xmlns:wsu="http://doc.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
    <SOAP-ENV:Header>
        <addr:Action SOAP-ENV:mustUnderstand="1">http://schemas.xmlsoap.org/ws/2005/02/trust/RST/SCT</addr:Action>
        <addr:MessageID>urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx</addr:MessageID>
        <addr:ReplyTo>
            <addr:Address>http://www.w3.org/2005/08/addressing/anonymous</addr:Address>
        </addr:ReplyTo>
        <addr:To SOAP-ENV:mustUnderstand="1">https://our.domain/path/ServiceName.svc</addr:To>
        <wsse:Security SOAP-ENV:mustUnderstand="1" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
            <wsu:Timestamp wsu:Id="uuid-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx-x">
                <wsu:Created>2014-08-14T10:07:00.095Z</wsu:Created>
                <wsu:Expires>2014-08-14T10:09:05.095Z</wsu:Expires>
            </wsu:Timestamp>
            <wsse:UsernameToken wsu:Id="uuid-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx-x">
                <wsse:Username>TST</wsse:Username>
                <wsse:Password Type="http://docs.oasis-open.org/wsse/2004/01/oasis-200401-wsse-username-token-profile-1.0#PasswordText">Test</wsse:Password>
            </wsse:UsernameToken>
        </wsse:Security>
    </SOAP-ENV:Header>
    <SOAP-ENV:Body>
        <trust:RequestSecurityToken xmlns:trust="http://schemas.xmlsoap.org/ws/2005/02/trust">
            <trust:TokenType>http://schemas.xmlsoap.org/ws/2005/02/sc/sct</trust:TokenType>
            <trust:RequestType>http://schemas.xmlsoap.org/ws/2005/02/trust/Issue</trust:RequestType>
            <trust:Entropy>
                <trust:BinarySecret wsu:Id="uuid-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx-x" Type="http://schemas.xmlsoap.org/ws/2005/02/trust/Nonce">xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=</trust:BinarySecret>
            </trust:Entropy>
            <trust:KeySize>256</trust:KeySize>
        </trust:RequestSecurityToken>
    </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

这是回复:

<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing">
    <s:Header>
        <a:Action s:mustUnderstand="1">http://www.w3.org/2005/08/addressing/soap/fault</a:Action>
        <a:RelatesTo>urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx</a:RelatesTo>
    </s:Header>
    <s:Body>
        <s:Fault>
            <s:Code>
                <s:Value>s:Sender</s:Value>
                <s:Subcode>
                    <s:Value xmlns:a="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">a:InvalidSecurity</s:Value>
                </s:Subcode>
            </s:Code>
            <s:Reason>
                <s:Text xml:lang="en-US">An error occurred when verifying security for the message.</s:Text>
            </s:Reason>
        </s:Fault>
    </s:Body>
</s:Envelope>

1 个答案:

答案 0 :(得分:0)

这是一个简单的C#REST(ish)服务器,它接受HTTP Post中的XML 您还可以修改它以使用HTTP Get Parameters,在标头中隐藏您的安全凭证,使用基本身份验证等。

希望你觉得这很有用。

namespace webservice {
    public partial class datasvc : System.Web.UI.Page {
        protected void Page_Load(object sender, EventArgs e) {
            XmlDocument xmlResponse = new XmlDocument();
            xmlResponse.LoadXml("<xml/>");



            try {
                XmlDocument xmlRequest = new XmlDocument();
                xmlRequest.Load(Request.InputStream);

                if (xmlRequest.DocumentElement.HasAttribute("id") &&
                    xmlRequest.DocumentElement.HasAttribute("pw")) {
                    // OK verify
                } else {
                    throw new Exception("Invalid credentials");
                }


                switch (xmlRequest.DocumentElement.GetAttribute("service")) {
                    case "time":
                        xmlResponse.DocumentElement.SetAttribute("content", DateTime.Now.ToString());
                        break;

                    case "hello":
                        xmlResponse.DocumentElement.SetAttribute("content", "Hello World");
                        break;

                    default:
                        throw new Exception("Unknown Service");
                }


            } catch (Exception ex) {
                xmlResponse.DocumentElement.SetAttribute("err", ex.Message);
            } finally {
                Response.ContentType = "text/xml";
                Response.Write(xmlResponse.OuterXml);
            }
        }
    }
}

从.NET调用它是一个客户端

namespace webservice {
    public partial class client : System.Web.UI.Page {

        /// <summary>Posts the specified document to the server using UTF-8 encoding.</summary>             
        public XmlDocument postXml(XmlDocument xml, String strURL, string strID, string strPassword) {
            HttpWebRequest req = (HttpWebRequest)WebRequest.Create(strURL);
            req.Method = "POST";
            req.ContentType = "text/xml";
            XmlDocument xmlReturn = new XmlDocument();
            req.Timeout = 180000;


            // UGH! not set by default!
            req.Proxy.Credentials = System.Net.CredentialCache.DefaultCredentials;

            // Write the serialized XML to the request
            Stream rs = req.GetRequestStream();

            XmlTextWriter tw = new XmlTextWriter(rs, Encoding.UTF8); // Encoding.GetEncoding("UTF-8"));
            xml.WriteTo(tw);
            tw.Flush();
            rs.Close();
            HttpWebResponse resp = (HttpWebResponse)req.GetResponse();
            string msg;

            try {
                // Get the response from the server
                StreamReader reader = new StreamReader(resp.GetResponseStream());
                msg = reader.ReadToEnd();
                xmlReturn.LoadXml(msg);
            } catch (Exception e) {
                throw new Exception("Error posting to server: " + strURL, e);
            }
            return xmlReturn;
        }


        protected void Page_Load(object sender, EventArgs e) {
            try {
                XmlDocument xml = new XmlDocument();
                xml.LoadXml("<xml/>");
                xml.DocumentElement.SetAttribute("userid", "test");
                string strID = "userid";
                string strPassword = "password";

                xml.DocumentElement.SetAttribute("id", strID);
                xml.DocumentElement.SetAttribute("pw", strPassword);

                // post XML to /datasvc.aspx on this .NET project
                string strURL = Request.Url.ToString().Replace( "client", "datasvc" );

                xml.DocumentElement.SetAttribute("service", "hello");
                XmlDocument xmlResponse = this.postXml(xml, strURL, strID, strPassword);
                Response.Write(xmlResponse.DocumentElement.GetAttribute("content"));

                xml.DocumentElement.SetAttribute("service", "time");
                xmlResponse = this.postXml(xml, strURL, strID, strPassword);
                Response.Write(xmlResponse.DocumentElement.GetAttribute("content"));


            } catch (Exception ex) {
                Response.Write(ex.Message);

            }

        }
    }