parent
9fbb2f1141
commit
d0a8b5f78f
|
|
@ -102,14 +102,48 @@ namespace Microsoft.AspNetCore.Mvc.Routing
|
|||
/// <inheritdoc />
|
||||
public virtual bool IsLocalUrl(string url)
|
||||
{
|
||||
return
|
||||
!string.IsNullOrEmpty(url) &&
|
||||
if (string.IsNullOrEmpty(url))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Allows "/" or "/foo" but not "//" or "/\".
|
||||
((url[0] == '/' && (url.Length == 1 || (url[1] != '/' && url[1] != '\\'))) ||
|
||||
// Allows "/" or "/foo" but not "//" or "/\".
|
||||
if (url[0] == '/')
|
||||
{
|
||||
// url is exactly "/"
|
||||
if (url.Length == 1)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// Allows "~/" or "~/foo".
|
||||
(url.Length > 1 && url[0] == '~' && url[1] == '/'));
|
||||
// url doesn't start with "//" or "/\"
|
||||
if (url[1] != '/' && url[1] != '\\')
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Allows "~/" or "~/foo" but not "~//" or "~/\".
|
||||
if (url[0] == '~' && url.Length > 1 && url[1] == '/')
|
||||
{
|
||||
// url is exactly "~/"
|
||||
if (url.Length == 2)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// url doesn't start with "~//" or "~/\"
|
||||
if (url[2] != '/' && url[2] != '\\')
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ using Microsoft.AspNetCore.Http;
|
|||
using Microsoft.AspNetCore.Http.Internal;
|
||||
using Microsoft.AspNetCore.Mvc.Abstractions;
|
||||
using Microsoft.AspNetCore.Mvc.Infrastructure;
|
||||
using Microsoft.AspNetCore.Mvc.Internal;
|
||||
using Microsoft.AspNetCore.Mvc.Routing;
|
||||
using Microsoft.AspNetCore.Routing;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
|
@ -87,6 +86,10 @@ namespace Microsoft.AspNetCore.Mvc
|
|||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("", "//", "/test")]
|
||||
[InlineData("", "/\\", "/test")]
|
||||
[InlineData("", "//foo", "/test")]
|
||||
[InlineData("", "/\\foo", "/test")]
|
||||
[InlineData("", "Home/About", "/Home/About")]
|
||||
[InlineData("/myapproot", "http://www.example.com", "/test")]
|
||||
public async Task Execute_Throws_ForNonLocalUrl(
|
||||
|
|
@ -111,6 +114,33 @@ namespace Microsoft.AspNetCore.Mvc
|
|||
exception.Message);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("", "~//", "//")]
|
||||
[InlineData("", "~/\\", "/\\")]
|
||||
[InlineData("", "~//foo", "//foo")]
|
||||
[InlineData("", "~/\\foo", "/\\foo")]
|
||||
public async Task Execute_Throws_ForNonLocalUrlTilde(
|
||||
string appRoot,
|
||||
string contentPath,
|
||||
string expectedPath)
|
||||
{
|
||||
// Arrange
|
||||
var httpResponse = new Mock<HttpResponse>();
|
||||
httpResponse.Setup(o => o.Redirect(expectedPath, false))
|
||||
.Verifiable();
|
||||
|
||||
var httpContext = GetHttpContext(appRoot, contentPath, expectedPath, httpResponse.Object);
|
||||
var actionContext = GetActionContext(httpContext);
|
||||
var result = new LocalRedirectResult(contentPath);
|
||||
|
||||
// Act & Assert
|
||||
var exception = await Assert.ThrowsAsync<InvalidOperationException>(() => result.ExecuteResultAsync(actionContext));
|
||||
Assert.Equal(
|
||||
"The supplied URL is not local. A URL with an absolute path is considered local if it does not " +
|
||||
"have a host/authority part. URLs using virtual paths ('~/') are also local.",
|
||||
exception.Message);
|
||||
}
|
||||
|
||||
private static ActionContext GetActionContext(HttpContext httpContext)
|
||||
{
|
||||
var routeData = new RouteData();
|
||||
|
|
|
|||
|
|
@ -261,6 +261,40 @@ namespace Microsoft.AspNetCore.Mvc.Routing
|
|||
Assert.False(result);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("~//www.example.com")]
|
||||
[InlineData("~//www.example.com?")]
|
||||
[InlineData("~//www.example.com:80")]
|
||||
[InlineData("~//www.example.com/foobar.html")]
|
||||
[InlineData("~///www.example.com")]
|
||||
[InlineData("~//////www.example.com")]
|
||||
public void IsLocalUrl_RejectsTokenUrlsWithMissingSchemeName(string url)
|
||||
{
|
||||
// Arrange
|
||||
var helper = CreateUrlHelper("www.mysite.com");
|
||||
|
||||
// Act
|
||||
var result = helper.IsLocalUrl(url);
|
||||
|
||||
// Assert
|
||||
Assert.False(result);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("~/\\")]
|
||||
[InlineData("~/\\foo")]
|
||||
public void IsLocalUrl_RejectsInvalidTokenUrls(string url)
|
||||
{
|
||||
// Arrange
|
||||
var helper = CreateUrlHelper("www.mysite.com");
|
||||
|
||||
// Act
|
||||
var result = helper.IsLocalUrl(url);
|
||||
|
||||
// Assert
|
||||
Assert.False(result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RouteUrlWithDictionary()
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in New Issue