在.Net Core 3.1中使用重定向和Cookies复制cURL命令 [英] Replicate cURL Command Using Redirect and Cookies in .Net Core 3.1

查看:40
本文介绍了在.Net Core 3.1中使用重定向和Cookies复制cURL命令的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这似乎是一个远射.但是我已经看到了几个答案,它们表明在.Net Core应用程序中需要cURL时应使用HttpClient(及类似名称).

This one seems a long shot. But I have seen several answers that indicate that HttpClient (and similar) should be used when cURL is needed in a .Net Core Application.

我有以下cURL命令(效果很好):

I have the following cURL command (that works perfectly):

curl -v -L --negotiate -u : -b ~/cookiejar.txt  "https://idp.domain.net/oauth2/authorize?scope=openid&response_type=code&redirect_uri=https://localhost:5001&client_id=client_id_here"

此命令的流程如下:

  1. 加载提供的网址( https://idp.domain.net/oauth2/授权....)
  2. 获取302响应以重定向到 https://idp.domain.net/iwa-kerberos?state = state_guid_here
    • 因为存在 -L 选项,所以它遵循了重定向
  1. Loads the provided url (https://idp.domain.net/oauth2/authorize....)
  2. Gets a 302 response to redirect to https://idp.domain.net/iwa-kerberos?state=state_guid_here
    • Because the -L option is there, it follows the redirect
  • 由于使用 -b 选项,因此cURL提取了cookie.
  • Because of the -b option, the cookie is picked up by cURL.

将所有内容全部写完,要使它在.Net应用程序中工作似乎是一项严肃的工作.但是我想我会问一下它是否内置在框架中.

Writing this all out, it seems like a serious undertaking to get this to work in a .Net Application. But I figured I would ask in case it is built in to the framework somewhere.

是否存在.Net Core Framework类(或类似类),可以让我用C#代码重现此cURL命令?

注意:我可以通过调用powershell来做到这一点.这个问题是关于使用 HttpClient 来实现的.

NOTE: I am able to do it by calling out to powershell. This question is about doing it with HttpClient.

推荐答案

我能够构建一个自定义方法来完成我需要的调用(获取OAuth 2身份验证代码).

I was able to build a custom purpose method that completed the call I needed (to get an OAuth 2 Auth Code).

Cookies是自动添加的,但是我是否添加 CookieContainer UseCookies 设置似乎并不重要.

The Cookies got added automatically, but it did not seem to matter if I added the CookieContainer and UseCookies settings or not.

此外, UseDefaultCredentials 似乎也没有任何作用.

Also, UseDefaultCredentials did not seem to do anything either.

async Task Main()
{   
    var services = new ServiceCollection();
    services.AddHttpClient("OAuthClient").ConfigurePrimaryHttpMessageHandler(() => new AuthenticationHandler());;
    var serviceProvider = services.BuildServiceProvider();  
    var httpClientFactory = serviceProvider.GetService<IHttpClientFactory>();   
    
    var authCodeUrl = "https://idp.domain.net/oauth2/authorize?scope=openid&response_type=code&redirect_uri=https://localhost:5001&client_id=client_id_here";
    var authNegotiator = new AuthenticaitonNegotiator(httpClientFactory);
    
    var authCode = await authNegotiator.GetAuthorizationCodeViaKerberosIwa(authCodeUrl);    
    Console.WriteLine(authCode);
}


public class AuthenticaitonNegotiator
{
    private IHttpClientFactory httpClientFactory;
    
    public AuthenticaitonNegotiator(IHttpClientFactory httpClientFactory)
    {
        this.httpClientFactory = httpClientFactory; 
    }
    
    public async Task<string> GetAuthorizationCodeViaKerberosIwa(string authCodeUrl)
    {
        var kerberosToken = GetKerberosTokenViaIwa();
        var authCode = await GetAuthorizationCodeViaKerberos(authCodeUrl, kerberosToken);
        return authCode;
    }

    public async Task<string> GetAuthorizationCodeViaKerberosCredsAsync(string authCodeUrl, string username, string password)
    {
        var kerberosToken = await GetKerberosTokenViaCredsAsync(username, password);
        var authCode = await GetAuthorizationCodeViaKerberos(authCodeUrl, kerberosToken);
        return authCode;
    }

    public async Task<string> GetAuthorizationCodeViaKerberos(string authCodeUrl, string kerberosToken)
    {
        var httpClient = httpClientFactory.CreateClient("OAuthClient");
        
        var done = false;
        string currentUrl = authCodeUrl;
        string responseText = "";
        bool wasSuccessful = false;
        while (!done)
        {           
            var response = await httpClient.GetAsync(currentUrl);
            responseText = await response.Content.ReadAsStringAsync();
            // Reset the authenticaiton header if it was set.  (It gets set as needed on each iteration.)
            httpClient.DefaultRequestHeaders.Authorization = null;          

            if (response.StatusCode == HttpStatusCode.Unauthorized
                && response.Headers.Any(x => x.Key == "WWW-Authenticate" && x.Value.Contains("Negotiate")))
            {
                currentUrl = response.RequestMessage.RequestUri.AbsoluteUri;                                        
                httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Negotiate", kerberosToken);
            }
            else if (response.StatusCode == HttpStatusCode.Redirect)
            {
                var redirectUri = response.Headers.Location;
                var query = HttpUtility.ParseQueryString(redirectUri.Query);
                var code = query.Get("code");
                if (code == null)
                {
                    currentUrl = redirectUri.AbsoluteUri;
                }
                else
                {
                    // If this is the last redirect where we would send to the callback, just grab the auth code.
                    // This saves us from needing to host a service to handle the callback.
                    responseText = code;
                    done = true;
                    wasSuccessful = true;
                }
            }
            else
            {
                done = true;
                wasSuccessful = false;
            }
        }
        
        if (wasSuccessful == false) 
        {
            throw new ApplicationException($"Failed to retrive authorization code: \r\n {responseText}");
        }
        
        return responseText;        
    }

    public async Task<String> GetKerberosTokenViaCredsAsync(string username, string password)
    {
        var client = new KerberosClient();
        var kerbCred = new KerberosPasswordCredential(username, password, "YourDomain.net");
        await client.Authenticate(kerbCred);
        var ticket = await client.GetServiceTicket("http/ServerToGetTheKerberosToken.YourDomain.net");
        return Convert.ToBase64String(ticket.EncodeGssApi().ToArray());
    }

    public string GetKerberosTokenViaIwa()
    {
        string token = "";
        using (var context = new SspiContext($"http/ServerToGetTheKerberosToken.YourDomain.net", "Negotiate"))
        {
            var tokenBytes = context.RequestToken();

            token = Convert.ToBase64String(tokenBytes);
        }
        return token;
    }
}


public class AuthenticationHandler : HttpClientHandler
{
    public AuthenticationHandler()
    {       
        // cURL Equivilant: -L
        AllowAutoRedirect = true;
        MaxAutomaticRedirections = 100;

        // cURL Equivilant: --negotiate -u :
        UseDefaultCredentials = true;

        // cURL Equivilant: -b ~/cookiejar.txt
        CookieContainer = new CookieContainer();
        UseCookies = true;
    }

}

如果添加以下NuGet软件包,它将在LinqPad中运行:

This runs in LinqPad if you add the following NuGet Packages:

  • Kerberos.NET
  • Microsoft.Extensions.DependencyInjection
  • Microsoft.Extensions.Http

我还具有以下使用"声明:

I also had the following "using" statements:

  • 系统

System.Collections

System.Collections

System.Collections.Generic

System.Collections.Generic

System.Data

System.Data

System.Diagnostics

System.Diagnostics

System.IO

System.IO

System.Linq

System.Linq

System.Linq.Expressions

System.Linq.Expressions

System.Reflection

System.Reflection

System.Text

System.Text

System.Text.RegularExpressions

System.Text.RegularExpressions

System.Threading

System.Threading

System.Transactions

System.Transactions

System.Xml

System.Xml

System.Xml.Linq

System.Xml.Linq

System.Xml.XPath

System.Xml.XPath

Kerberos.NET

Kerberos.NET

Kerberos.NET.Client

Kerberos.NET.Client

Kerberos.NET.Credentials

Kerberos.NET.Credentials

Kerberos.NET.Entities

Kerberos.NET.Entities

Kerberos.NET.Win32

Kerberos.NET.Win32

Microsoft.Extensions.DependencyInjection

Microsoft.Extensions.DependencyInjection

Microsoft.Extensions.Http

Microsoft.Extensions.Http

System.Net

System.Net

System.Net.Http

System.Net.Http

System.Net.Http.Headers

System.Net.Http.Headers

System.Threading.Tasks

System.Threading.Tasks

System.Web

System.Web

这篇关于在.Net Core 3.1中使用重定向和Cookies复制cURL命令的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆