ASP.NET MVC授权

4
什么是保护asp .net mvc中特定区域的最佳方法?我知道我们可以在每个操作处放置[Authorization]属性,但这似乎非常繁琐,因为你必须到处都放置它。我正在使用会员提供程序,并尝试像在postback模型中那样根据文件夹设置此保护。我使用web.config <location>部分来保护一些文件夹。我在mvc中尝试了这种方法,它似乎可以工作,但大多数教程都使用[Authorization]方式。哪种方法更好?
6个回答

6
我强烈建议不要将它放在web.config中。实际上,Conery、Hanselman、Haack和Guthrie也这样认为--尽管没有高度重视(p223 of Professional ASP.NET MVC 1.0)。
路由是易变的,特别是在MVC中。在WebForm模型中,路由在文件系统上被物理表示,所以你不必真正担心它。在MVC中,路由是"动态的",缺乏更好的术语。
您可能会出现多个路由映射到一个控制器,在web.config中导致维护痛苦。更糟糕的是,您可能会无意中调用一个控制器或忘记在添加/修改路由后更新web.config,并使自己处于开放状态。
然而,如果您保护控制器而不是实际路由,则无需担心将web.config与控制器的情况同步,并更改路由。
以上仅供参考。

5

一个可能的解决方案是创建一个“受保护的控制器”,并将其用作您想要保护的应用程序所有区域的基类。

[Authorize]
public class ProtectedBaseController : Controller { 

}

public class AdminController : ProtectedBaseController { 
  ...
}

public class Admin2Controller : ProtectedBaseController { 
  ...
}

3
将[授权]放在控制器类的顶部。这将锁定整个控制器的操作。

好的,谢谢。问题是哪个更好,在所有控制器中放置还是在一个文件web.config中设置。我选择了web.config。 - dritterweg
是的,很难不同意这一点。 :) - griegs

1

您可以在需要保护的每个控制器中添加 [Authorize]。

您可以在 Startup.cs (或 Global.asax) 中添加过滤器 GlobalFilters.Add(new AuthorizeAttribute()); 并将 [AllowAnonymus] 属性放置在任何允许非注册用户访问的控制器或操作上。

如果选择在每个安全控制器中添加 [Authorize],则需要确保您或团队中的其他人添加的任何控制器都是安全的。为此,我使用以下测试:

[Fact]
public void AllAuth()
{
    var asm = Assembly.GetAssembly(typeof (HomeController));
    foreach (var type in asm.GetTypes())
    {
        if (typeof(Controller).IsAssignableFrom(type))
        {
            var attrs = type.GetCustomAttributes(typeof (AuthorizeAttribute));
            Assert.True(attrs.Any());
        }
    }
}

我认为这种方式比创建ProtectedController更好,因为它不能保证您的系统拥有所有控制器的安全性。此外,这种方式不使用继承,使项目更加繁重。

1

授权是保护应用程序的一种方式;一种方法是将该属性应用于每个控制器。 另一种方法是在登录和注册操作中使用新的AllowAnonymous属性。 基于当前区域进行安全决策是非常糟糕的,会使您的应用程序面临漏洞。

您可以在这里获取代码。

由于ASP.NET MVC 4包括新的AllowAnonymous属性,因此您不再需要编写该代码。
在global.asax中全局设置AuthorizeAttribute,然后进行白名单处理即可。 这种方法被视为保护操作方法的最佳实践。谢谢。


0
[Area("AdminPanel")]
public class TestimonialsController : Controller
{
    private  AppDbContext _context;
    private IWebHostEnvironment _env;
    public TestimonialsController(AppDbContext context, IWebHostEnvironment env)
    {
        _context = context;
        _env = env;
    }
    public IActionResult Index()
    {
        return View(_context.Testimonials);
    }
    // GET: AdminPanel/Testimonials/Create
    public IActionResult Create()
    {
        return View();
    }

    // POST: AdminPanel/Testimonials/Create
    [HttpPost]
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> Create(Testimonial testimonial)
    {
        if (!ModelState.IsValid)
        {
            return View();
        }
        if (!testimonial.Photo.CheckFileType("image/"))
        {
            return View();
        }
        if (!testimonial.Photo.CheckFileSize(200))
        {
            return View();
        }


        testimonial.Image = await testimonial.Photo.SaveFileAsync(_env.WebRootPath, "images");
        await _context.Testimonials.AddAsync(testimonial);
        await _context.SaveChangesAsync();
        return RedirectToAction(nameof(Index));
    }

    // GET: AdminPanel/Testimonials/Edit/5
    public async Task<IActionResult> Update(int? id)
    {
        if (id == null)
        {
            return BadRequest();
        }
        var testimonial = await _context.Testimonials.FindAsync(id);
        if (testimonial == null)
        {
            return NotFound();
        }
        return View(testimonial);
    }

    // POST: AdminPanel/Testimonials/Edit/5
    [HttpPost]
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> Update(int? id, Testimonial newtestimonial)
    {
        if (id==null)
        {
            return BadRequest();
        }
        var oldtestimonial = _context.Testimonials.Find(id);
        if (oldtestimonial == null)
        {
            return NotFound();
        }
        if (!ModelState.IsValid)
        {
            return View();
        }
        if (!newtestimonial.Photo.CheckFileType("image/"))
        {
            return View();
        }
        if (!newtestimonial.Photo.CheckFileSize(200))
        {
            return View();
        }
        var path = Helper.GetPath(_env.WebRootPath, "images", oldtestimonial.Image);
        if (System.IO.File.Exists(path))
        {
            System.IO.File.Delete(path);
        }
        newtestimonial.Image = await newtestimonial.Photo.SaveFileAsync(_env.WebRootPath, "images");
        oldtestimonial.Image = newtestimonial.Image;
        await _context.SaveChangesAsync();
        return RedirectToAction(nameof(Index));
    }
    public async Task<IActionResult> Delete(int id)
    {
        if (id == null)
        {
            return BadRequest();
        }

        var testimonial = _context.Testimonials.Find(id);
        if (testimonial == null)
        {
            return NotFound();
        }
        var path = Helper.GetPath(_env.WebRootPath, "images", testimonial.Image);
        if (System.IO.File.Exists(path))
        {
            System.IO.File.Delete(path);
        }
        _context.Testimonials.Remove(testimonial);
        await _context.SaveChangesAsync();
        return RedirectToAction(nameof(Index));
    }

}

}


并且使用扩展方法,代码如下:public static string GetPath(string root, params string[] folders) { string resultPath = root; foreach (var folder in folders) { resultPath = Path.Combine(resultPath,folder); } return resultPath; } - user19426549
目前你的回答不够清晰。请编辑并添加更多细节,以帮助其他人理解它如何回答所提出的问题。你可以在帮助中心找到有关如何撰写好答案的更多信息。 - Community

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接