Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/297.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使业务层的方法安全。最佳实践/最佳模式_C#_.net_Security_Design Patterns - Fatal编程技术网

C# 使业务层的方法安全。最佳实践/最佳模式

C# 使业务层的方法安全。最佳实践/最佳模式,c#,.net,security,design-patterns,C#,.net,Security,Design Patterns,我们使用ASP.NET进行大量AJAX“页面方法”调用。 页面中定义的WebServices调用来自BusinessLayer的方法。 为了防止黑客调用页面方法,我们希望在业务层实现一些安全性 我们正与两个不同的问题作斗争 第一个: public List<Employees> GetAllEmployees() { // do stuff } 此方法只能由订单的所有者调用 我知道很容易实现每种方法的安全性,如: public List<Employees> G

我们使用ASP.NET进行大量AJAX“页面方法”调用。 页面中定义的WebServices调用来自BusinessLayer的方法。 为了防止黑客调用页面方法,我们希望在业务层实现一些安全性

我们正与两个不同的问题作斗争

第一个:

public List<Employees> GetAllEmployees()
{
    // do stuff
}
此方法只能由订单的所有者调用

我知道很容易实现每种方法的安全性,如:

public List<Employees> GetAllEmployees()
{
    // check if the user is in Role HR
}
我要寻找的是某种模式/最佳实践,以一种通用的方式实现这种安全性(无需每次编写if-then-else)
我希望您理解我的意思:-)

如果您使用SOA,您可以创建一个安全服务,并且每个操作(方法)都将发送它的上下文(UserId、OrderId等)。安全服务了解业务安全规则

计划可能是这样的

UI -> Security -> BLL -> DAL
一个“最佳实践”是实现一个方面的安全性。这使安全规则与主要业务逻辑保持分离,避免硬编码,并使在不同环境中更改安全规则变得容易

下面的文章列出了实现方面和保持代码独立的7种方法。一种简单且不会改变业务逻辑接口的方法是使用代理。这将公开与当前相同的接口,但允许替代实现,它可以修饰现有实现。可以使用硬编码或自定义属性将安全需求注入该接口。代理拦截对业务层的方法调用,并调用适当的安全检查。这里详细描述了通过代理实现拦截。中给出了其他AOP方法

下面是一个将安全性作为一个方面进行讨论的示例,其中的实现使用建议和安全属性。最终结果是

public static class Roles 
{
    public const string ROLE_ADMIN = "Admin";
    public const string ROLE_CONTENT_MANAGER = "Content Manager";
}

// business method    
[Security(Roles.ROLE_HR)]
public List<Employee> GetAllEmployees();
公共静态类角色
{
公用常量字符串角色\u ADMIN=“ADMIN”;
public const string ROLE\u CONTENT\u MANAGER=“CONTENT MANAGER”;
}
//商业方法
[安全(角色、角色)]
公共列表GetAllEmployees();

您可以将该属性直接放在您的业务方法上、紧密耦合,或者使用这些属性创建服务代理,因此安全性细节是分开的。

User@mdma介绍了一些面向方面的编程。为此,您需要使用外部库(如伟大的PostSharp),因为.NET没有太多AOP功能。然而,.NET已经有了一个用于基于角色的安全性的AOP机制,可以解决部分问题。请看以下标准.NET代码示例:

[PrincipalPermission(SecurityAction.Demand, Role="HR")]
public List<Employees> GetAllEmployees()
{
    // do stuff
}
当然,您可以使用AOP框架,但是您仍然需要编写一个特定于框架的属性,该属性将再次调用您自己的安全层。只有当这样一个属性将替换多个方法调用时,例如当必须将代码放入try、catch、finally语句中时,这才有用。当您执行一个简单的方法调用时,单个方法调用和单个属性之间不会有太大区别

当您返回一组对象并希望过滤掉当前用户没有适当权限的所有对象时,LINQ表达式树可以派上用场:

public Order[] GetAllOrders()
{
    IQueryable orders = GetAllOrdersInternal();
    orders = BusinessSecurity.ApplySecurityOnOrders(orders);
    return orders.ToArray();
}

static class BusinessSecurity
{
    public static IQueryable<Order> ApplySecurityOnOrders(
       IQueryable<Order> orders)
    {
        var user = Membership.GetCurrentUser();

        if (user.IsInRole("Administrator"))
        {
            return orders;
        }

        return 
            from order in orders
            where order.Customer.User.Name == user.Name
            select order; 
    }
}
公共秩序[]GetAllOrders()
{
IQueryable orders=GetAllOrdersInternal();
orders=BusinessSecurity.ApplySecurityOnOrders(订单);
返回订单。ToArray();
}
静态类业务安全
{
公共静态IQueryable贴花安全订单(
(可查询订单)
{
var user=Membership.GetCurrentUser();
if(user.IsInRole(“管理员”))
{
退货订单;
}
返回
从订单到订单
其中order.Customer.User.Name==User.Name
选择订单;
}
}
当您的O/RM通过表达式树(如NHibernate、LINQtoSQL和EntityFramework)支持LINQ时,您可以编写一次这样的安全方法,并在任何地方应用它。当然,这样做的好处是,对数据库的查询总是最优的。换句话说,检索到的记录不会超过需要的数量

更新(几年后):

我在我的代码库中使用了这个属性很长一段时间,但几年前,我得出结论,基于属性的AOP有可怕的缺点。例如,它阻碍了可测试性。由于安全代码是由普通代码编织而成的,所以在不模拟有效用户的情况下,无法运行普通的单元测试。这是脆弱的,不应该成为单元测试的关注点(单元测试本身违反了单一责任原则)。除此之外,它还迫使您在代码库中添加该属性


因此,我不使用
PrincipalPermissionAttribute
,而是通过使用包装代码来应用交叉关注点,如安全性。这使我的应用程序更加灵活,测试也更加容易。在过去的几年里,我已经写了几篇关于这项技术的文章(例如和)。

我知道你这样做已经有一段时间了。尽管如此,我还是建议您将标签([.net/c#])从标题中删除。让他们留在标签里。此外,“嗨”和“谢谢”虽然适合讨论论坛,但不适合这样的问答网站。谢谢。@John,好的。谢谢你的提示。我同意将安全性放在应用程序级别,而不是像其他答案那样放在“框架”级别。如果角色是动态的呢?在我看来,解决方案与框架联系太紧密(通过装饰方法)。我将把安全特性作为系统的一部分来实现,因为它不像看上去那样在业务逻辑之外。不过我喜欢代理的建议。。我的2美分。@Mike-属性是你自己的,所以我不知道这是如何与任何框架联系在一起的。它们是一个实现细节——去极化安全性
[PrincipalPermission(SecurityAction.Demand, Role="HR")]
public List<Employees> GetAllEmployees()
{
    // do stuff
}
public Order GetMyOrder(int orderId)
{
    Order o = GetOrderInternal(orderId);
    BusinessSecurity.ValidateOrderForCurrentUser(o);
}
public Order[] GetAllOrders()
{
    IQueryable orders = GetAllOrdersInternal();
    orders = BusinessSecurity.ApplySecurityOnOrders(orders);
    return orders.ToArray();
}

static class BusinessSecurity
{
    public static IQueryable<Order> ApplySecurityOnOrders(
       IQueryable<Order> orders)
    {
        var user = Membership.GetCurrentUser();

        if (user.IsInRole("Administrator"))
        {
            return orders;
        }

        return 
            from order in orders
            where order.Customer.User.Name == user.Name
            select order; 
    }
}