2014-12-05 61 views
0

我在我的MVC项目上使用owin认证。 我有导航属性的订单和用户(ApplicationUser)表。EF代码第一次拦截OWIN User.Identity到所有查询

每次我querieng订单授权的用户,我需要检查用户:

public class TestController : Controller 
{ 
    public ActionResult Index() 
    { 
     using (var ctx = new TestContext()) 
     { 
      ctx.Orders.Where(o => o.User == User.Identity.Name).Where(...).ToList(); 
     } 
    } 
} 

如果我忘了什么地方检查,用户将获得所有订单。

我想是这样或者一些更好的方式来做到这一点:

[InterceptQuery] 
public Expression<Func<Orders, Boolean>> FilterUser(){ 
    return o => o.Where(o => o.User == HttpContext.User.Identity.Name); 
} 

,当我quering Orders表,它会永远闪光。

+0

为什么你不这样做过滤器的存储库?所以你只写一次,每次调用都会执行。 – 2014-12-05 13:02:00

+0

你是什么意思?我没有存储库,只有上下文 – 2014-12-05 13:16:18

回答

1

建立在你的背景下,资源库,让您的代码使用的仓库,所以你会在仓库中添加方法过滤,并以此做每次调用库方法将得到过滤后的数据,所以朝鲜年轻人联合阵线不要不要重复自己,无处不在,只需在存储库中。

编辑:

您可以实现这样的仓库:

// an interface around the current user, so you can mock this later 
// and test your repository with your own username. 
public interface ICurrentUser 
{ 
    string UserName { get; } 
} 

// the implementation of the current user which get the username from the current identity. 
public class CurrentUser : ICurrentUser 
{ 
    public string UserName 
    { 
     get 
     { 
      return HttpContext.Current.User.Identity.Name; 
     } 
    } 
} 

// a simple repository to get the orders filtered by the current user. 
public interface IOrderRespositroy 
{ 
    List<Order> GetAllOrders(); 
} 

// the implementation of the orderrepository interface, 
// this get the dbcontext, which get the orders from the data base, 
// but you will filter all orders by the username 
public class OrderRepository : IOrderRespositroy 
{ 
    private readonly TestContext _context; 

    public OrderRepository(TestContext context, ICurrentUser currentUser) 
    { 
     _context = context; 
    } 

    public List<Order> GetAllOrders() 
    { 
     return _context.Orders.Where(o=> o.User == currentUser.UserName).Where() 
    } 
} 

// your new controller which depends on IOrderRepository, and your code will not be polluted 
// by the code to filter the orders by the current user. 
public class TestController : Controller 
{ 
    private readonly IOrderRespositroy _repository; 

    public TestController(IOrderRespositroy repository) 
    { 
     _repository = repository; 
    } 

    public ActionResult Index() 
    { 
     var orders = _repository.GetAllOrders(); 

     // . 
     // . 
     // . 
    } 
} 

现在,您可以设置使用像Autofac IoC容器你的依赖,但通过上面的图案,你可以轻松更改例如,如果您决定所有订单都应由userName和userAccess过滤(例如),则过滤逻辑。

希望有所帮助。

+0

为什么我会创建一个存储库,如果ef dbcontext是存储库本身的设计? – 2014-12-05 13:42:26

+0

因此,您可以通过编写一次过滤代码来使代码变干,并且您可以更轻松地单元测试代码。 – 2014-12-05 13:48:49

0

我建议您覆盖AuthorizeAttribute并将其应用于操作和/或控制器需要。

public class OrdersAuthorizeAttribute : AuthorizeAttribute 
{ 
    protected virtual bool AuthorizeCore(HttpContextBase httpContext) { 
    { 
     base.AuthorizeCore(httpContext); 

     IPrincipal user = httpContext.User; 

     if (!user.Identity.IsAuthenticated) { 
      return false; 
     } 

     return ctx.Orders.FirstOrDefault(o => o.User == user.Identity.Name) != null; 
    } 
}