ASP.NET MVC Post Authentication IoC setup
本文关键字:IoC setup Authentication Post NET MVC ASP | 更新日期: 2023-09-27 18:18:51
我有一个http客户端包装器,我注入到我所有的控制器。如果一个用户是经过身份验证的,注入的包装器应该有一些属性设置为经过身份验证的用户信息。
我现在有这个:
[System.Web.Mvc.Authorize]
public class ProfileController : Controller
{
private readonly IMyClient client;
public ProfileController()
{
string apiKey = ConfigurationManager.AppSettings["ApiKey"];
client = new MyClient(apiKey);
SetupClient();
}
private void SetupClient()
{
if (Thread.CurrentPrincipal.Identity.IsAuthenticated)
{
var identity = Thread.CurrentPrincipal.Identity as ClaimsIdentity;
var tokenClaim = identity.Claims.First(c => c.Type == ClaimTypes.Sid);
client.AddCredentials(tokenClaim.Value);
}
}
}
我想卸载SetupClient
到某个地方,将允许我做IMyClient
的依赖注入。
本质上我想实现这个解决方案:
ProfileController.cs
[System.Web.Mvc.Authorize]
public class ProfileController : Controller
{
private readonly IMyClient client;
public ProfileController(IMyClient client)
{
this.client = client;
}
}
Startup.cs
public partial class Startup
{
public void Configuration(IAppBuilder app)
{
IoCConfig.RegisterIoC(app);
ConfigureAuth(app);
}
}
IoCConfig.cs
public class IoCConfig
{
public static void RegisterIoC(IAppBuilder app)
{
var container = new Container();
container.Register<IMyClient>(
() =>
{
var apiKey = ConfigurationManager.AppSettings["APIKey"];
var myClient= new MyClient(apiKey);
// This will not work as this code is executed on app start
// The identity will not be of the user making the web request
var identity = Thread.CurrentPrincipal.Identity as ClaimsIdentity;
var tokenClaim = identity.Claims.First(c => c.Type == ClaimTypes.Sid);
client.AddCredentials(tokenClaim.Value);
return myClient;
});
// Register the dependency resolver.
DependencyResolver.SetResolver(
new SimpleInjectorDependencyResolver(container));
}
}
我被困在IoCConfig的代码中,以提取经过身份验证的用户的信息(如果用户经过身份验证),并设置客户端进行注入。有什么帮助吗?
我的IoC框架是SimpleInjector,但我想要一个不可知的解决方案。
我是这样做的
public class ProfileController : Controller
{
private readonly MyClient _client;
public ProfileController()
{
var clientInfo = Resolve<IClientInfo>(); // call out to your service locator
_client = clientInfo.GetClient();
}
}
public interface IClientInfo
{
MyClient GetClient();
}
public interface IAuth
{
System.Security.Claim GetSidClaim();
}
public class ClientInfo : IClientInfo
{
private readonly IAuth _auth;
public ClientInfo(IAuth auth)
{
_auth = auth;
}
public MyClient GetClient()
{
var apiKey = ApiKey;
var client = new MyClient(apiKey);
var claim = _auth.GetSidClaim();
client.AddCredentials(claim.Value);
return client;
}
protected virtual string ApiKey
{
get { return ConfigurationManager.AppSettings["APIKey"]; }
}
}
我会看看NInject和MVC扩展…
http://ninject.codeplex.com/wikipage?title=Dependency%20Injection%20With%20Ninjecthttp://www.codeproject.com/Articles/412383/Dependency-Injection-in-asp-net-mvc-and-webapi-us
当设置正确时,它只是一个为IMyClient创建绑定的问题,NInject将隐式地为您注入它。还有很多其他的注入框架,NInject只是我选择的一个。它们中的每一种都会给你带来实质性的好处,而不是你自己做的任何东西。例如,使用NInject,你可以创建在整个应用中注入单例的绑定,或者为每个请求注入单例的绑定。
在NInject中你可以创建一个像
这样的绑定Bind<IMyClient>().ToMethod(x => SetupClient(x)).InRequestScope();
private IMyClient SetupClient(IContext context)
{
string apiKey = ConfigurationManager.AppSettings["ApiKey"];
var client = new MyClient(apiKey);
if (Thread.CurrentPrincipal.Identity.IsAuthenticated)
{
var identity = Thread.CurrentPrincipal.Identity as ClaimsIdentity;
var tokenClaim = identity.Claims.First(c => c.Type == ClaimTypes.Sid);
client.AddCredentials(tokenClaim.Value);
}
return client;
}
InRequestScope说NInject应该为每个请求创建一个实例…
https://github.com/ninject/Ninject.Web.Common/wiki/InRequestScope我认为等效的SimpleInjector是…
https://simpleinjector.codeplex.com/wikipage?title=ObjectLifestyleManagement PerWebRequest
这个问题的答案就像把你的代码改成…
public static void RegisterIoC(IAppBuilder app)
{
var container = new Container();
container.RegisterPerWebRequest<IMyClient>(
() =>
{
...
我通过CRice发布的使用工厂委托的版本解决了这个问题:
ProfileController.cs
[System.Web.Mvc.Authorize]
public class ProfileController : Controller
{
private readonly IMyClient client;
public ProfileController(Func<IMyClient> clientFactory)
{
client = clientFactory.Invoke();
}
}
IoCConfig.cs
public class IoCConfig
{
public static void RegisterIoC(IAppBuilder app)
{
// Create the container as usual.
Container container = new Container();
// Registering as a factory delegate because we need the user authentication information if any.
container.RegisterSingle<Func<IMyClient>>(() =>
{
string apiKey = ConfigurationManager.AppSettings["ApiKey"];
var myClient = new MyClient(apiKey);
if (Thread.CurrentPrincipal.Identity.IsAuthenticated)
{
var identity = Thread.CurrentPrincipal.Identity as ClaimsIdentity;
var tokenClaim = identity.Claims.First(c => c.Type == ClaimTypes.Sid);
myClient.AddCredentials(tokenClaim.Value);
}
return myClient;
});
// This is an extension method from the integration package.
container.RegisterMvcControllers(Assembly.GetExecutingAssembly());
// This is an extension method from the integration package as well.
container.RegisterMvcIntegratedFilterProvider();
container.Verify();
DependencyResolver.SetResolver(
new SimpleInjectorDependencyResolver(container));
}
}