12

MSSQLバックエンドでMVC3を使用してイントラネットアプリケーションを構築しています。認証とロール(カスタムロールプロバイダーを介して)が正しく機能しています。私が今やろうとしているのは、User.Identityをオーバーライドして、User.Identity.FirstNameのようなアイテムを許可することです。しかし、WindowsIdentityでこれを行う方法を示すコードが見つかりません

カスタムプロバイダーを書いてみました:

public class CPrincipal : WindowsPrincipal
{
    UserDAL userDAL = new UserDAL();
    public CPrincipal(WindowsIdentity identity)
        : base(identity)
    {
        userInfo = userDAL.GetUserProfile(identity.Name.Split('\\')[1]);
        this.identity = identity;
    }
    public UserInfo userInfo { get; private set; }
    public WindowsIdentity identity { get; private set; }
}

WindowsAuthenticationをオーバーライドして、カスタムプリンシパルを設定します。

    void WindowsAuthentication_OnAuthenticate(object sender, WindowsAuthenticationEventArgs e)
    {
        if (e.Identity != null && e.Identity.IsAuthenticated)
        {
            CPrincipal cPrincipal = new CPrincipal(e.Identity);
            HttpContext.Current.User = cPrincipal;
        }
    }

認証機能にブレークポイントがあり、プリンシパルにデータが入力されています。ただし、コントローラーにブレークポイントを設定すると、ユーザーはカスタムプリンシパルではなく、通常のRolePrincipalになります。私は何が間違っているのですか?

編集:

上記のコードをglobal.asaxでコメントアウトしました。C#を使用してAuthorizeAttributeをオーバーライドしました:

public class CAuthorize : AuthorizeAttribute
{
    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
        bool authorized = base.AuthorizeCore(httpContext);
        if (!authorized)
        {
            return false;
        }


        IIdentity user = httpContext.User.Identity;
        CPrincipal cPrincipal = new CPrincipal(user);
        httpContext.User = cPrincipal;

        return true;
    } 

}

そして、私のプリンシパルを次のように調整しました:

public class CPrincipal : IPrincipal
{
    private UserDAL userDAL = new UserDAL();
    public CPrincipal(IIdentity identity)
    {
        userInfo = userDAL.GetUserProfile(identity.Name.Split('\\')[1]);
        this.Identity = identity;
    }
    public UserInfo userInfo { get; private set; }

    public IIdentity Identity { get; private set; }

    public bool IsInRole(string role)
    {
        throw new NotImplementedException();
    }
}

ブレークポイントを設定すると、時計はユーザーに次のように表示されます。

  • ユーザー
    • [CSupport.Model.CPrincipal]
    • 身元

IDにアクセスできます。ただし、それでもWindowsIdentity CPrincipalは時計でのみアクセス可能であり、直接アクセスすることはできません。

編集: これに貢献してくれたすべての人に感謝します。さまざまな部品がどのように機能するかについての私の理解が大幅に広がりました。

両方の働き方ができたので、シェアしたいと思いました。

オプション1:Global.asaxの承認リクエストを上書きする

これは私が行っているものです。

Application_AuthenticateRequestを使用しなかったのは、(これによると、Windows認証がオンになっているにもかかわらずHttpContext.Current.Userがnullである)、ユーザーがWindows認証プロセスに入力されていないため、ユーザーを取得するために使用できるものがないためです。情報。

Application_AuthorizeRequestはチェーンの次のものであり、WindowsIDが取り込まれた後に発生します。

    protected void Application_AuthorizeRequest(object sender, EventArgs e)
    {
        if (User.Identity.IsAuthenticated && Roles.Enabled)
        {
            Context.User = new FBPrincipal(HttpContext.Current.User.Identity);
        }
    }

これはプリンシパルのオーバーライドです

public class CPrincipal : IPrincipal
{
    private UserDAL userDAL = new UserDAL();
    public CPrincipal(IIdentity identity)
    {
        userInfo = userDAL.GetUserProfile(identity.Name.Split('\\')[1]);
        this.Identity = identity;
    }
    public UserInfo userInfo { get; private set; }

    public IIdentity Identity { get; private set; }

    public bool IsInRole(string role)
    {
        return userDAL.IsUserInRole(userInfo.UserName, role);
    }
}

これは、作成された新しいプリンシパルの更新された情報にアクセスする方法です。

    [Authorize(Roles = "super admin")]
    public ActionResult Dashboard()
    {
        string firstname = (User as CPrincipal).userInfo.FirstName; // <--
        DashboardModel dModel = reportDAL.GetChartData();
        return View(dModel);
    }

オプション2:AuthorizeAttributeをオーバーライドします

これはオーバーライドされたプリンシパルです(上記と同じです)

public class CPrincipal : IPrincipal
{
    private UserDAL userDAL = new UserDAL();
    public CPrincipal(IIdentity identity)
    {
        userInfo = userDAL.GetUserProfile(identity.Name.Split('\\')[1]);
        this.Identity = identity;
    }
    public UserInfo userInfo { get; private set; }

    public IIdentity Identity { get; private set; }

    public bool IsInRole(string role)
    {
        return userDAL.IsUserInRole(userInfo.UserName, role);
    }
}

これがAuthorize属性のオーバーライドです

public class CAuthorize : AuthorizeAttribute
{
    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
        bool authorized = base.AuthorizeCore(httpContext);
        if (!authorized)
        {
            return false;
        }


        IIdentity user = httpContext.User.Identity;
        CPrincipal cPrincipal = new CPrincipal(user);
        httpContext.User = cPrincipal;

        return true;
    } 

}

ここで、使用するAuthorizeAttributeを変更し、新しい情報を利用します。

    [CAuthorize(Roles = "super admin")] // <--
    public ActionResult Dashboard()
    {
        string firstname = (User as CPrincipal).userInfo.FirstName; // <--
        DashboardModel dModel = reportDAL.GetChartData();
        return View(dModel);
    }

オプション1はすべてをグローバルに処理し、オプション2はすべてを個別のレベルで処理します。

4

2 に答える 2

6

このようにする代わりに、global.asax で Application_AuthenticateRequest メソッドをオーバーライドしてから、HttpContext.Current.User ではなく Current.User を使用する必要があります (理由はわかりませんが、違いがあります)。

次に、コントローラーでこれにアクセスする簡単な方法は、拡張メソッドを作成することですか? このようなもの:

public static class IIdentityExtensions {
    public static IMyIdentity MyIdentity(this IIdentity identity) {
        return (IMyIdentity)identity;
    }
}

と言うことができますUser.Identity.IMyIdenty().FirstName。おそらくこれをプロパティとして行うこともできます。

私が使用するコードは次のとおりです。

protected void Application_AuthenticateRequest(Object sender, EventArgs e)
{
    FormsAuthenticationTicket authTicket = FormsAuthentication
       .Decrypt(authCookie.Value);
    var identity = new MyIdentity(authTicket.Name, "Forms", 
       FormsAuthenticationHelper.RetrieveAuthUserData(authTicket.UserData));
    Context.User = new GenericPrincipal(identity, 
       DependencyResolver.Current.GetService<ISecurityHandler>()
          .GetRoles(identity.Name).ToArray());
}

さて、DependencyResolver のものとカスタム認証チケットのものを無視すると、これはかなり基本的なものであり、私にとっては正しく機能します。

次に、私のアプリで、カスタム ID からの情報が必要な場合は、必要((IMyIdentity)User.Identity).FirstNameなものをキャストするだけです。それはロケット科学ではなく、機能します。

于 2012-09-24T15:55:36.660 に答える
2

私は何を間違っていますか?

おそらく、[Authorize]属性が変更を上書きしています。したがって、WindowsAuthentication_OnAuthenticateメソッドでこれを行う代わりに、次のようGlobal.asaxにカスタムAuthorize属性を記述します。

public class MyAuthorizeAttribute : AuthorizeAttribute
{
    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
        var authorized = base.AuthorizeCore(httpContext);
        if (!authorized)
        {
            return false;
        }


        var user = httpContext.User as WindowsIdentity;
        CPrincipal cPrincipal = new CPrincipal(user);
        httpContext.User = cPrincipal;

        return true;
    }
}

次に、デフォルトの属性の代わりにカスタム属性を使用します。

[MyAuthorize]
public ActionResult SomeAction()
{
    // User.Identity will be your custom principal here
}

ASP.NET MVC で承認を実行する標準的な方法は、Global.asax のイベントではなく、承認アクション フィルターを使用することです。

于 2012-09-24T16:00:50.187 に答える