繁体   English   中英

Web服务调用ADFS 2.0身份验证

[英]Web Service Call for ADFS 2.0 Authentication

我有一个使用ADFS 2.0进行身份验证的ASP.NET MVC Web应用程序。 一些MVC控制器动作用作通用Web服务端点,接收和提供JSON。 我想构建一个自动化应用程序功能的客户端应用程序。 为此,我正在构建一个API访问库,它将向Web服务发出HTTP请求以完成其工作。

我被困在试图验证。 我正在使用ADFS 2.0的表单身份验证,所以我不能简单地使用有效的用户名和密码模拟表单帖子以生成令牌? 我没有收到令牌,而只是获取登录页面。 我不确定我需要做什么才能验证我的请求。 我的代码粘贴在下面...但也许我做错了,而且我不知道的是什么?

string postData = string.Empty;
postData += "ctl00$ContentPlaceHolder1$UsernameTextBox=" + username + "&";
postData += "ctl00$ContentPlaceHolder1$PasswordTextBox=" + password;
postData += "&AuthMethod=FormsAuthentication";// Submit the data back

string url = "{url of website}";
HttpWebRequest getTokenRequest = WebRequest.Create(url) as HttpWebRequest;

getTokenRequest.CookieContainer = cookies;
getTokenRequest.ContentType = "application/x-www-form-urlencoded";
getTokenRequest.ContentLength = postData.Length;
getTokenRequest.Method = "POST";

// post the data to the request
using (StreamWriter sw = new StreamWriter(getTokenRequest.GetRequestStream()))
{
    sw.Write(postData);
    sw.Flush();
    sw.Close();
}

HttpWebResponse getTokenResponse = (HttpWebResponse)getTokenRequest.GetResponse(); 

string responseString = ResponseToString(getTokenResponse);

我也尝试过另一种方法,但也行不通。 这使用WCF。 我收到错误:

无法打开安全通道,因为与远程端点的安全协商失败。这可能是由于在用于创建通道的EndpointAddress中缺少或错误指定了EndpointIdentity。 请验证EndpointAddress指定或暗示的EndpointIdentity是否正确标识远程端点。

        const string relyingPartyId = "[ID]"; //ID of the relying party in AD FS
        const string adfsEndpoint = "https://[server]/adfs/services/trust/13/usernamemixed"; //url to hit - username & pw?
        const string certSubject = "[subject]"; //?

        //Setup the connection to ADFS
        var factory = new Microsoft.IdentityModel.Protocols.WSTrust.WSTrustChannelFactory(
            new WindowsWSTrustBinding(SecurityMode.TransportWithMessageCredential), 
            new EndpointAddress(adfsEndpoint));

        factory.TrustVersion = TrustVersion.WSTrust13;

        factory.Credentials.UserName.UserName = "[un]";
        factory.Credentials.UserName.Password = "[pw]";

        //Setup the request object 
        var rst = new Microsoft.IdentityModel.Protocols.WSTrust.RequestSecurityToken
        {
            RequestType = Microsoft.IdentityModel.SecurityTokenService.RequestTypes.Issue,
            KeyType = Microsoft.IdentityModel.SecurityTokenService.KeyTypes.Bearer,
            AppliesTo = new EndpointAddress(relyingPartyId)
        };

        //Open a connection to ADFS and get a token for the logged in user
        var channel = factory.CreateChannel();

        //added to solve a trust certificate issue - bad from a security perspective
        System.Net.ServicePointManager.ServerCertificateValidationCallback +=
        (se, cert, chain, sslerror) =>
        {
            return true;
        };

        var genericToken = channel.Issue(rst) as GenericXmlSecurityToken;

最有可能的问题是: string url = "{url of website}"; 和/或POST中缺少参数。

它不应该只是任何URL。 它应该是格式正确的WS-Federation请求。 有时间戳等等。通常/有时(在当前的ADFS中)它是一个两步过程。 首先是正常请求,然后是真实(uid + pwd)认证。 两者都在适当的位置使用适当的WS-Fed参数。 只有uid和pwd是不够的。

现在明显的答复,没有任何侮辱:我建议您跟踪常规登录过程,然后将这些确切的HTTP请求与您的请求进行比较。

ASP.NET中的表单身份验证默认情况下依赖于Cookie。 用户登录到应用程序后,运行时可以在浏览器上发出cookie。 然后,浏览器将向每个后续请求发送cookie给应用程序。 ASP.NET将看到cookie并知道用户已经过身份验证,无需再次登录。

无论有没有WebRequest.Credentials你都需要这样的东西:

HttpWebRequest request = (HttpWebRequest)WebRequest.Create("yoururl");
request.CookieContainer = new CookieContainer();
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
byte[] bytes = Encoding.UTF8.GetBytes(yourpostdata);//as user pass
request.ContentLength = bytes.Length;

//or use credentials
//request.Credentials = new NetworkCredential("UserName", "PassWord");

using (Stream streamOut = request.GetRequestStream())
{
    streamOut.Write(bytes, 0, bytes.Length);
    streamOut.Close();
}

using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
{
    Stream stream = response.GetResponseStream();
    StreamReader sr = new StreamReader(stream);
    //save cookie to reuse
    //var _cookie = response.Cookies;
    string responseString = sr.ReadToEnd()
}

我希望解决你的问题。

您必须首先请求ADFS识别您的自己,接受令牌,然后将请求发送到您的应用程序,包括内部令牌(作为cookie)

我建议您使用Fiddler捕获从浏览器发送的请求,并查看您的请求的哪些部分缺失

暂无
暂无

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

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