2012-03-08 6 views
11

[RequireHttps]は[RequireHttps]が301の代わりにリダイレクトを行います。私はこれがどういう意味かわかりません...MVCで[RequireHttps]を実行しても、301の永久リダイレクトは必要ありませんか?なぜそれは302(SEOのために悪いですか)

コントローラー[RequireHttps]を実行すると、そのページのHTTPバージョンを訪問することは決してありません。だからなぜ永続的なリダイレクトではないのですか?検索エンジンに "このページのhttpsバージョンにあなたのリンクを永久にアップデートしてください"と伝えます。

これが意味をなさないのであれば、301リダイレクトに変更する方法はありますか?

+1

http://webmasters.stackexchange.com/questions/22268/when-redirecting-from-http-to-https-in-a-shop-site-which-status-code-should-iu – Hupperware

答えて

7

301の上に302と一緒に行く選択肢は、まずは少し恣意的だったようです。ただし、必ずしもすべてのURLがHTTPSスキームを利用するために「持っている」というわけではありません。 HTTPやHTTPSからのアクセスを可能にするページであっても、HTTPやHTTPSの両方からアクセスできるようにすることができます。これが発生する可能性のある実装では、いくつかの特別な基準に基づいてHTTPSを使用するかどうかを判断するためにいくつかのコードを組み込むことができます。

ケーススタディとして、Gmailをご覧ください。設定内では、アプリケーションの大部分にわたってHTTPSプロトコルを許可または禁止することができます。どのコードを返す必要がありますか? 301は "永久"ではないので、正確ではないでしょう...ユーザーの命令での変更のみ。残念なことに、302エラーは、302エラーが将来のある時点でリンクを元に戻す意思があることを意味するため(どちらも、参考文献http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html)、どちらも正確ではありません。

ただし、このオプションを許可するサイトの部分は、通常は検索エンジンでインデックスが作成されない可能性があるため、Gmailは大まかな例です。

最後の質問に答えるために、ASP.NET MVC(小さな構文例で使用していると仮定しています)で別のステータスコードが必要な場合は、単純なカスタム属性で変更することができます。

public class MyRequireHttpsAttribute : RequireHttpsAttribute 
{ 
    public override void OnAuthorization(AuthorizationContext filterContext) 
    { 
     base.OnAuthorization(filterContext); 

     if (!filterContext.HttpContext.Request.IsSecureConnection) 
      filterContext.HttpContext.Response.StatusCode = (int)HttpStatusCode.MovedPermanently; 
    } 
} 

属性を実装するすべてのアクションは、HTTPプロトコル経由でアクセスすると301ステータスコードを返すようになりました。

+3

RequireHttps属性は、この問題に「選択」を残す属性ではありません。基本的に* HTTPSでなければなりません - HTTPは間違っています。なぜなら、HTTP経由でサイトにアクセスすることは不可能だからです。これがまずは301となっていたはずだと感じているのですが、あなたのコードは注目に値すると思います。私は301にそれをすべて切り替えることにする前にもう少し研究をするつもりです...私は少しSEOの新しいです。ありがとう! –

+1

これは、特にRequireHttps属性のその点に同意します。私は、特定のフレームワークの枠外で特定のアプリケーションで明示的に必要でない方法をより深く理解しようとしていました。コードがうれしかった! – Dulan

+4

残念ながら、これはうまくいきませんでした...まだ302.私はそれをつぶすことを試みました...しかし、私は依然としてRequireHttpsをオーバーライドして301にすることができませんでした。代わりに、私は自分の[RequireHttpsPerm]自分自身をリダイレクトしています。 –

4

Dulanのソリューションは正しいパスに入れましたが、コードサンプルはコアRequireHttpsAttribute実装からの302リダイレクトを停止しませんでした。だから、私はRequireHttpsAttributeのコードを見て、それをハッキングしました。ここに私が思い付いたものです:

using System.Net; 
using System.Web.Mvc; 
using System; 
using System.Diagnostics.CodeAnalysis; 

[SuppressMessage("Microsoft.Performance", "CA1813:AvoidUnsealedAttributes", Justification = "Unsealed because type contains virtual extensibility points.")] 
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = false)] 
public class RequireHttps301Attribute : FilterAttribute, IAuthorizationFilter 
{ 

    public virtual void OnAuthorization(AuthorizationContext filterContext) 
    { 
     if (filterContext == null) { 
      throw new ArgumentNullException("filterContext"); 
     } 

     if (!filterContext.HttpContext.Request.IsSecureConnection) { 
      HandleNonHttpsRequest(filterContext); 
     } 
    } 

    protected virtual void HandleNonHttpsRequest(AuthorizationContext filterContext) 
    { 
     // only redirect for GET requests, otherwise the browser might not propagate the verb and request 
     // body correctly. 

     if (!String.Equals(filterContext.HttpContext.Request.HttpMethod, "GET", StringComparison.OrdinalIgnoreCase)) { 
      throw new InvalidOperationException("Only redirect for GET requests, otherwise the browser might not propagate the verb and request body correctly."); 
     } 

     // redirect to HTTPS version of page 
     string url = "https://" + filterContext.HttpContext.Request.Url.Host + filterContext.HttpContext.Request.RawUrl; 
     //what mvc did to redirect as a 302 
     //filterContext.Result = new RedirectResult(url); 

     //what I did to redirect as a 301 
     filterContext.HttpContext.Response.StatusCode = (int)HttpStatusCode.MovedPermanently; 
     filterContext.HttpContext.Response.RedirectLocation = url; 
    } 
} 
+1

MVC 4+では、2つの引数をとり、301を強制する 'RedirectResult'コンストラクタを使用できます:' filterContext.Result = new RedirectResult(url、true); ' –

8

Dulanの答えは近いですが、それは、少なくとも私たちのMVC 4+溶液で、動作しません。しかし、試行錯誤の後、私たちは302の代わりに301のものを使用しました。ここで新しいクラスがある:

public class CustomRequireHttpsAttribute : RequireHttpsAttribute 
{ 
    public override void OnAuthorization(AuthorizationContext filterContext) 
    { 
     #if !DEBUG 
     base.OnAuthorization(filterContext); 

     if (!filterContext.HttpContext.Request.IsSecureConnection) 
     { 
      string url = "https://" + filterContext.HttpContext.Request.Url.Host + filterContext.HttpContext.Request.RawUrl; 
      filterContext.Result = new RedirectResult(url, true); 
     } 
     #endif 
    } 
} 

動作しませんでしたDulanの答えはfilterContext.ResultのPermanentプロパティが読み取り専用であるとRedirectResult()が呼び出されたときにのみ設定することができ、かつ問題があるためと考えられる理由そのRedirectResult()base.OnAuthorization()メソッドで呼び出されます。したがって、基本メソッドを呼び出して、次にfilterContext.Resultを第2引数のtrueで上書きして、結果を永久にします。この後、我々はFiddler2で301のコードを見始めた。

1

要求がGET要求以外のものであれば、RequireHttpsAttributeもInvalidOperationExceptionをスローすることに注意してください。これは405メソッドが許可されていないことを返すことでより効果的です。これははるかに適切なエラーです。

私の実装では、属性のユーザーに、リダイレクト(301)または一時的(302)のいずれかを選択するかどうかのオプションも指定します。 @Dulanによると、HTTPSでしかページにアクセスできない場合は301永久リダイレクトを、HTTPまたはHTTPSでページにアクセスできる場合は302の一時リダイレクトを実行する必要があります。

/// <summary> 
/// Represents an attribute that forces an unsecured HTTP request to be re-sent over HTTPS. 
/// <see cref="System.Web.Mvc.RequireHttpsAttribute"/> performs a 302 Temporary redirect from a HTTP URL to a HTTPS URL. 
/// This filter gives you the option to perform a 301 Permanent redirect or a 302 temporary redirect. 
/// You should perform a 301 permanent redirect if the page can only ever be accessed by HTTPS and a 302 temporary redirect if 
/// the page can be accessed over HTTP or HTTPS. 
/// </summary> 
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, Inherited = true, AllowMultiple = false)] 
public class RedirectToHttpsAttribute : FilterAttribute, IAuthorizationFilter 
{ 
    private readonly bool permanent; 

    /// <summary> 
    /// Initializes a new instance of the <see cref="RedirectToHttpsAttribute"/> class. 
    /// </summary> 
    /// <param name="permanent">if set to <c>true</c> the redirection should be permanent; otherwise, <c>false</c>.</param> 
    public RedirectToHttpsAttribute(bool permanent) 
    { 
     this.permanent = permanent; 
    } 

    /// <summary> 
    /// Gets a value that indicates whether the redirection should be permanent. 
    /// </summary> 
    /// <value> 
    /// <c>true</c> if the redirection should be permanent; otherwise, <c>false</c>. 
    /// </value> 
    public bool Permanent 
    { 
     get { return this.permanent; } 
    } 

    /// <summary> 
    /// Determines whether a request is secured (HTTPS) and, if it is not, calls the <see cref="HandleNonHttpsRequest"/> method. 
    /// </summary> 
    /// <param name="filterContext">An object that encapsulates information that is required in order to use the <see cref="System.Web.Mvc.RequireHttpsAttribute"/> attribute.</param> 
    /// <exception cref="System.ArgumentNullException">The filterContext parameter is null.</exception> 
    public virtual void OnAuthorization(AuthorizationContext filterContext) 
    { 
     if (filterContext == null) 
     { 
      throw new ArgumentNullException("filterContext"); 
     } 

     if (!filterContext.HttpContext.Request.IsSecureConnection) 
     { 
      this.HandleNonHttpsRequest(filterContext); 
     } 
    } 

    /// <summary> 
    /// Handles unsecured HTTP requests that are sent to the action method. 
    /// </summary> 
    /// <param name="filterContext">An object that encapsulates information that is required in order to use the <see cref="System.Web.Mvc.RequireHttpsAttribute"/> attribute.</param> 
    /// <exception cref="System.InvalidOperationException">The HTTP request contains an invalid transfer method override. All GET requests are considered invalid.</exception> 
    protected virtual void HandleNonHttpsRequest(AuthorizationContext filterContext) 
    { 
     // Only redirect for GET requests, otherwise the browser might not propagate the verb and request body correctly. 
     if (!string.Equals(filterContext.HttpContext.Request.HttpMethod, "GET", StringComparison.OrdinalIgnoreCase)) 
     { 
      // The RequireHttpsAttribute throws an InvalidOperationException. Some bots and spiders make HEAD requests (to reduce bandwidth) 
      // and we don’t want them to see a 500-Internal Server Error. A 405 Method Not Allowed would be more appropriate. 
      throw new HttpException((int)HttpStatusCode.MethodNotAllowed, "Method Not Allowed"); 
     } 

     string url = "https://" + filterContext.HttpContext.Request.Url.Host + filterContext.HttpContext.Request.RawUrl; 
     filterContext.Result = new RedirectResult(url, this.permanent); 
    } 
} 
関連する問題