2


0

不正ユーザーをリダイレクトするログインページをどのように定義しますか

次のように、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);
    }
}
  1. 私は役割を定義する非標準的な方法を使用しているため。つまり、私は 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);

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

しかし、これが全体にどのような影響を与えるかはわかりませんが…​

更新:ロバートのソリューションのおかげで、ここに私がそれを解決した方法があります-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"))
   { %>
<%= TempData["Message"]%>
<% } %>

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

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

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

1 Answer


3


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

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

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

Edit

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

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

But. そもそもログインページにリダイレクトされた理由をユーザーに伝えるとよいでしょう。 そのための組み込み機能はありません…​ それでもこの知識はあなたの問題を解決するものではありません…​

編集2

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

シンプルなもの

  1. 独自の認可属性を記述します(単純に 既存のものに追加のパブリックプロパティ「Message」を追加します)。ieなどの属性宣言を使用して、何らかのメッセージを提供することもできます。

[AuthorizeWithMessage(Role = "ExecAdmin", Message = "You need at least ExecAdmin permissions to access requested resource."]
  1. 認可属性は「TempData」辞書に入力する必要があります 提供されたメッセージ(この場合に使用する `TempData`についてhttp://msdn.microsoft.com/en-us/library/dd394711.aspx[documentation]を確認します)を使用して、基本クラス機能を呼び出します。

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

複雑な

  1. 独自の認証フィルターを作成します( オリジナル)そして、ユーザーが十分な権限を持っていない場合にログインを提供する_承認ログインビュー_への独自のリダイレクトを提供します。

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

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

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

どちらを選択しますか?

それがあなたのニーズを満たすなら、よりシンプルなものを使ってください。しかし、もしあなたがプロセス全体をもっとコントロールしたいなら、私はむしろ複雑なものを使います。 それほど複雑ではなく、不十分なログインプロセスを完全に制御できます。 ユーザーにとってより良いエクスペリエンスにすることができます。