(更新已經在這個問題的底部添加)授權使用ASP.NET身份和Autofac OWIN整合
我同時使用MVC5和WebAPI2與Autofac對DI的Web應用程序。該應用程序使用ASP.NET身份和oAuth承載令牌,但後者可能並不重要。這一切都工作得很好,但在這一點上,我需要我的注入服務的相同實例在整個OWIN管道以及我的應用程序的其餘部分共享,因此我試圖爲MVC和Web設置Autofac的OWIN集成API。我似乎很接近 - 除AuthorizeAttibutes
,ApiControllers
之外似乎都可以工作。 oAuth進程成功完成,並最終以不記名令牌登錄,但隨後嘗試使用WebAPI控制器/操作上的所述令牌進行授權失敗。
具體來說,在System.Web.Http.AuthorizeAttribute
的IsAuthorized
方法,IPrincipal.Identity
似乎還沒有被正確的,因爲它不具備相應的索賠實例化和IsAuthenticated
屬性始終爲false。 Autofac的開發人員指出this attribute should work with the OWIN integrations即使該代碼使用GlobalConfiguration
which is not advisable for the OWIN integrations。我已經看到多個建議刪除config.SuppressDefaultHostAuthentication()
(here和here),雖然不可取,但我已經嘗試了絕望,但仍無濟於事 - 對於我的特定配置,這會導致IPrincipal返回爲空。我也試圖修改a much simpler example project比我自己在WebAPI控制器上使用AuthorizeAttribute
也沒有成功。在這一點上,我沒有辦法嘗試,幫助將不勝感激。
這裏是我的Startup.cs:
[assembly: OwinStartup(typeof (Startup))]
namespace Project.Web
{
public partial class Startup
{
public void Configuration(IAppBuilder app)
{
var builder = new ContainerBuilder();
builder.RegisterControllers(Assembly.GetExecutingAssembly());
var config = new HttpConfiguration();
builder.RegisterHttpRequestMessage(config);
builder.RegisterApiControllers(Assembly.GetExecutingAssembly());
RegisterGeneralTypes(builder);
var container = builder.Build();
WebApiConfig.Register(config);
config.DependencyResolver = new AutofacWebApiDependencyResolver(container);
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
WebApiFilterConfig.RegisterGlobalFilters(config.Filters);
app.UseAutofacMiddleware(container);
app.UseAutofacWebApi(config);
app.UseAutofacMvc();
app.UseWebApi(config);
ConfigureAuth(app);
}
private static void RegisterGeneralTypes(ContainerBuilder builder)
{
builder.Register(c => new DomainModelContext())
.AsSelf()
.InstancePerRequest();
builder.Register(c => HttpContext.Current.User.Identity)
.As(typeof (IIdentity));
builder.RegisterType<EmailService>()
.AsImplementedInterfaces()
.InstancePerRequest();
builder.Register(c => new IdentityFactoryOptions<DomainUserManager>
{
DataProtectionProvider = DataProtectionProvider
}).InstancePerRequest();
builder.RegisterType<DomainUserManager>()
.AsSelf()
.UsingConstructor(typeof (IIdentityMessageService),
typeof (IdentityFactoryOptions<DomainUserManager>),
typeof (CustomUserStore))
.InstancePerRequest();
builder.RegisterType<CustomUserStore>()
.AsImplementedInterfaces()
.AsSelf()
.InstancePerRequest();
builder.Register(c => HttpContext.Current.GetOwinContext().Authentication)
.As<IAuthenticationManager>();
}
}
}
和我Startup.Auth.cs:
public partial class Startup
{
internal static IDataProtectionProvider DataProtectionProvider;
public static OAuthAuthorizationServerOptions OAuthOptions { get; private set; }
public static string PublicClientId { get; private set; }
public void ConfigureAuth(IAppBuilder app)
{
var onValidateIdentity = SecurityStampValidator
.OnValidateIdentity<DomainUserManager, DomainUser, int>(
validateInterval: TimeSpan.FromMinutes(30),
regenerateIdentityCallback: (manager, user) =>
user.GenerateUserIdentityAsync(manager, CookieAuthenticationDefaults.AuthenticationType),
getUserIdCallback: id => id.GetUserId<int>());
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
LoginPath = new PathString("/account/login"),
Provider = new CookieAuthenticationProvider
{
OnValidateIdentity = onValidateIdentity
}
});
app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
// Configure the application for OAuth based flow
PublicClientId = "self";
OAuthOptions = new OAuthAuthorizationServerOptions
{
TokenEndpointPath = new PathString("/token"),
Provider = new ApplicationOAuthProvider(PublicClientId),
AuthorizeEndpointPath = new PathString("/api/v1/account/externallogin"),
AccessTokenExpireTimeSpan = TimeSpan.FromDays(14),
};
// Enable the application to use bearer tokens to authenticate users
app.UseOAuthBearerTokens(OAuthOptions);
DataProtectionProvider = app.GetDataProtectionProvider();
}
}
我認爲,涵蓋了,但我會應要求樂意交額外的代碼。
UPDATE
因此,基於jumuro's answer,我改變了我註冊的順序推薦。但是,這只是將完全相同的問題從Web API授權轉移到MVC授權。因爲我更新之前有MVC權威性的工作,我最終試圖在管道註冊AUTH兩次如下:
app.UseAutofacMiddleware(container);
ConfigureAuth(app);
app.UseAutofacWebApi(config);
app.UseAutofacMvc();
app.UseWebApi(config);
ConfigureAuth(app);
這工作,但我真的不能說,我明白爲什麼我不能想象這樣做兩次很好。所以現在我有新的問題:
- 這是有道理的WebAPI需要驗證在 管道註冊第一,但爲什麼在世界上確實MVC要我註冊 驗證最後?
- 我該如何清理並避免兩次撥打
ConfigureAuth
?
那麼會發生什麼?你有錯誤嗎?你能發佈錯誤信息嗎? – NightOwl888
@ NightOwl888就像我所說的,IPrincipal.Identity.IsAuthenticated總是返回爲false,所以授權失敗並且404響應返回給客戶端。沒有什麼事情發生,IPrincipal似乎沒有正確實例化。就具體而言,它的行爲幾乎與我上面發佈的[鏈接之一]完全一樣(http://stackoverflow.com/questions/27294032/webapi-owin-identity-is-not-authorized-after-signing-in )。但是,在我的情況下刪除config.SuppressDefaultHostAuthentication()導致IPrincipal變爲空。 – joelmdev