Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit5196c45

Browse files
authored
Merge pull request#6685 from duplicati/feature/improve-proxy-support
Improved support for authenticating behind a proxy
2 parentse5b72ef +ba3c5ea commit5196c45

File tree

5 files changed

+84
-32
lines changed

5 files changed

+84
-32
lines changed

‎Duplicati/Server/webroot/ngclient/package-lock.json‎

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more aboutcustomizing how changed files appear on GitHub.

‎Duplicati/Server/webroot/ngclient/package.json‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,6 @@
44
"description":"Modern Angular Client for Duplicati",
55
"license":"MIT",
66
"dependencies": {
7-
"@duplicati/ngclient":"^0.0.179"
7+
"@duplicati/ngclient":"^0.0.188"
88
}
99
}

‎Duplicati/WebserverCore/Endpoints/V1/Auth.cs‎

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ public static void Map(RouteGroupBuilder group)
126126
{
127127
case"export":
128128
case"bugreport":
129+
case"websocket":
129130
break;
130131

131132
default:
@@ -145,6 +146,30 @@ public static void Map(RouteGroupBuilder group)
145146

146147
returnnewDto.AccessTokenOutputDto(tokenProvider.CreateForeverToken(),null);
147148
}).RequireAuthorization();
149+
150+
group.MapPost("auth/status",([FromServices]IHttpContextAccessorhttpContextAccessor,[FromServices]IJWTTokenProvidertokenProvider)=>
151+
{
152+
varhttpContext=httpContextAccessor.HttpContext;
153+
varuser=httpContext?.User;
154+
varisAuthenticated=user?.Identity?.IsAuthenticated??false;
155+
156+
// Return 200, to avoid showing this probe as an error in browser devtools and logs
157+
if(!isAuthenticated)
158+
returnResults.Ok(new
159+
{
160+
authorized=false,
161+
message="Not authorized",
162+
});
163+
164+
165+
// If we are authenticated, we can return the socket token
166+
returnResults.Ok(new
167+
{
168+
authorized=true,
169+
message="Authorized",
170+
socketToken=tokenProvider.CreateSingleOperationToken("web-api","websocket"),
171+
});
172+
});
148173
}
149174

150175
privatestaticvoidAddCookie(HttpContextcontext,stringname,stringvalue,DateTimeOffsetexpires)

‎Duplicati/WebserverCore/Middlewares/StaticFilesMiddleware.cs‎

Lines changed: 46 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -51,34 +51,46 @@ public static class StaticFilesExtensions
5151
};
5252

5353
privateconststringFORWARDED_PREFIX_HEADER="X-Forwarded-Prefix";
54-
privateconststringDEFAULT_FORWARDED_PREFIX="/ngclient";
54+
privateconststringFORWARDED_PREFIX_HEADER_ALT="X-Forwarded-Prefix-Alt";
55+
privateconststringFORWARDED_PREFIX_HEADER_NGCLIENT="X-Forwarded-Prefix-Ngclient";
56+
privateconststringENABLE_IFRAME_HOSTING_HEADER="X-Allow-Iframe-Hosting";
57+
privateconststringENABLE_IFRAME_HOSTING_ENVIRONMENT_VARIABLE="DUPLICATI_ENABLE_IFRAME_HOSTING";
58+
privateconststringNGCLIENT_LOCATION="ngclient/";
5559

5660
privatesealedrecordSpaConfig(stringPrefix,stringFileContent,stringBasePath);
5761

5862
privatestaticreadonlyRegex_baseHrefRegex=newRegex(
59-
@"(<base\b[^>]*?\bhref\s*=\s*)(['""])\s*/\s*(?=\2)",
63+
@"(<base\b[^>]*?\bhref\s*=\s*)(['""])\s*[^'""]*\s*(?=\2)",
6064
RegexOptions.IgnoreCase|RegexOptions.Compiled);
6165

6266
privatestaticreadonlyRegex_headInjectRegex=newRegex(
6367
@"(</head\s*>)",
6468
RegexOptions.IgnoreCase|RegexOptions.Compiled|RegexOptions.Singleline);
6569

66-
privatestaticstringPatchIndexContent(stringfileContent,stringprefix)
70+
privatestaticstringPatchIndexContent(stringfileContent,stringprefix,stringngclientPrefix,boolenableIframeHosting)
6771
{
6872
if(!prefix.EndsWith("/"))
6973
prefix+="/";
7074

75+
if(string.IsNullOrWhiteSpace(ngclientPrefix))
76+
ngclientPrefix=$"{prefix}{NGCLIENT_LOCATION}";
77+
7178
varheadContent=string.Empty;
7279
if(!string.IsNullOrWhiteSpace(AutoUpdateSettings.CustomCssFilePath))
7380
headContent+=$"<link rel=\"stylesheet\" href=\"oem-custom.css\" />";
7481
if(!string.IsNullOrWhiteSpace(AutoUpdateSettings.CustomJsFilePath))
7582
headContent+=$"<script src=\"oem-custom.js\"></script>";
83+
if(!string.IsNullOrWhiteSpace(prefix))
84+
headContent+=$@"<meta name=""duplicati-proxy-config"" content=""{prefix}""/> ";
85+
if(enableIframeHosting)
86+
headContent+=$@"<meta name=""duplicati-enable-iframe-hosting"" content=""true""/> ";
87+
7688
fileContent=_headInjectRegex.Replace(fileContent,headContent+"</head>");
7789

7890
return_baseHrefRegex.Replace(fileContent, match=>
7991
{
8092
varquote=match.Groups[2].Value;
81-
return$"{match.Groups[1].Value}{quote}{prefix}";
93+
return$"{match.Groups[1].Value}{quote}{ngclientPrefix}";
8294
});
8395
}
8496

@@ -120,7 +132,7 @@ public static IApplicationBuilder UseDefaultStaticFiles(this WebApplication app,
120132
{
121133
prefixHandlerMap.Add(newSpaConfig(prefix,File.ReadAllText(fi.FullName),basepath));
122134
}
123-
#ifDEBUG
135+
#ifDEBUG
124136
else
125137
{
126138
// Install from NPM in debug mode for easier development
@@ -138,23 +150,10 @@ public static IApplicationBuilder UseDefaultStaticFiles(this WebApplication app,
138150
prefixHandlerMap=prefixHandlerMap.OrderByDescending(p=>p.Prefix.Length).ToList();
139151
app.Use(async(context,next)=>
140152
{
141-
awaitnext();
142-
143-
// Not found only
144-
if(context.Response.StatusCode!=404||context.Response.HasStarted)
145-
return;
146-
147-
// Check if we can use the path
148-
varpath=context.Request.Path;
149-
if(!path.HasValue)
150-
return;
151-
152153
// Check if the path is a SPA path
153-
varspaConfig=prefixHandlerMap.FirstOrDefault(p=>path.Value.StartsWith(p.Prefix));
154-
if(spaConfig==null)
155-
return;
156-
157-
if(string.IsNullOrEmpty(Path.GetExtension(path))||path.Value.EndsWith("/index.html"))
154+
varpath=context.Request.Path;
155+
varspaConfig=path.HasValue?prefixHandlerMap.FirstOrDefault(p=>path.Value.StartsWith(p.Prefix)):null;
156+
if(spaConfig!=null&&path.HasValue&&(string.IsNullOrEmpty(Path.GetExtension(path))||path.Value.EndsWith("/index.html")))
158157
{
159158
// Serve the index file
160159
context.Response.ContentType="text/html";
@@ -165,13 +164,34 @@ public static IApplicationBuilder UseDefaultStaticFiles(this WebApplication app,
165164
indexContent=File.ReadAllText(Path.Combine(spaConfig.BasePath,"index.html"));
166165
#endif
167166
varforwardedPrefix=context.Request.Headers[FORWARDED_PREFIX_HEADER].FirstOrDefault();
168-
if(string.IsNullOrEmpty(forwardedPrefix))
169-
forwardedPrefix=DEFAULT_FORWARDED_PREFIX;
167+
if(string.IsNullOrWhiteSpace(forwardedPrefix))
168+
forwardedPrefix=context.Request.Headers[FORWARDED_PREFIX_HEADER_ALT].FirstOrDefault();
169+
if(string.IsNullOrWhiteSpace(forwardedPrefix))
170+
forwardedPrefix="";
171+
172+
varngclientPrefix=context.Request.Headers[FORWARDED_PREFIX_HEADER_NGCLIENT].FirstOrDefault();
173+
if(string.IsNullOrWhiteSpace(ngclientPrefix))
174+
ngclientPrefix="";
170175

171-
awaitcontext.Response.WriteAsync(PatchIndexContent(indexContent,forwardedPrefix),context.RequestAborted);
176+
varenableIframeHosting=Library.Utility.Utility.ParseBool(context.Request.Headers[ENABLE_IFRAME_HOSTING_HEADER].FirstOrDefault(),false)
177+
||Library.Utility.Utility.ParseBool(Environment.GetEnvironmentVariable(ENABLE_IFRAME_HOSTING_ENVIRONMENT_VARIABLE),false);
178+
179+
awaitcontext.Response.WriteAsync(PatchIndexContent(indexContent,forwardedPrefix,ngclientPrefix,enableIframeHosting),context.RequestAborted);
172180
awaitcontext.Response.CompleteAsync();
181+
return;
173182
}
174-
elseif(path.Value.EndsWith("/oem-custom.css")&&(customCssFile?.Exists??false))
183+
184+
awaitnext();
185+
186+
// Handle not found only
187+
if(context.Response.StatusCode!=404||context.Response.HasStarted)
188+
return;
189+
190+
// Check if we can use the path
191+
if(!path.HasValue)
192+
return;
193+
194+
if(path.Value.EndsWith("/oem-custom.css")&&(customCssFile?.Exists??false))
175195
{
176196
// Serve the custom CSS file
177197
context.Response.ContentType="text/css";
@@ -187,7 +207,7 @@ public static IApplicationBuilder UseDefaultStaticFiles(this WebApplication app,
187207
awaitcontext.Response.SendFileAsync(newPhysicalFileInfo(customJsFile));
188208
awaitcontext.Response.CompleteAsync();
189209
}
190-
else
210+
elseif(spaConfig!=null)
191211
{
192212
// Serve the static file
193213
varfile=newFileInfo(Path.Combine(spaConfig.BasePath,path.Value.Substring(spaConfig.Prefix.Length).TrimStart('/')));

‎Duplicati/WebserverCore/Notifications/WebsocketAuthenticator.cs‎

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,8 +142,15 @@ public async Task HandleClientMessage(WebSocket socket, string messagestr)
142142
Exception?exception=null;
143143
try
144144
{
145+
try
146+
{
147+
isValid=jWTTokenProvider.ReadSingleOperationToken(message.Token).Operation=="websocket";
148+
}
149+
catch
150+
{
151+
}
145152
// Validate the token against the allowed tokens
146-
isValid=config.AllowedTokens.Contains(message.Token)||
153+
isValid=isValid||config.AllowedTokens.Contains(message.Token)||
147154
jWTTokenProvider.ReadAccessToken(message.Token)!=null;
148155
}
149156
catch(Exceptionex)

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp