ASP. NET Core open-source GitServer implements its own GitHub, gitservergithub

Source: Internet
Author: User

ASP. NET Core open-source GitServer implements its own GitHub, gitservergithub

ASP. NET Core 2.0 open source Git HTTP Server, implementation is similar to GitHub, GitLab.

GitHub: https://github.com/linezero/GitServer

Set

  "GitSettings": {    "BasePath": "D:\\Git",    "GitPath": "git"  }

Install Git first and make sure that the git command can be executed. GitPath can be the absolute path of git.

Current functions

  • Create a repository
  • Browse warehouse
  • Git client push pull
  • The Database supports SQLite, MSSQL, and MySQL.
  • Allows users to manage warehouses.

For more functions, see readme. You are also welcome to contribute your support.

Git Interaction

LibGit2Sharp is used to operate the Git library to create and read the Repository Information and delete the repository.

The main code is as follows:

        public Repository CreateRepository(string name)        {            string path = Path.Combine(Settings.BasePath, name);            Repository repo = new Repository(Repository.Init(path, true));            return repo;        }        public Repository CreateRepository(string name, string remoteUrl)        {            var path = Path.Combine(Settings.BasePath, name);            try            {                using (var repo = new Repository(Repository.Init(path, true)))                {                    repo.Config.Set("core.logallrefupdates", true);                    repo.Network.Remotes.Add("origin", remoteUrl, "+refs/*:refs/*");                    var logMessage = "";                    foreach (var remote in repo.Network.Remotes)                    {                        IEnumerable<string> refSpecs = remote.FetchRefSpecs.Select(x => x.Specification);                        Commands.Fetch(repo, remote.Name, refSpecs, null, logMessage);                    }                    return repo;                }                            }            catch            {                try                {                    Directory.Delete(path, true);                }                catch { }                return null;            }        }        public void DeleteRepository(string name)        {            Exception e = null;            for(int i = 0; i < 3; i++)            {                try                {                    string path = Path.Combine(Settings.BasePath, name);                    Directory.Delete(path, true);                }                catch(Exception ex) { e = ex; }            }            if (e != null)                throw new GitException("Failed to delete repository", e);        }

 

Execute Git commands

Git-upload-pack

Git-receive-pack

The main code is GitCommandResult to implement IActionResult.

public async Task ExecuteResultAsync(ActionContext context)        {            HttpResponse response = context.HttpContext.Response;            Stream responseStream = GetOutputStream(context.HttpContext);            string contentType = $"application/x-{Options.Service}";            if (Options.AdvertiseRefs)                contentType += "-advertisement";            response.ContentType = contentType;            response.Headers.Add("Expires", "Fri, 01 Jan 1980 00:00:00 GMT");            response.Headers.Add("Pragma", "no-cache");            response.Headers.Add("Cache-Control", "no-cache, max-age=0, must-revalidate");            ProcessStartInfo info = new ProcessStartInfo(_gitPath, Options.ToString())            {                UseShellExecute = false,                CreateNoWindow = true,                RedirectStandardInput = true,                RedirectStandardOutput = true,                RedirectStandardError = true            };            using (Process process = Process.Start(info))            {                GetInputStream(context.HttpContext).CopyTo(process.StandardInput.BaseStream);                if (Options.EndStreamWithNull)                    process.StandardInput.Write('\0');                process.StandardInput.Dispose();                using (StreamWriter writer = new StreamWriter(responseStream))                {                    if (Options.AdvertiseRefs)                    {                        string service = $"# service={Options.Service}\n";                        writer.Write($"{service.Length + 4:x4}{service}0000");                        writer.Flush();                    }                    process.StandardOutput.BaseStream.CopyTo(responseStream);                }                process.WaitForExit();            }        }

 

BasicAuthentication Basic Authentication implementation

Git http performs Basic authentication by default.

In ASP. NET Core 2.0, the Authentication changes significantly. Some code in earlier versions cannot be used.

Implement AuthenticationHandler first, implement AuthenticationSchemeOptions, and create BasicAuthenticationOptions.

These two classes are the most important ones. The following two classes are helper classes for configuration and middleware registration.

For more information, see the official documentation.

Authentication

Https://docs.microsoft.com/zh-cn/aspnet/core/security/authentication/

Https://docs.microsoft.com/zh-cn/aspnet/core/migration/1x-to-2x/identity-2x

 1    public class BasicAuthenticationHandler : AuthenticationHandler<BasicAuthenticationOptions> 2     { 3         public BasicAuthenticationHandler(IOptionsMonitor<BasicAuthenticationOptions> options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock) 4             : base(options, logger, encoder, clock) 5         { } 6         protected async override Task<AuthenticateResult> HandleAuthenticateAsync() 7         { 8             if (!Request.Headers.ContainsKey("Authorization")) 9                 return AuthenticateResult.NoResult();10 11             string authHeader = Request.Headers["Authorization"];12             if (!authHeader.StartsWith("Basic ", StringComparison.OrdinalIgnoreCase))13                 return AuthenticateResult.NoResult();14 15             string token = authHeader.Substring("Basic ".Length).Trim();16             string credentialString = Encoding.UTF8.GetString(Convert.FromBase64String(token));17             string[] credentials = credentialString.Split(':');18 19             if (credentials.Length != 2)20                 return AuthenticateResult.Fail("More than two strings seperated by colons found");21 22             ClaimsPrincipal principal = await Options.SignInAsync(credentials[0], credentials[1]);23 24             if (principal != null)25             {26                 AuthenticationTicket ticket = new AuthenticationTicket(principal, new AuthenticationProperties(), BasicAuthenticationDefaults.AuthenticationScheme);27                 return AuthenticateResult.Success(ticket);28             }29 30             return AuthenticateResult.Fail("Wrong credentials supplied");31         }32         protected override Task HandleForbiddenAsync(AuthenticationProperties properties)33         {34             Response.StatusCode = 403;35             return base.HandleForbiddenAsync(properties);36         }37 38         protected override Task HandleChallengeAsync(AuthenticationProperties properties)39         {40             Response.StatusCode = 401;41             string headerValue = $"{BasicAuthenticationDefaults.AuthenticationScheme} realm=\"{Options.Realm}\"";42             Response.Headers.Append(Microsoft.Net.Http.Headers.HeaderNames.WWWAuthenticate, headerValue);43             return base.HandleChallengeAsync(properties);44         }45     }46 47     public class BasicAuthenticationOptions : AuthenticationSchemeOptions, IOptions<BasicAuthenticationOptions>48     {49         private string _realm;50 51         public IServiceCollection ServiceCollection { get; set; }52         public BasicAuthenticationOptions Value => this;53         public string Realm54         {55             get { return _realm; }56             set57             {58                 _realm = value;59             }60         }61 62         public async Task<ClaimsPrincipal> SignInAsync(string userName, string password)63         {64             using (var serviceScope = ServiceCollection.BuildServiceProvider().CreateScope())65             {66                 var _user = serviceScope.ServiceProvider.GetService<IRepository<User>>();67                 var user = _user.List(r => r.Name == userName && r.Password == password).FirstOrDefault();68                 if (user == null)69                     return null;70                 var identity = new ClaimsIdentity(BasicAuthenticationDefaults.AuthenticationScheme, ClaimTypes.Name, ClaimTypes.Role);71                 identity.AddClaim(new Claim(ClaimTypes.Name, user.Name));72                 var principal = new ClaimsPrincipal(identity);73                 return principal;74             }75         }76     }77 78     public static class BasicAuthenticationDefaults79     {80         public const string AuthenticationScheme = "Basic";81     }82     public static class BasicAuthenticationExtensions83     {84         public static AuthenticationBuilder AddBasic(this AuthenticationBuilder builder)85             => builder.AddBasic(BasicAuthenticationDefaults.AuthenticationScheme, _ => { _.ServiceCollection = builder.Services;_.Realm = "GitServer"; });86 87         public static AuthenticationBuilder AddBasic(this AuthenticationBuilder builder, Action<BasicAuthenticationOptions> configureOptions)88             => builder.AddBasic(BasicAuthenticationDefaults.AuthenticationScheme, configureOptions);89 90         public static AuthenticationBuilder AddBasic(this AuthenticationBuilder builder, string authenticationScheme, Action<BasicAuthenticationOptions> configureOptions)91             => builder.AddBasic(authenticationScheme, displayName: null, configureOptions: configureOptions);92 93         public static AuthenticationBuilder AddBasic(this AuthenticationBuilder builder, string authenticationScheme, string displayName, Action<BasicAuthenticationOptions> configureOptions)94         {95             builder.Services.TryAddEnumerable(ServiceDescriptor.Singleton<IOptions<BasicAuthenticationOptions>, BasicAuthenticationOptions>());96             return builder.AddScheme<BasicAuthenticationOptions, BasicAuthenticationHandler>(authenticationScheme, displayName, configureOptions);97         }98     }
View Code

 

CookieAuthentication Cookie Authentication

User-Defined logon without identity.

Main Code:

Enable Cookie

Https://github.com/linezero/GitServer/blob/master/GitServer/Startup.cs#L60

services.AddAuthentication(options =>            {                options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;                options.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme;            }).AddCookie(options=> {                options.AccessDeniedPath = "/User/Login";                options.LoginPath = "/User/Login";            })

Login

Https://github.com/linezero/GitServer/blob/master/GitServer/Controllers/UserController.cs#L34

                    var identity = new ClaimsIdentity(CookieAuthenticationDefaults.AuthenticationScheme, ClaimTypes.Name, ClaimTypes.Role);                    identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, user.Name));                    identity.AddClaim(new Claim(ClaimTypes.Name, user.Name));                    identity.AddClaim(new Claim(ClaimTypes.Email, user.Email));                    var principal = new ClaimsPrincipal(identity);                    await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, principal);

Official Document Introduction: https://docs.microsoft.com/zh-cn/aspnet/core/security/authentication/cookie? Tabs = aspnetcore2x

Deployment description

After the release, configure the database and git directory (which can be an absolute address and command) and git repository directory.

{  "ConnectionStrings": {    "ConnectionType": "Sqlite", //Sqlite,MSSQL,MySQL    "DefaultConnection": "Filename=gitserver.db"  },  "GitSettings": {    "BasePath": "D:\\Git",    "GitPath": "git"  }}

After running the command, register an account, log on to the account to create a repository, and then follow the prompts to perform operations. Then, git push and git pull are all supported.

 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.