参考系统是不是不好的做法.网状物使用实体服务/存储库模式时模型中的安全性



在我的ASP.net网站上,我需要检查登录的用户是否属于某个角色,或者我的数据库中的"UserInstance"表中的字段是否设置为true。要做到这一点,我可以做以下事情。

if(Roles.IsUserInRole("Global Admin") 
|| uow.UserInstanceService.GetUserInstance(userId,InstanceId).Admin)
{
 //Do something
}

然而,由于我将在很大程度上使用这段代码,因为许多权限取决于登录用户是"全局管理员",或者我表中的某个字段是true,我不想经常写出来。

我找到的一个解决方案是在"UserInstance"服务中创建一个方法,该方法检查"IsUserAdminOrGlobalAdmin"方法中的两者。

 public class UserInstanceService
{
    IRepository<UserInstance> userInstanceRepository;
    public UserInstanceService(IRepository<UserInstance> userInstanceRepository)
    {
        this.userInstanceRepository = userInstanceRepository;
    }
    public UserInstance GetByUserIdAndInstanceId(Guid userId, int instanceId)
    {
       return userInstanceRepository.GetSingle(u => u.UserId == userId && u.InstanceId == instanceId);
    }
   public bool IsUserAdminOrGlobalAdmin(Guid userId,int instanceId)
    {
        bool valid = false;
        if (System.Web.Security.Roles.IsUserInRole("Global Admin"))
            valid = true;
        if (GetByUserIdAndInstanceId(userId, instanceId).Admin)
            valid = true;
        return valid;
    } 
   //Removed rest of methods for readability
}

由于这是构建逻辑,我将此方法放在我的"UserInstanceService"类中,该类与包含实体上下文的存储库类交互。这个服务类位于一个单独的Model项目中,所以我不得不添加对System的引用。网状物安全,我不确定这样做是否是一种好的做法。我注意到的一件事是,我不能为这个方法编写单元测试,因为它依赖于登录的用户

所以我的问题是,在服务中结合HttpContext特定的功能(如登录用户角色)是否可以接受?

编辑-在阅读答案后,我更改了代码,因此调用了一个Auth服务(在Web应用程序项目中),该服务反过来调用UserInstanceService进行类似操作。

public class Auth: IAuthService {
public bool IsUserAdminOrGlobalAdmin(Guid userId,int instanceId) {
    myEntities entityContext = new myEntities
    //RepsitoryBase inherits my IRepository<TEntity> class 
    UserInstanceService uis = new UserInstanceService(new RepositoryBase<UserInstance>(entityContext));
    bool valid = false
    if(Roles.IsUserInRole("Global Admin"))
         valid = true;
    if(uis.GetByUserIdAndInstanceId(userId,instanceId).Admin)
         valid = true;
    return valid;
}

}

所以我可以在我的页面上称之为

if(Auth.IsUserAdminOrGlobalAdmin(userId,InstanceId)
{
//Do stuff
}

最初的答案是在假设UserAccess需要身份验证的情况下编写的,但似乎身份验证消耗了UserAccess;只需颠倒依赖项,但其他所有内容都应该以大致相同的方式可用。


原始答案:

拉动ASP。NET特定的代码集成到它的自己的服务中,该服务独立于存储库。然后,任何需要访问集中式身份验证/授权逻辑的组件(如UserInstanceService)都可以使用该服务,比如Auth服务。

根据IoC原则,将Auth作为依赖项使用,希望使用一些DI让生活更轻松。

如果Auth服务是单独的,那么它也可以被简单地模拟用于测试,例如测试当使用是否经过身份验证时会发生什么,这完全避免了设置完整ASP的需要。NET堆栈。

此外,由于服务(接口)和组件(类)是独立的,因此实际使用HTTP的组件可以与服务单独存在于一个项目中,并在以后连接,这将避免将Web依赖关系拉入Model项目。


例如,

// This is the Service Contract and can live in the Model
public class IAuthService {
    void AssertCurrentUserIsAdminOrGlobalAdmin();
    void AssertIsUserAdminOrGlobalAdmin(Guid userId,int instanceId);
}    
// This is the Component, which provides the Service, and is part
// of the Web/HTTP-specific project. It is wired up via IoC/DI from
// the large context of the application.
public class Auth: IAuthService {
    public void AssertCurrentUserIsAdminOrGlobalAdmin() {
       // This one already knows the applicable HTTP/User Context
    }
    public void AssertIsUserAdminOrGlobalAdmin(Guid userId,int instanceId) {
       // Do whatever
    }
}
// This Component is part of the Model
public class UserInstanceService
{
    // IoC dependencies
    IRepository<UserInstance> userInstanceRepository;
    IAuthService authService;
}

您可以在线程上设置当前主体并使用它。我认为ASP。网络也为你服务。

最新更新