LibGit2Sharp and Authentication UI

末鹿安然 提交于 2020-01-14 14:18:10

问题


I'm working with LibGit2Sharp to add a number of Git operations to an application. I've added the Microsoft.Alm.Authentication to help with Authentication and credential manager access. It works great for retrieving credentials that are already entered from the command line.

However is there any way to also hook into the Credential Manager's Login UI that prompts for username and password for Github, BitBucket and VSTS. This UI pops up automatically from the command line, but doesn't fire when using LibGit2Sharp.

I've looked at the GitCredentialManager project on Github and I can see the components that provide the UI, but before trying to figure out how to hook those in explicitly, is there some way I'm missing that this is provided as part of the Microsoft.Alm.Authentication (or related package)? Or can anybody point to an example or guidance on how to best hook this up?


回答1:


Unfortunately, there's no functionality in libgit2 (or LibGit2Sharp) to talk directly to the git-credential-helper functionality, which is what git itself uses to perform this action.

Instead, you can set a CredentialsHandler on your PushOptions (or FetchOptions), eg:

options.CredentialsProvider = (url, usernameFromUrl, types) => {
    string username, password;

    Uri uri = new Uri(url);   
    string hostname = uri.Host;

    ProcessStartInfo startInfo = new ProcessStartInfo();
    startInfo.UseShellExecute = false;

    startInfo.RedirectStandardInput = true;
    startInfo.RedirectStandardOutput = true;
    startInfo.RedirectStandardError = true;

    startInfo.FileName = "git.exe";
    startInfo.Arguments = "credential fill";

    Process process = new Process();
    process.StartInfo = startInfo;
    process.Start();

    process.StandardInput.WriteLine("hostname={0}", hostname);
    process.StandardInput.WriteLine("username={0}", usernameFromUrl);

    while ((line = process.StandardOutput.ReadLine()) != null)
    {
        string[] details = line.Split('=', 2);
        if (details[0] == "username")
        {
            username = details[1];
        }
        else if (details[0] == "password")
        {
            password = details[1];
        }
    }

    return new UsernamePasswordCredentials(username, password);
};



回答2:


I managed to get your solution working with some minor modifications. I paste here a sample code to push using git credentials. It works using the credentials already stored in the computer and prompts for credentials the first time with UI.

Only problem I'm having so far is when user is prompt for credentials and they enter an invalid user/password. Git writes to the console asking for user/pass and the process is not finished until you input that. Tried to monitor StandardError/Output with no success. I get the error text in stderror but only after filling that manually.

public void PushLibGit2Sharp(string repositoryFolder, string branch)
{
    using (var repo = new Repository(repositoryFolder))
    {
        var options = new PushOptions
        {
            CredentialsProvider = (url, usernameFromUrl, types) =>
            {
                ProcessStartInfo startInfo = new ProcessStartInfo
                {
                    FileName = "git.exe",
                    Arguments = "credential fill",
                    UseShellExecute = false,
                    WindowStyle = ProcessWindowStyle.Hidden,
                    CreateNoWindow = true,
                    RedirectStandardInput = true,
                    RedirectStandardOutput = true,
                    RedirectStandardError = true
                };

                Process process = new Process
                {
                    StartInfo = startInfo
                };

                process.Start();

                // Write query to stdin. 
                // For stdin to work we need to send \n instead of WriteLine
                // We need to send empty line at the end
                var uri = new Uri(url);
                process.StandardInput.NewLine = "\n";       
                process.StandardInput.WriteLine($"protocol={uri.Scheme}");
                process.StandardInput.WriteLine($"host={uri.Host}");
                process.StandardInput.WriteLine($"path={uri.AbsolutePath}");
                process.StandardInput.WriteLine();

                // Get user/pass from stdout
                string username = null;
                string password = null;
                string line;
                while ((line = process.StandardOutput.ReadLine()) != null)
                {
                    string[] details = line.Split('=');
                    if (details[0] == "username")
                    {
                        username = details[1];
                    }
                    else if (details[0] == "password")
                    {
                        password = details[1];
                    }
                }

                return new UsernamePasswordCredentials()
                {
                    Username = username,
                    Password = password
                };
            }
        };

        repo.Network.Push(repo.Branches[branch], options);
    }
}


来源:https://stackoverflow.com/questions/50010941/libgit2sharp-and-authentication-ui

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!