2

次のように、コントローラーをAuthorize属性で装飾しました。

[Authorize(Roles="ExecAdmin")]

ExecAdmin以外のユーザーとしてログインした後でそのコントローラーにアクセスしようとすると、ログインページにリダイレクトしようとしているように見えます。しかし、リダイレクトしようとしているページは私のログインページではなく、LogOnUserControl.ascxというビューです。これは私のログインページに表示されない部分的なビューです。

なぜこれを行っているのかわかりません。あるいは、LogOnUserControl.ascxを表示している他のページに完全にリダイレクトしようとしているのかもしれません。それとも、名前に「LogOn」が含まれているものを探しているのでしょうか。(私のログインビューの名前はLogOn.aspxですが...)

どのページにリダイレクトするかをどのように伝えることができますか?

更新:私はglobal.asaxにこれを持っています

protected void Application_AuthenticateRequest(Object sender, EventArgs e)
{
    HttpCookie authCookie = Context.Request.Cookies[FormsAuthentication.FormsCookieName];
    if (authCookie == null || authCookie.Value == "")
    {
        return;
    }
    FormsAuthenticationTicket authTicket = null;
    try
    {
        authTicket = FormsAuthentication.Decrypt(authCookie.Value);
    }
    catch
    {
        return;
    }
    string[] roles = authTicket.UserData.Split(new char[] { ';' });
    //Context.ClearError(); 
    if (Context.User != null)
    {
        Context.User = new System.Security.Principal.GenericPrincipal(Context.User.Identity, roles);
    }
}

...私は役割を定義する非標準的な方法を使用しているので; つまり、ASP.NETメンバーシップスキームを使用していません(web.configなどで定義されたロールプロバイダーを使用)。代わりに、次のように役割を設定しています。

// get user's role
string role = rc.rolesRepository.GetUserType(rc.loginRepository.GetUserID(userName)).ToString();

// create encryption cookie
FormsAuthenticationTicket authTicket = new FormsAuthenticationTicket(
        1,
        userName,
        DateTime.Now,
        DateTime.Now.AddMinutes(120),
        createPersistentCookie,
        role //user's role 
        );

// add cookie to response stream
string encryptedTicket = FormsAuthentication.Encrypt(authTicket);

System.Web.HttpCookie authCookie = new System.Web.HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket);
System.Web.HttpContext.Current.Response.Cookies.Add(authCookie);

(これは、ユーザーが検証された後に呼び出されます。)

これが全体にどのように影響するかはわかりませんが...

更新:Robertのソリューションのおかげで、これが私がそれを解決した方法です-AuthorizeAttributeクラスを拡張します:

public class AuthorizeAttributeWithMessage : AuthorizeAttribute
{
    private string _message = "";
    public string Message
    {
        get { 
            return _message; 
        }
        set { 
            _message = value;
        }
    }

    protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
    {
        if (filterContext.HttpContext.Request.IsAuthenticated)
        {
            // user is logged in but wrong role or user:
            filterContext.Controller.TempData.Add("Message", Message);
        }
        base.HandleUnauthorizedRequest(filterContext);
    }
}

次に、ログオンビューで:

<% 
    if (HttpContext.Current.Request.IsAuthenticated)
    {
        // authenticated users should not be here
        Response.Redirect("/Home/Index");
    }
%>

そしてホームページビューで:

<% if (TempData != null && TempData.Count > 0 && TempData.ContainsKey("Message"))
   { %>
<div class="largewarningtext"><%= TempData["Message"]%></div>
<% } %>

そして、影響を受けるコントローラーの上に:

[AuthorizeAttributeWithMessage(Roles = "Consultant,ExecAdmin", Message = "You do not have access to the requested page")]

これには、Logon.aspxに到達する認証済みユーザーを常にリダイレクトするという利点があります。認証済みユーザーはそこにいるべきではありません。TempDataにメッセージがある場合は、ホームページに出力されます。そうでない場合は、少なくともリダイレクトが実行されます。

4

1 に答える 1

3

ログインページはweb.configファイル内で構成されます。

しかし、あなたはおそらくすでにそれを知っています。ここでの本当の問題はもう少し複雑です。ログインページはほとんどユーザーを認証しないので、ここで非常に興味深いことに気付いていると思います。特定のリソース(ここでは承認が失敗した場合)の承認をチェックしないため、そもそもログインページにリダイレクトされるべきではありません。

AuthorizeAttributeソースコードを確認401: Unauthorize Requestすると、サーバーから応答が返ってきます。ログインページにリダイレクトされません(前の段落で予想したように、ログインはそれには愚かすぎるためです。したがって、コードには、正常に機能しないものが他にほとんどあります。

編集

このページが述べているように:

サイトがASP.NETフォーム認証を使用するように構成されている場合、401ステータスコードにより、ブラウザーはユーザーをログインページにリダイレクトします。

この情報に基づいて、実際にはこの401を確認し、ログインにリダイレクトする認証を形成します(コメントで説明したように構成されます)。

だが。そもそもなぜログインページにリダイレクトされたのか、ユーザーにメッセージを提示するとよいでしょう。そのための組み込み機能はありません...それでもこの知識はあなたの問題を解決しません、それは...

編集2

実際にはユーザーに非常によく似ているが、サーバー上で異なる動作をする2つのパターンをとることができます。

単純なもの

  1. 独自の承認属性を記述します(既存の属性から継承し、それにパブリックプロパティを追加するだけMessageです)。ここで、ieのような属性宣言を含むある種のメッセージを提供することもできます。

    [AuthorizeWithMessage(Role = "ExecAdmin", Message = "You need at least ExecAdmin permissions to access requested resource."]
    
  2. 承認属性はTempData、提供されたメッセージを辞書に入力し(この場合に使用するドキュメントを確認してください)、基本クラスの機能を呼び出す必要があります。TempData

  3. ログインビューを変更して、TempData辞書のメッセージを確認します。存在する場合は、すでに認証されているユーザーに簡単に提示できるため(アクセス可能なホームページへのリンクとともに)、ログインが提示される理由がわかります。

複雑なもの

  1. 独自の承認フィルター(元のフィルターから継承しない)を作成し、ユーザーの権限が不十分な場合にログインを提供する承認ログインビューへの独自のリダイレクトを提供します。

  2. この場合は強いタイプのカスタムログインビューを作成します。承認フィルターに正しいモデルを設定できます。このモデルにはメッセージ文字列が含まれ、ユーザーが移動できるページへのルートリンクを提供することもできます。

  3. カスタムログインページのこの構成を提供するカスタム構成クラス。

ユーザー権限に基づいて、さまざまな異なるルート定義を構成することもできます。したがって、一部の権利については、いくつかのページが表示されますが、他の権利がある場合、それらのルートは別のルートを指します。

どれを選ぶ?

ニーズを満たす場合は単純なものを使用しますが、プロセス全体をより細かく制御したい場合は、複雑なものを使用します。それほど複雑ではなく、不十分なログインプロセスを完全に制御できます。あなたはそれをユーザーにとってはるかに良い体験にすることができます。

于 2010-08-03T21:56:54.213 に答える