9

ASP.NET MVC 4 イントラネット アプリケーションがあります。Windows 認証を使用しており、その側面は正常に機能します。ユーザーの資格情報が使用され、Web アプリからそれらの資格情報にアクセスできます。

ただし、私たちが本当に必要としているのは、ある種のハイブリッド モードです。ブラウザーからユーザーの資格情報を取得したいのですが、ユーザーがアプリケーションのデータベースに存在することも確認したいと考えています。ユーザーがデータベースにいる場合は、そのまま続行できます。そうでない場合は、別の資格情報を要求するページにリダイレクトします。私が今していることは、 でGlobal.asax.cs、メソッドを取得しApplication_AuthenticateRequest、ユーザーが認証されているかどうかを確認しています。ユーザーがログインしていて、Cookie 情報がシステムにログインしているという事実を反映していない場合は、ログインして、ユーザーに関する情報を含む Cookie をいくつか設定します。認証されていない場合は、ログイン ページにリダイレクトします。会社のポリシーに関連する理由で AD ロールを使用できないため、データベースを使用して追加の認証を行う必要があります。

これを行う場所ではないと思いますが、そうかもしれませんApplication_AuthenticateRequest。ただし、基本的には、認証のリクエストをフィルタリングする場所が必要です。しかし、さらに、この実装は別の問題につながります:

アプリには、匿名アクセスを許可する特定の URL があります。<location>これらのタグを web.config に追加しました。問題は、これらに対して匿名の呼び出しが行われるApplication_AuthenticateRequestと、DB にアクセスしてユーザーをログインさせようとすることです。これで、これらの URL を処理するコードを に追加できるようにApplication_AuthenticateRequestなり、それが現在の私の計画ですが、私が書いApplication_AuthenticateRequestていて、これを行う場所ではない場合は、後よりも今考えたいと思います。

4

1 に答える 1

5

この目的には、アクション フィルターを使用する必要があります。次のように AuthorizeAttribute を拡張できます。

public class MyAuthorizeAttribute : AuthorizeAttribute
{
    private UnitOfWork _unitOfWork = new UnitOfWork();

    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
        var isAuthorized = false;
        var username = httpContext.User.Identity.Name;
        // Some code to find the user in the database...
        var user = _unitOfWork.UserRepository.Find(username);
        if(user != null)
        {
           isAuthorized = true;
        }


        return isAuthorized;
    }

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

        if (AuthorizeCore(filterContext.HttpContext))
        {
            SetCachePolicy(filterContext);
        }
        else
        {
           // If not authorized, redirect to the Login action 
           // of the Account controller... 
          filterContext.Result = new RedirectToRouteResult(
            new System.Web.Routing.RouteValueDictionary {
               {"controller", "Account"}, {"action", "Login"}
            }
          );               
        }
    }

    protected void SetCachePolicy(AuthorizationContext filterContext)
    {
        // ** IMPORTANT **
        // Since we're performing authorization at the action level, 
        // the authorization code runs after the output caching module. 
        // In the worst case this could allow an authorized user 
        // to cause the page to be cached, then an unauthorized user would later 
        // be served the cached page. We work around this by telling proxies not to 
        // cache the sensitive page, then we hook our custom authorization code into 
        // the caching mechanism so that we have the final say on whether a page 
        // should be served from the cache.
        HttpCachePolicyBase cachePolicy = filterContext.HttpContext.Response.Cache;
        cachePolicy.SetProxyMaxAge(new TimeSpan(0));
        cachePolicy.AddValidationCallback(CacheValidationHandler, null /* data */);
    }

    public void CacheValidationHandler(HttpContext context,
                                        object data,
                                        ref HttpValidationStatus validationStatus)
    {
        validationStatus = OnCacheAuthorization(new HttpContextWrapper(context));
    }
}

次に、この属性をコントローラー レベルまたはアクション レベルで次のように使用できます。

[MyAuthorize]
public ActionResult SomeAction()
{
  // Code that is supposed to be accessed by authorized users only
}
于 2013-07-03T19:21:58.750 に答える