如何阻止自定义的基于ef的RoleProvider缓存结果?
本文关键字:缓存 RoleProvider 结果 ef 何阻止 自定义 | 更新日期: 2023-09-27 18:10:34
我有一个ASP。NET MVC 4应用程序,需要使用预先存在的用户/角色成员模型。我这样做的方法是实现一个自定义ASP。. NET RoleProvider来管理访问,它使用实体框架存储库从数据库读取用户数据。读取用户角色的方法如下所示,但是所有的方法实现都遵循这个模式:
public class OurRoleProvider : RoleProvider
{
private IUserRepository _userRepository;
public OurRoleProvider() : this(Container.Resolve<IUserRepository>())
{
}
public OurRoleProvider(IUserRepository userRepository)
{
_userRepository = userRepository;
}
public override string[] GetRolesForUser(string username)
{
var user = _userRepository.GetUserByUserName(username);
if (user.Roles.IsNullOrEmpty())
return new string[0];
return user.Roles.Select(r => r.RoleName).ToArray();
}
}
我现在遇到了这篇文章中描述的问题。因为RoleProvider的单个实例在应用程序的生命周期内被重用,并且所有其他功能都会创建它自己的每个请求DbContext来持久化数据,所以对User配置文件所做的更改不会被RoleProvider反映,直到应用程序中重新启动,因为它的底层DbContext没有被刷新。这意味着你可以从一个角色中删除一个用户,并且他们仍然可以访问该角色的功能,直到应用程序重新启动。
我已经尝试在RoleProvider方法中创建一个新的存储库实例,即在GetRoleForUser():
var user = _userRepository.GetUserByUserName(username);
是
var userRepository = Container.Resolve<IUserRepository>();
var user = userRepository.GetUserByUserName(username);
这修复了这个问题,但破坏了不使用DI容器并通过构造函数注入模拟存储库的单元测试。会有很多单元测试需要重写。
如果可能的话,我想坚持使用自定义角色提供者,以利用诸如Authorize
属性之类的功能。我真正需要做的是在每个请求的基础上重新实例化RoleProvider,或者强制EF存储库始终从数据库更新。到目前为止,我还没有找到这样做的方法。这可能吗?还是有更好的解决方案?
你不应该将EF Services的生命周期定义为单例(它应该是per-request
生命周期)。因为DbContext不是线程安全的,而且它的设计寿命很短。激活角色提供者的缓存是在其他地方完成的,在web中。配置文件:
<roleManager defaultProvider="CustomRoleProvider" cacheRolesInCookie="true" enabled="true">
<providers>
<clear />
<add name="CustomRoleProvider" type="Security.CustomRoleProvider" />
</providers>
</roleManager>
上面的自定义角色提供程序被缓存,因为它在这里使用了cacherolesinccookie ="true"