Web服务调用ADFS 2.0身份验证

时间:2015-06-15 11:59:43

标签: asp.net asp.net-mvc wcf forms-authentication adfs2.0

我有一个使用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   渠道。请验证指定或暗示的EndpointIdentity   EndpointAddress正确识别远程端点。

        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;

3 个答案:

答案 0 :(得分:0)

问题很可能出在:string url = "{url of website}";。和/或POST中缺少参数。

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

现在显而易见的回复,没有侮辱意图:我建议您跟踪常规登录过程,然后将这些确切的HTTP请求与您的请求进行比较。

答案 1 :(得分:0)

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()
}

我希望解决您的问题。

答案 2 :(得分:0)

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

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