2

アプリケーションの単一ユーザーのコンテンツを次の場所に保存します。

  • C:\ファイル{GUID}\

これらのファイルは次のようなものです。

  • C:\Files{GUID}\bunny.jpg
  • C:\Files{GUID}\unicorn.html

エンド ユーザーには、「わかりやすい」URL を提示する必要があります。

http:// domain.com/files/{GUID}/bunny.jpg

そのURLは、そのファイルを表示する権限を得るために、コントローラーまたはhttpmoduleまたはthingIdontknowを何らかの形で通過する必要があります。これらのアクセス許可は日々変更される可能性があるため、ファイルのアクセス許可を頻繁に確認する必要があります。

私が読んだことから、これは完全に可能ですが、次に何をコーディングするか、または誰かがここで洞察を持っているかどうかはわかりません. HttpModule またはコントローラー? 私は何が起こる必要があるかについて混乱しています。

4

1 に答える 1

8

そのURLは、そのファイルを表示する権限を得るために、何らかの方法でコントローラーまたはhttpmoduleまたはthingIdontknowを通過する必要があります。これらの権限は日々変化する可能性があるため、ファイルの権限を頻繁にチェックする必要があります。

知らないものには名前があります。これは、承認アクション フィルターと呼ばれます。

まず、これらのファイルを提供するためのカスタム ルートを登録したとします。

routes.MapRoute(
    "MyImagesRoute",
    "files/{id}/{name}",
    new { controller = "Files", action = "Index" }

    // TODO: you could constrain the id parameter to be a GUID.
    // Just Google for a Regex that will match a GUID pattern and put here
    // as route constraint
);

そしてもちろん、それらに対応する対応するコントローラー:

public class FilesController: Controller
{
    public ActionResult Index(Guid guid, string name)
    {
        var path = @"C:\files";
        var file = Path.Combine(path, guid.ToString(), name);
        file = Path.GetFullPath(file);
        if (!file.StartsWith(path))
        {
            // someone tried to be smart and send
            // files/{Guid}/..\..\creditcard.pdf as parameter
            throw new HttpException(403, "Forbidden");
        }

        // TODO: adjust the mime type based on the extension
        return File(file, "image/png");
    }
}

残念ながら、この段階では、ユーザー ALPHA がユーザー BETA のファイルを要求することを妨げるものは何もありませんよね? それがあなたが扱いたいシナリオですよね?

それでは、このコントローラー アクションを保護するために、カスタムの Authorize 属性を書きましょう。

public class MyAuthorizeAttribute: AuthorizeAttribute
{
    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
        var authorized = base.AuthorizeCore(httpContext);
        if (!authorized)
        {
            // The user is not authenticated or doesn't have 
            // permissions to access this controller action
            return false;
        }

        // at this stage we know that there's some user authenticated

        // Let's get the Guid now from our route:
        var routeData = httpContext.Request.RequestContext.RouteData;

        var id = routeData.Values["id"] as string;
        Guid guid;
        if (!Guid.TryParse(id, out guid))
        {
            // invalid Guid => no need to continue any further, just deny access
            return false;
        }

        // Now we've got the GUID that this user is requesting

        // Let's see who this user is:
        string username = httpContext.User.Identity.Name;

        // and finally ensure that this user
        // is actually the owner of the folder
        return IsAuthorized(username, guid);
    }

    private bool IsAuthorized(string username, Guid guid)
    {
        // You know what to do here: hit your data store to verify
        // that the currently authenticated username is actually
        // the owner of this GUID
        throw new NotImplementedException();
    }
}

次に、コントローラー アクションをこの認証属性で装飾しましょう。

public class FilesController: Controller
{
    [MyAuthorize]
    public ActionResult Index(Guid guid, string name)
    {
        // at this stage we know that the currently authenticated user
        // is authorized to access the file.

        var path = @"C:\files";
        var file = Path.Combine(path, guid.ToString(), name);
        file = Path.GetFullPath(file);
        if (!file.StartsWith(path))
        {
            // someone tried to be smart and send
            // files/{Guid}/..\..\creditcard.pdf as parameter
            throw new HttpException(403, "Forbidden");
        }

        var file = Path.Combine(@"c:\files", guid.ToString(), name);
        // TODO: adjust the mime type based on the extension
        return File(file, "image/png");
    }
}
于 2013-01-09T22:20:08.037 に答える