何处根据授权过滤结果

时间:2015-06-17 21:01:55

标签: asp.net-mvc authorization

[Authorize]
public class ContactController{

    private readonly ContactService service;

    public ContactController(ContactService service){
        this.service = service;
    }

    public IActionResult Index() {
        var model = service.GetContacts();
        return View(model);
    }
} 

public class ContactService {

    private readonly ContactRepository repository;

    public ContactService(ContactRepository repository){
        this.repository = repository;
    }

    public IEnumerable<ContactViewModel> GetContacts() {
        var contacts = repository.GetAll();
        return contacts.Select(c=> new ContactViewModel(c));
    }
}

public class ContactRepository {
    private readonly ApplicationDbContext db;

    public ContactRepository(ApplicationDbContext context){
        db = context;
    }

    public IQueryable<Contact> GetAll() {
        return db.Contacts;
    }
}

现在我想只获取经过身份验证的用户的联系人。假设联系人有一个UserId属性,所以, 我想做。哪里(c =&gt; c.UserId == userId)'某处';

假设代码在哪里?在服务?在存储库?在控制器?

服务的实现将是这样的:

public class ContactService {

    private readonly ContactRepository repository;
    private readonly IIdentity identity;

    public ContactService(ContactRepository repository, HttpContext httpContext){
        if (context?.User?.Identity?.IsAuthenticated == false)
                throw new ArgumentException("Non authenticated request", nameof(httpContext));
            identity = HttpContext.Current.User.Identity;
        this.repository = repository;
    }

    public IEnumerable<ContactViewModel> GetContacts() {
        var contacts = repository.GetAll()
            .Where(c=> c.UserId == identity.GetUserId()); // <-- authorization logic.
        return contacts.Select(c=> new ContactViewModel(c));
    }
}

这是正确的做法吗? 你好吗?另一层?

1 个答案:

答案 0 :(得分:0)

我会警告不要公开从您的存储库中暴露IQueryable。公开IQueryable意味着利用存储库的类确定何时将IQueryable实际解析为数据库往返。这意味着您的存储库难以使用,并且无法提供清晰的关注点分离。

出于这个原因,我在任何数据库存储库(如

)上使用了更具体的接口
public Contact[] GetAllContacts() {}

public Contact GetContact(int userId) {}

返回像Lists和Arrays这样的混凝土而不是IQueryable会强制数据库在存储库中往返。权衡的是它更冗长,但值得分离它所提供的关注点。

[编辑]例如 - 数据库往返实际发生在上面的代码中?实际上,直到视图执行并实际从模型中读取数据才会发生。