我有一个应用程序,由DAL,BLL和API层组成,Iam使用统一注入。在Business层中,我有一个名为AuthRepository的类,它继承自IAuthRepository,以下是该类的一部分。
BLL中的类AuthRepository:
public class AuthRepository : IAuthRepository, IDisposable
{
private UserAuthContext _authContext;
private UserManager<UserInfo> _userManager;
// Issue 1: this constructor should be delete and use injection instead
// to solve the problem in class SimpleAuthorizationServerProvider
public AuthRepository()
{
_authContext = new UserAuthContext();
_userManager = new UserManager<UserInfo>(new UserStore<UserInfo>(_authContext));
}
public AuthRepository(UserAuthContext authContext)
{
_authContext = authContext;
//this._authContext = new UserAuthContext();
_userManager = new UserManager<UserInfo>(new UserStore<UserInfo>(_authContext)); // TODO: implement usermanager with Unity
}
public async Task<IdentityResult> RegisterUser(UserEntity createUserModel)
{
UserInfo user = new UserInfo
{
FirstName = createUserModel.FirstName,
LastName = createUserModel.LastName,
UserName = createUserModel.UserName,
Email = createUserModel.Email
};
var result = await _userManager.CreateAsync(user, createUserModel.Password);
return result;
}
在API层中我有另一个名为SimpleAuthorizationServerProvider的类,该类负责Owin提供的Bear令牌以下是类
API层中的SimpleAuthorizationServerProvider类:
public class SimpleAuthorizationServerProvider : OAuthAuthorizationServerProvider
{
public override Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
{
// Resource owner password credentials does not provide a client ID.
if (context.ClientId == null)
{
context.Validated();
}
return Task.FromResult<object>(null);
}
public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { "*" });
using (AuthRepository _repo = new AuthRepository())
{
IdentityUser user = await _repo.FindUser(context.UserName, context.Password);
if (user == null)
{
context.SetError("invalid_grant", "The user name or password is incorrect.");
return;
}
}
var identity = new ClaimsIdentity(context.Options.AuthenticationType);
identity.AddClaim(new Claim("sub", context.UserName));
identity.AddClaim(new Claim("role", "user"));
context.Validated(identity);
}
}
问题是应该删除AuthRepository中的第一个构造函数以使应用程序耦合。如果我删除这个构造函数,所以我需要在此语句的方法GrantResourceOwnerCredentials中从SimpleAuthorizationServerProvider类发送一个类型为UserAuthContext的参数
使用(AuthRepository _repo = new AuthRepository())
那就是我不想做的事情,API层应该与BLL而不是DAL进行通信。
知道如何解决这个问题吗?
答案 0 :(得分:1)
我不熟悉Unity
但通常IoC容器应该注意通过构造函数注入注入依赖项。在您的情况下,您应该更改SimpleAuthorizationServerProvider
和AuthRepository
类。
public class SimpleAuthorizationServerProvider
{
private IAuthRepository _authRepository;
public SimpleAuthorizationServerProvider(IAuthRepository authRepository)
{
_authRepository = authRepository
}
...
public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { "*" });
// no need for new repository anymore
// class already has repository injected
IdentityUser user = await _authRepository.FindUser(context.UserName, context.Password);
if (user == null)
{
context.SetError("invalid_grant", "The user name or password is incorrect.");
return;
}
var identity = new ClaimsIdentity(context.Options.AuthenticationType);
identity.AddClaim(new Claim("sub", context.UserName));
identity.AddClaim(new Claim("role", "user"));
context.Validated(identity);
}
}
public class AuthRepository : IAuthRepository, IDisposable
{
public AuthRepository(UserAuthContext userAuthContext, UserManager<UserInfo> userManager)
{
_userAuthContext = userAuthContext;
_userManager = userManager;
}
...
}
如果您的AuthRepository
类不需要UserAuthContext
(您的代码段仅使用它来创建UserManager<UserInfo>
),那么您可以从构造函数中删除该类并将该依赖项移至UserManager<T>
类的构造函数:
public class AuthRepository : IAuthRepository, IDisposable
{
public AuthRepository(UserManager<UserInfo> userManager)
{
_userManager = userManager;
}
...
}
public class UserManager<T>
{
private UserAuthContext _userAuthContext;
public UserManager<T>(UserAuthContext userAuthContext)
{
_userAuthContext = userAuthContext;
}
...
}
最后,您需要按照in the documentation
所述注册必须使用Unity注入的所有类还有一件事:在可能的情况下,您最好用接口替换构造函数中的具体类。通常,最好是针对接口而不是具体类进行编程。可以找到一个很好的概述here
修改强>
添加了GrantResourceOnwerCredentials
的主体,强调您不再需要新的存储库,因为该对象已经可以访问注入的存储库。
<强>更新强>
在您的启动课程中,您不应该创建新的SimpleAuthorizationServerProvider
,而是要求SimpleAuthorizationServerProvider
依赖Java HotSpot(TM) 64-Bit Server VM warning: INFO: os::commit_memory(0x000000078fb80000, 293601280, 0) failed; error='Cannot allocate memory' (errno=12)
的{{3}}为您执行此操作。
答案 1 :(得分:1)
按照venerik的指示进行操作,所以添加一个带有IAuthRepository接口的构造函数:
public class SimpleAuthorizationServerProvider
{
private IAuthRepository _authRepository;
public SimpleAuthorizationServerProvider(IAuthRepository authRepository)
{
_authRepository = authRepository
}
...
然后,正如您在Startup类中注册SimpleAuthorizationServerProvider时所提到的那样,您需要传递类型为“ IAuthRepository ”的参数,您可以通过添加以下内容来执行此操作:
var OAuthServerOptions = new OAuthAuthorizationServerOptions()
{
AllowInsecureHttp = true,
TokenEndpointPath = new PathString("/token"),
AccessTokenExpireTimeSpan = TimeSpan.FromMinutes(60),
Provider = new SimpleAuthorizationServerProvider((IAuthRepository)GlobalConfiguration.Configuration.DependencyResolver.GetService(typeof(IAuthRepository)))
};
在上面的代码中, provider 行是您需要注入具体类的地方。
P.S。我假设您在Owin启动文件中注册Unity配置,即
public class Startup
{
public void Configuration(IAppBuilder app)
{
UnityConfig.RegisterComponents();
ConfigureOAuth(app);
...