博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
ASP.NET Core 开源GitServer 实现自己的GitHub
阅读量:6974 次
发布时间:2019-06-27

本文共 10645 字,大约阅读时间需要 35 分钟。

ASP.NET Core 2.0 开源Git HTTP Server,实现类似 GitHub、GitLab。

GitHub:

设置

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

需要先安装Git,并确保git 命令可以执行,GitPath 可以是 git 的绝对路径。

目前实现的功能

  • 创建仓库
  • 浏览仓库
  • git客户端push pull
  • 数据库支持 SQLite、MSSQL、MySQL
  • 支持用户管理仓库

更多功能可以查看readme,也欢迎大家贡献支持。

Git交互

LibGit2Sharp 用于操作Git库,实现创建读取仓库信息及删除仓库。

以下是主要代码:

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

 

执行Git命令

git-upload-pack 

git-receive-pack

主要代码 GitCommandResult 实现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 基本认证实现

git http 默认的认证为Basic 基本认证,所以这里实现Basic 基本认证。

在ASP.NET Core 2.0 中 Authentication 变化很大之前1.0的一些代码是无法使用。

首先实现 AuthenticationHandler,然后实现  AuthenticationSchemeOptions,创建 BasicAuthenticationOptions。

最主要就是这两个类,下面两个类为辅助类,用于配置和中间件注册。

更多可以查看官方文档

身份验证

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
2 { 3 public BasicAuthenticationHandler(IOptionsMonitor
options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock) 4 : base(options, logger, encoder, clock) 5 { } 6 protected async override Task
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
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
SignInAsync(string userName, string password)63 {64 using (var serviceScope = ServiceCollection.BuildServiceProvider().CreateScope())65 {66 var _user = serviceScope.ServiceProvider.GetService
>();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
configureOptions)88 => builder.AddBasic(BasicAuthenticationDefaults.AuthenticationScheme, configureOptions);89 90 public static AuthenticationBuilder AddBasic(this AuthenticationBuilder builder, string authenticationScheme, Action
configureOptions)91 => builder.AddBasic(authenticationScheme, displayName: null, configureOptions: configureOptions);92 93 public static AuthenticationBuilder AddBasic(this AuthenticationBuilder builder, string authenticationScheme, string displayName, Action
configureOptions)94 {95 builder.Services.TryAddEnumerable(ServiceDescriptor.Singleton
, BasicAuthenticationOptions>());96 return builder.AddScheme
(authenticationScheme, displayName, configureOptions);97 }98 }
View Code

 

CookieAuthentication Cookie认证

实现自定义登录,无需identity ,实现注册登录。

主要代码:

启用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";            })

登录

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

官方文档介绍:https://docs.microsoft.com/zh-cn/aspnet/core/security/authentication/cookie?tabs=aspnetcore2x

部署说明

发布后配置数据库及git目录(可以为绝对地址和命令)、git 仓库目录。

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

运行后注册账户,登录账户创建仓库,然后根据提示操作,随后git push、git pull 都可以。

 

转载地址:http://pxesl.baihongyu.com/

你可能感兴趣的文章
php实现简单视图模板(视图引擎)
查看>>
[改善Java代码]多线程使用Vector或HashTable
查看>>
js事件之event.preventDefault()与event.stopPropagation()用法区别
查看>>
Ubuntu 上 执行命令 java -version 显示 没有那个文件或目录
查看>>
jQuery补充之jQuery扩展/form表单提交/滚动菜单
查看>>
Html5拖拽复制
查看>>
RDLC报表格式化format表达式
查看>>
ArcMap属性的列菜单简介
查看>>
【2011.9.20】基于CXF Web Service:Apache CXF简单部署 .
查看>>
jquery Flexigrid的使用
查看>>
Inotify + rsync
查看>>
中风从水治案
查看>>
SQL Server 内存使用量下降问题
查看>>
嵌入式驱动开发之dsp fpga通信接口---spi串行外围接口、emif sram接口
查看>>
网络协议之socks---子网和公网的穿透
查看>>
Java控制语句——if语句
查看>>
BadUSB的防范研究
查看>>
网站flash黑屏问题
查看>>
JAVA TIMER定时器
查看>>
CCF-201512-3 绘图
查看>>