使用 Asp.Net Core 中间件将非 WWW 重定向到 WWW

Posted

技术标签:

【中文标题】使用 Asp.Net Core 中间件将非 WWW 重定向到 WWW【英文标题】:Redirect Non WWW to WWW using Asp.Net Core Middleware 【发布时间】:2017-10-05 00:36:54 【问题描述】:

在 ASP.Net Core 应用程序启动时,我有:

RewriteOptions rewriteOptions = new RewriteOptions(); 

rewriteOptions.AddRedirectToHttps();

applicationBuilder.UseRewriter(rewriteOptions);

在生产中,我需要将所有非 WWW 重定向到 WWW 网址

例如:

domain.com/about > www.domain.com/about

如何使用重写中间件做到这一点?

我认为这可以使用 AddRedirect 和 Regex 来完成:

Github - ASP.NET Core Redirect Docs

但不知道怎么做...

【问题讨论】:

AddApacheModRewrite 在这种情况下有效吗? 【参考方案1】:

可重用的替代方法是创建自定义重写规则和相应的扩展方法,以将规则添加到重写选项。这与 AddRedirectToHttps 的工作方式非常相似。

自定义规则:

public class RedirectToWwwRule : IRule

    public virtual void ApplyRule(RewriteContext context)
    
        var req = context.HttpContext.Request;
        if (req.Host.Host.Equals("localhost", StringComparison.OrdinalIgnoreCase))
        
            context.Result = RuleResult.ContinueRules;
            return;
        

        if (req.Host.Value.StartsWith("www.", StringComparison.OrdinalIgnoreCase))
        
            context.Result = RuleResult.ContinueRules;
            return;
        

        var wwwHost = new HostString($"www.req.Host.Value");
        var newUrl = UriHelper.BuildAbsolute(req.Scheme, wwwHost, req.PathBase, req.Path, req.QueryString);
        var response = context.HttpContext.Response;
        response.StatusCode = 301;
        response.Headers[HeaderNames.Location] = newUrl;
        context.Result = RuleResult.EndResponse;
    

扩展方法:

public static class RewriteOptionsExtensions

    public static RewriteOptions AddRedirectToWww(this RewriteOptions options)
    
        options.Rules.Add(new RedirectToWwwRule());
        return options;
    

用法:

var options = new RewriteOptions();
options.AddRedirectToWww();
options.AddRedirectToHttps();
app.UseRewriter(options);

重写中间件的未来版本将包含规则和相应的扩展方法。见this pull request

【讨论】:

如果您希望您的应用程序处理不同的子域,它是否打算仅使用 PR 从无子域重定向到 www?所以例如mydomain.org 转到 www.mydomain.org,但 ww2.mydomain.org 保持不变?【参考方案2】:

我更像是一个 Apache 用户,幸运的是 ASP.NET Core 中的 URL 重写中间件提供了一个名为 AddApacheModRewrite 的方法来即时执行 mod_rewrite 规则。

1- 创建一个.txt 文件,无论名称如何,并将这两行放入其中:

RewriteCond %HTTP_HOST !^www\. [NC]
RewriteRule ^(.*)$ http://www.%HTTP_HOST/$1 [R=301,L]

2-然后这样称呼它:

AddApacheModRewrite(env.ContentRootFileProvider, "Rules.txt")

完成!

【讨论】:

【参考方案3】:

只使用一个正则表达式,

找到^(https?://)?((?!www\.)(?:(?:[a-z\u00a1-\uffff0-9]+-?)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]+-?)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]2,)))

替换$1www.$2

展开

 ^                             # BOS
 (                             # (1 start), optional http(s)
      https?  ://
 )?                            # (1 end)
 (                             # (2 start), domains without www prefix
      (?! www\. )
      (?:
           (?: [a-z\u00a1-\uffff0-9]+ -? )*
           [a-z\u00a1-\uffff0-9]+ 
      )
      (?:
           \.
           (?: [a-z\u00a1-\uffff0-9]+ -? )*
           [a-z\u00a1-\uffff0-9]+ 
      )*
      (?:
           \.
           (?: [a-z\u00a1-\uffff]2, )
      )
 )                             # (2 end)

【讨论】:

这个正则表达式解决方案看起来不错,但与 ASP 重写中间件没有任何关系,并且 OP 在赏金之前有类似的基于正则表达式的解决方案。【参考方案4】:

自 ASP.NET Core 3.0 (2019) 起,可以使用以下方法:

AddRedirectToWwwPermanent() AddRedirectToWww()

示例

app.UseRewriter(new RewriteOptions()
  .AddRedirectToWww());

见https://docs.microsoft.com/en-us/aspnet/core/fundamentals/url-rewriting?view=aspnetcore-5.0

【讨论】:

app.UseRewriter(new RewriteOptions().AddRedirectToWwwPermanent());对于永久重定向,请使用此。【参考方案5】:

尚不清楚 AddRedirect 方法是否执行以及它是否真的接受正则表达式。

但是要在没有“www”的网址中插入“www”? 您可以使用以下字符串进行尝试:

string pattern = @"^(https?://)(?!www[.])(.*)$";
string replacement = "$1www.$2";

//Regex rgx = new Regex(pattern);
//string redirectUrl = rgx.Replace(url, replacement);

由于协议后面的负前瞻(?!www[.]),它会忽略像http://www.what.ever这样的字符串

$1 和 $2 是第一个和第二个捕获组。

【讨论】:

看起来不错,但是如果您可以匹配和替换起始字符,为什么还要匹配整个 URL? string pattern = @"^https?://(?!www[.])";string replacement = "$&www."; @JohanWentholt 好吧,我想我当时不确定正则表达式引擎是否会使用 $& 或 $0 进行匹配。但你的版本是更好的高尔夫。看到这家伙现在对这么老的问题投入巨资,我有点惊讶。哦,没关系,他改变了问题。也许他应该刚刚开始一个新的......【参考方案6】:

我认为,除非必须,否则不要使用正则表达式,您可以使用 Uri 类来重构您的网址

var uri = new Uri("http://example.com/test/page.html?query=new&sortOrder=ASC");
var returnUri = $"uri.Scheme://www.uri.Authority
string.Join(string.Empty, uri.Segments)uri.Query";

结果会是这样的

Output: http://www.example.com/test/page.html?query=new&sortOrder=ASC

【讨论】:

我需要使用正则表达式,因为这是在 ASP.NET Core 方法中使用的。【参考方案7】:

这是一个可以尝试的正则表达式:

(http)(s)?(:\/\/)[^www.][A-z0-9]+(.com|.gov|.org)

它将选择如下 URL:

http://example.com https://example.com http://example.gov https://example.gov http://example.org https://example.org

但不喜欢:

http://www.example.com https://www.example.com

如果可能,我更喜欢使用显式扩展(例如.com.gov.org),但如果它对您的用例有益,您也可以使用类似的扩展:

(http)(s)?(:\/\/)[^www.][A-z0-9]+(.*)3

然后我会用类似以下的方式来处理替换:

Regex r = new Regex(@"(http)(s)?(:\/\/)[^www.][A-z0-9]+(.*)3");
string test = @"http://example.org";
if (r.IsMatch(test))

    Console.WriteLine(test.Replace("https://", "https://www."));
    Console.WriteLine(test.Replace("http://", "http://www."));

【讨论】:

正则表达式似乎不正确 [^www.] 匹配 不是 w单个 字符>.(点)。用http://willywonka.com 试试你的正则表达式。【参考方案8】:

您不需要 RegEx,只需简单的替换即可:

var temp = new string[] "http://google.com", "http://www.google.com", "http://gmail.com", "https://www.gmail.com", "https://example.com";

var urlWithoutWWW = temp.Where(d => 
                         d.IndexOf("http://www") == -1 && d.IndexOf("https://www") == -1);

foreach (var newurl in urlWithoutWWW)

     Console.WriteLine(newurl.Replace("://", "://www."));

【讨论】:

我需要使用正则表达式,因为这是在 ASP.NET Core 方法中使用的。 所以,这个可以在.net core中使用。【参考方案9】:

现在最常见的情况是,您希望同时重定向到 www 和 https。 hankors 的回答很好,但需要两个重定向而不是一个,所以我重写了他的自定义规则,以便在需要时添加 www 和 https。结果只是一个重定向(如果您在 Azure 中打开 https 重定向)。

    public class RedirectToHttpsWwwRule : IRule

    public void ApplyRule(RewriteContext context)
    
        var req = context.HttpContext.Request;
        if (req.Host.Host.Equals("localhost", StringComparison.OrdinalIgnoreCase))
        
            context.Result = RuleResult.ContinueRules;
            return;
        
        HostString wwwHost;

        if (req.IsHttps)
        
            if (req.Host.Value.StartsWith("www.", StringComparison.OrdinalIgnoreCase))
            
                context.Result = RuleResult.ContinueRules;
                return;
            
            else
            
                wwwHost = new HostString($"www.req.Host.Value");
            
        
        else
        
            if (req.Host.Value.StartsWith("www.", StringComparison.OrdinalIgnoreCase))
            
                wwwHost = new HostString(req.Host.Value);
            
            else
            
                wwwHost = new HostString($"www.req.Host.Value");
            
        

        string newUrl = UriHelper.BuildAbsolute("https", wwwHost, req.PathBase, req.Path, req.QueryString);
        var response = context.HttpContext.Response;
        response.StatusCode = 301;
        response.Headers[HeaderNames.Location] = newUrl;
        context.Result = RuleResult.EndResponse;
    

【讨论】:

【参考方案10】:

我也在 .net 6 ASP.net 应用程序中使用了 SuperDuck 的答案。我的代码是:

using Microsoft.AspNetCore.Rewrite;

app.UseRewriter(new RewriteOptions().AddRedirectToWwwPermanent().AddRedirectToHttpsPermanent()); // in program.cs

它重定向到 www 子域以及 web-app 的 https 版本。

【讨论】:

这并不能真正回答问题。如果您有其他问题,可以点击 提问。要在此问题有新答案时收到通知,您可以follow this question。一旦你有足够的reputation,你也可以add a bounty 来引起对这个问题的更多关注。 - From Review

以上是关于使用 Asp.Net Core 中间件将非 WWW 重定向到 WWW的主要内容,如果未能解决你的问题,请参考以下文章