简体   繁体   English

Web服务调用ADFS 2.0身份验证

[英]Web Service Call for ADFS 2.0 Authentication

I have an ASP.NET MVC web app that uses ADFS 2.0 for authentication. 我有一个使用ADFS 2.0进行身份验证的ASP.NET MVC Web应用程序。 Some of the MVC controller actions function as generic web service endpoints, receiving and serving JSON. 一些MVC控制器动作用作通用Web服务端点,接收和提供JSON。 I want to build a client application that automates some of the app's functionality. 我想构建一个自动化应用程序功能的客户端应用程序。 For that purpose, I am building an API access library that will make HTTP requests to the web service in order to do its job. 为此,我正在构建一个API访问库,它将向Web服务发出HTTP请求以完成其工作。

I am stuck at trying to authenticate. 我被困在试图验证。 I am using forms authentication for ADFS 2.0, so shouldn't I be able to simply simulate the form post with a valid username and password in order to generate a token? 我正在使用ADFS 2.0的表单身份验证,所以我不能简单地使用有效的用户名和密码模拟表单帖子以生成令牌? Instead of receiving a token back, I just get the login page. 我没有收到令牌,而只是获取登录页面。 I am not sure what else I need to do in order to authenticate my request. 我不确定我需要做什么才能验证我的请求。 My code is pasted below... but maybe I'm doing it totally wrong and there's something I don't know about? 我的代码粘贴在下面...但也许我做错了,而且我不知道的是什么?

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);

I have also tried another approach, which also doesn't work. 我也尝试过另一种方法,但也行不通。 This uses WCF. 这使用WCF。 I get the error: 我收到错误:

Secure channel cannot be opened because security negotiation with the remote endpoint has failed.This may be due to absent or incorrectly specified EndpointIdentity in the EndpointAddress used to create the channel. 无法打开安全通道,因为与远程端点的安全协商失败。这可能是由于在用于创建通道的EndpointAddress中缺少或错误指定了EndpointIdentity。 Please verify the EndpointIdentity specified or implied by the EndpointAddress correctly identifies the remote endpoint. 请验证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;

Most likely the problem is in: string url = "{url of website}"; 最有可能的问题是: string url = "{url of website}"; . And/or missing parameters in the POST. 和/或POST中缺少参数。

It shouldn't be just any URL. 它不应该只是任何URL。 It should be a properly formatted WS-Federation request. 它应该是格式正确的WS-Federation请求。 With timestamps etc. etc. And normally/sometimes (in current ADFS) it is a two step process. 有时间戳等等。通常/有时(在当前的ADFS中)它是一个两步过程。 First the normal request, then the real (uid+pwd) authentication. 首先是正常请求,然后是真实(uid + pwd)认证。 Both with proper WS-Fed parameters in the proper places. 两者都在适当的位置使用适当的WS-Fed参数。 Only uid and pwd is not enough. 只有uid和pwd是不够的。

Now the obvious reply, no insult intended: I suggest you make a trace of the regular logon process and then compare those exact HTTP requests with your requests. 现在明显的答复,没有任何侮辱:我建议您跟踪常规登录过程,然后将这些确切的HTTP请求与您的请求进行比较。

Forms Authentication in ASP.NET relies on cookies by default. ASP.NET中的表单身份验证默认情况下依赖于Cookie。 Once the user is signed in to an Application the runtime can issue a cookie on the browser. 用户登录到应用程序后,运行时可以在浏览器上发出cookie。 The browser will then send the cookie with every subsequent request to the application. 然后,浏览器将向每个后续请求发送cookie给应用程序。 ASP.NET will see the cookie and know that the user is already authenticate and does not need to sign on again. ASP.NET将看到cookie并知道用户已经过身份验证,无需再次登录。

So you need something like this with or without WebRequest.Credentials : 无论有没有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()
}

I wish to solve your problem. 我希望解决你的问题。

You have to first request to ADFS to identify your self , accept a token back, and Than send the request to your application including the token inside (as a cookie) 您必须首先请求ADFS识别您的自己,接受令牌,然后将请求发送到您的应用程序,包括内部令牌(作为cookie)

I suggest you use Fiddler to capture the request sent from Browser, and see which parts of your request are missing 我建议您使用Fiddler捕获从浏览器发送的请求,并查看您的请求的哪些部分缺失

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

相关问题 使用adfs 2.0被动身份验证从Web应用程序调用时,带有webhttpbinding的WCF服务调用不起作用 - wcf service call with webhttpbinding not working when calling from web application when using adfs 2.0 passive authentication ADFS 2.0 Web 应用注销 - ADFS 2.0 Web app signout jQuery ajax调用Web服务(asmx)会触发身份验证弹出窗口 - jQuery ajax call to web service (asmx) triggers an authentication popup 从Web API调用具有表单身份验证的MVC服务 - Call MVC Service with Forms Authentication from Web API Sharepoint在处理Web服务呼叫时要求身份验证 - Sharepoint asks for authentication while processing a web service call 当 Windows 身份验证打开时,使用 ajax 调用 web 服务? - Using ajax to call a web service when Windows Authentication turned on? 在同一ASP.NET网站中进行表单身份验证和联合身份验证(单点登录+ ADFS 2.0 + SAML) - Forms authentication and Federation Authentication(Single Sign On + ADFS 2.0 + SAML) in Same ASP.NET Website 从非Web客户端调用ASP.NET 2.0身份验证服务 - Calling ASP.NET 2.0 authentication service from non-web client 如何从ASP.NET 2.0 Web应用程序中的客户端脚本调用ASP.NET Web服务? - How to call an ASP.NET web service from client script in an ASP.NET 2.0 web application? Web 服务 - Windows 认证 - Web Service - Windows Authentication
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM