3

一部のユーザーがロールに属しているアプリケーションを使用していますが、実際には URL 内の特定のデータにアクセスできない場合があります。たとえば、次の URL はすべてのユーザーに公開されています

/Library/GetFile/1

ただし、一部のユーザーは file1 にアクセスできない可能性がありますが、Authorize 属性を使用してそれを検出することはできません。代わりに、これらのユーザーを無許可またはアクセス拒否のページにリダイレクトしたいと考えています。フォーム認証を使用しており、構成は次のように設定されています

<authentication mode="Forms">
    <forms loginUrl="~/Home/Index" timeout="2880" />
</authentication>

私のカスタムエラーブロックはこのようなものです

<customErrors mode="On" defaultRedirect="Error" redirectMode="ResponseRewrite" >
    <error statusCode="401" redirect="Unauthorized"/>
</customErrors>

ユーザーがアクセス権を持っていない場合、HttpUnauthorizedResult を返そうとしていますが、ユーザーが既に認証されているため、ここでは無効なログイン ページにリダイレクトされます。


HttpUnauthorizedResult が HTTP 応答コードを 401 に設定しているように見えます。フォーム認証がハイジャックされ、ユーザーがログイン ページに送られます。

RegisterGlobalFiltersを

filters.Add(new HandleErrorAttribute
{
    ExceptionType = typeof(UnauthorizedAccessException),
    View = "Unauthorized",
    Order = 3
});

UnauthorizedAccessException をカスタム Exception に変更すると、リダイレクトが機能し、今のところそれが私が行ったことです。

4

2 に答える 2

3

あなたの解決策は、私がこれを行ったことを除いて、私のものと似ています:

  1. カスタム例外 UnauthorizedDataAccessException を作成します。

  2. カスタム例外フィルターを作成します (無効なアクセス試行をログに記録できるようにするため)。

  3. カスタム例外属性をグローバル フィルターとして App_start に登録します。

  4. マーカー インターフェイス ISecureOwner を作成し、エンティティに追加しました。

  5. 現在のユーザーが読み込まれたエンティティの所有者でない場合に例外をスローする、セキュリティで保護された 'Load' 拡張メソッドをリポジトリに追加します。これが機能するには、エンティティは、エンティティを保存したユーザーの ID を返す ISecureOwner を実装する必要があります。

これはパターンを示しているだけであることに注意してください。GetSecureUser の実装方法とデータの取得に使用するものの詳細はさまざまです。ただし、このパターンは小さなアプリでは問題ありませんが、データベース内の所有権グループを使用して、その種のセキュリティをデータレベルで深く実装する必要があるため、少しハックです:)

    public class UnauthorizedDataAccessException : Exception
    {
        // constructors
    }

    public class UnauthorizedDataAccessAttribute : HandleErrorAttribute
    {
        public override void OnException(ExceptionContext filterContext)
        {
            if (filterContext.Exception.GetType() == Typeof(UnauthorizedDataAccessException))
            {
                // log error
                filterContext.ExceptionHandled = true;
                filterContext.Result = new RedirectToRouteResult(new RouteValueDictionary(new { controller = "Error", action = "UnauthorizedDataAccess" }));
            }
            else
            {
                base.OnException(filterContext);
            }
        }

    // marker interface for entity and extension method    
    public interface ISecureOwner
    {
        Guid OwnerId { get; }
    }

    // extension method
    public static T SecureFindOne<T>(this IRepository repository, Guid id) where T : class, ISecureOwner, new()
    {
        var user = GetSecureUser();
        T entity = repository.FindOne<T>(id);

        if (entity.OwnerId != user.GuidDatabaseId)
        {
            throw new UnauthorizedDataAccessException(string.Format("User id '{0}' attempted to access entity type {1}, id {2} but was not the owner. The real owner id is {3}.", user.GuidDatabaseId, typeof(T).Name, id, entity.OwnerId));
        }

        return entity;
    }

    // Register in global.asax
    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
        var filter = new UnauthorizedDataAccessAttribute { ExceptionType = typeof(UnauthorizedDataAccessException) };
        filters.Add(filter);
        filters.Add(new HandleErrorAttribute());
    }

   // Usage:
   var ownedThing = myRepository.SecureFindOne<myEntity>(id))
于 2011-12-02T18:16:49.883 に答える
0

特定のロールへのアクセスを制限できます。権限のないロールがリソースにアクセスしようとした場合、特定の URL にリダイレクトできます。この他のSOの質問を見てください: attribute-for-net-mvc-controller-action-method、そこに良い答えがあります。ユーザーがロールに属しているかどうかをコードで確認できます。

User.IsInRole("RoleToTest");

コントローラー/アクション メソッドに属性を適用することもできます。とにかく、上で指定したリンクですべて説明されています。

*編集* ベースコントローラーでOnExceptionをオーバーライドできます。AccessNotAuthorizedAccessException などのカスタム例外を実装します。OnExceptionon で、カスタム例外を検出した場合は、「承認されていません...」メッセージを表示するわかりやすい URL にリダイレクトするだけです。

于 2011-12-01T22:39:34.543 に答える