在我的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。网络也为你服务。