17

クラスをオーバーライドしてカスタム承認を実行します

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)]
public class AuthorizeAttribute : System.Web.Mvc.AuthorizeAttribute
{
    protected override void HandleUnauthorizedRequest(System.Web.Mvc.AuthorizationContext filterContext)
    {
        if (filterContext.HttpContext.Request.IsAuthenticated)
        {
            filterContext.Result = new System.Web.Mvc.HttpStatusCodeResult(403);
        }
        else
        {
            base.HandleUnauthorizedRequest(filterContext);
        }
    }
}

今web.configで403エラーページを設定しました

<customErrors defaultRedirect="/Shared/Error" mode="On">
  <error statusCode="403" redirect="/Shared/UnAuthorize" />
</customErrors>

しかし、ブラウザにはまだ 403 のデフォルトのエラー ページが表示されます。

4

7 に答える 7

11

Max B以外のちょっとしたヒント/メモ:答え:

カスタムエラーを使用している場合はErrorsController、とUnAuthorize ActionResultを作成し、次のようにします。

<error statusCode="403" redirect="/Errors/UnAuthorize" />

このようにして、コントローラーで追加情報を追加したり、他のアクションを実行したりできます。たとえば、次のようになります。

  • 誰かが認証された領域にアクセスしようとしたデータベースにログを記録するようなものです。
  • エラーカウント。
  • おそらく、管理者情報を送信するために使用できるバグまたはレポートフォームです。
  • ..。

このようにして、何が起こっているかをさらに制御できます。

于 2011-08-11T09:23:45.647 に答える
6

独自のカスタム AuthorizeAttribute を作成したときとまったく同じ問題がありました。web.config に「customErrors」タグを追加すると、403 のカスタム エラー ページが表示されません。これは私がそれを解決した方法です:

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)]
public class AuthorizeAttribute : System.Web.Mvc.AuthorizeAttribute
{
    protected override void HandleUnauthorizedRequest(System.Web.Mvc.AuthorizationContext filterContext)
    {
        if (filterContext.HttpContext.Request.IsAuthenticated)
        {
           filterContext.Result = new RedirectToRouteResult(
                new RouteValueDictionary(
                    new
                        { 
                            controller = "Error", 
                            action = "Unauthorised" 
                        })
                ); 

        }
        else
        {
            base.HandleUnauthorizedRequest(filterContext);
        }
    }
}

403 HttpStatusCode を割り当てる代わりに、表示したいルートを filterContext.Result に割り当てました。

于 2013-12-31T18:39:37.010 に答える
3

または、以下を使用する代わりに、この代替ソリューションを実行できます。

filterContext.Result = new System.Web.Mvc.HttpStatusCodeResult(403);

次のように変更できます:

if (filterContext.HttpContext.Request.IsAuthenticated)
        {               
            throw new UnauthorizedAccessException();
        }

そして、Controller / BaseControllerのメソッドOnException(ExceptionContext filterContext)をオーバーライドします

protected override void OnException(ExceptionContext filterContext)
    {
        if (filterContext.ExceptionHandled)
        {
            return;
        }

        if (filterContext.Exception.GetType() == typeof(UnauthorizedAccessException))
        {   
            filterContext.Result = new ViewResult
            {
                ViewName = "~/Views/Error/NotAuthorized.cshtml"
            };
            filterContext.ExceptionHandled = true;
            return;
        }

        base.OnException(filterContext);
    }
于 2011-12-08T09:01:53.710 に答える
0

私には、HttpStatusCodeResult(403)が間違っているifブランチにあるように見えます。私の意見では、コードは次のようになります。

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)]
public class AuthorizeAttribute : System.Web.Mvc.AuthorizeAttribute
{
    protected override void HandleUnauthorizedRequest(System.Web.Mvc.AuthorizationContext filterContext)
    {
        if (!filterContext.HttpContext.Request.IsAuthenticated)
        {
            base.HandleUnauthorizedRequest(filterContext);
            filterContext.Result = new System.Web.Mvc.HttpStatusCodeResult(403);
        }
    }
}
于 2011-08-11T09:17:05.663 に答える
0

mvc で 401 (Unauthorized)、403 (Forbidden)、および 500 (Internal Server Error) を処理する方法。ajax/非 ajax 呼び出しおよび aspx フォーム認証の下で。

キャッチされていないさまざまな例外を異なる方法で処理し、リクエストが ajax であるかどうかにかかわらず、異なる方法で反応するように変更できます。auth 部分により、通常の mvc Web フォームのリダイレクトからログインページへのリダイレクトをバイパスし、代わりに 401 無許可を返すことができます。クライアント側の js フレームワークは、http ステータス 401/403 により簡単に反応できます。

// FilterConfig.cs:
filters.Add(new ApplicationAuthorizeAttribute());
filters.Add(new ApplicationHandleErrorAttribute());

public class ApplicationAuthorizeAttribute : System.Web.Mvc.AuthorizeAttribute
{
    protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
    {
        // Note: To reach here, a Web.config path-specific rule 'allow users="?"' is needed (otherwise it redirects to login)

        var httpContext = filterContext.HttpContext;
        var request = httpContext.Request;
        var response = httpContext.Response;

        if (request.IsAjaxRequest())
        {
            response.SuppressFormsAuthenticationRedirect = true;
            response.TrySkipIisCustomErrors = true;
        }

        filterContext.Result = new HttpUnauthorizedResult();
    }
}

public class ApplicationHandleErrorAttribute : HandleErrorAttribute
{
    public override void OnException(ExceptionContext context)
    {
        var exception = context.Exception is AggregateException
            ? ((AggregateException)context.Exception).InnerExceptions.First()
            : context.Exception;
        var request = context.HttpContext.Request;
        var response = context.HttpContext.Response;
        var isAjax = request.IsAjaxRequest();

        if (exception is MyCustomPermissionDeniedException)
        {
            filterContext.Result = new HttpStatusCodeResult(HttpStatusCode.Forbidden);
            response.TrySkipIisCustomErrors = isAjax;
            filterContext.ExceptionHandled = true;
            return;
        }

#if DEBUG
        if (!isAjax)
        {
            // Show default aspx yellow error page for developers
            return;
        }
#endif

        var requestUri = request.Url == null ? "" : request.Url.AbsoluteUri;
        MyCustomerLogger.Log(exception, requestUri);

        response.Clear();
        response.StatusCode = (int)System.Net.HttpStatusCode.InternalServerError;

#if DEBUG
        var errorMessage = exception.Message;
#else
        var errorMessage = "An error occurred, please try again or contact the administrator.";
#endif

        response.Write(isAjax
            ? JsonConvert.SerializeObject(new {Message = errorMessage})
            : errorMessage);
        response.End();
        response.TrySkipIisCustomErrors = true;
        context.ExceptionHandled = true;
    }
}

Web.config:

<system.webServer>

<authentication mode="Forms">
  <forms name=".MYAUTHCOOKIE" protection="All" loginUrl="/Account/Login" timeout="18000" slidingExpiration="true" enableCrossAppRedirects="false" />
</authentication>

<authorization>
  <deny users="?" />
</authorization>

</system.webServer>

<!-- ajax api security done via ApplicationAuthorizeAttribute -->
<location path="api">
  <system.web>
    <authorization>
      <allow users="?"/>
    </authorization>
  </system.web>
</location>

Web サービス API リクエストの追加ルート: (通常の mvc ルートの上に配置)

// This route has special ajax authentication handling (no redirect to login page)
routes.MapRoute(
    name: "DefaultApi",
    url: "api/{controller}/{action}/{id}",
    defaults: new { id = UrlParameter.Optional }
);

エラーを処理する jquery のサンプル クライアント側コード:

$.ajaxSetup({
    complete: function onRequestCompleted(xhr, textStatus) {
        if (xhr.readyState == 4 && xhr.status == 401) {
            // Not needed with smart status: && xhr.responseText.substring(0, 150).indexOf("<title>Log in") != -1
            //location.href = "/Account/Login";
            alert("Your session has timed out.");
        }
    }
});

または、すべての認証を ApplicationHandleErrorAttribute を通過させ、その web.config deny users="?" を取り除くこともできます。しかし、mvc フィルタリングにヒットしない従来の aspx ページがあるため、users="?" を拒否したいと考えています。

于 2015-05-27T17:24:03.043 に答える