为什么 IIdentity 在 ASP.NET Web API 中被重置/替换?
Why is IIdentity getting reset / replaced in ASP.NET Web API?
在 ASP.Net Web API 方法上使用 [Authorize]
属性会导致“401 未经授权”响应。
我有一个处理 context.AuthenticateRequest
事件的 Http 模块,我在其中检查请求的授权 header(Basic
授权),如果有效,则设置 System.Threading.Thread.CurrentPrincipal
到包含新 GenericIdentity
的新 GenericPrincipal
,基于授权 header 中的信息。我还将 HttpContext.Current.User
设置为 GenericPrincipal
的相同实例。
此时,IIdentity
的IsAuthenticated
属性为真。但是,在调用控制器中的操作方法时,System.Threading.Thread.CurrentPrincipal
已设置为包含 System.Security.Claims.ClaimsIdentity
且 IsAuthenticated
= false.
的 System.Security.Claims.ClaimsPrincipal
所以...在我设置 CurrentPrincipal
的点和到达操作方法之间的管道中的某处,CurrentPrincipal
和身份被替换。
API获取ASP.Net身份用户的一些方法(相关网站,API本身不使用ASP.Net身份authentication/authorization),因此 API 项目设置了所有相关的 ASP.Net Identity NuGet 包等
我在其他 API 项目中使用了相同的 Http 模块,这些项目没有所有 ASP.Net Identity NuGet 包等,它工作得很好。
我怀疑 ASP.Net 身份配置导致我的 Basic
身份验证 System.Security.Claims.ClaimsPrincipal
被替换。
如有任何帮助,我们将不胜感激!
这是我的代码:
Http Module - 在此方法结束时,System.Threading.Thread.CurrentPrincipal
和 HttpContext.Current.User
已正确设置。
public class FsApiHttpAuthentication : IHttpModule, IDisposable {
public void Init( HttpApplication context ) {
context.AuthenticateRequest += AuthenticateRequests;
context.EndRequest += TriggerCredentials;
}
private static void AuthenticateRequests( object sender, EventArgs e ) {
string authHeader = HttpContext.Current.Request.Headers["Authorization"];
if ( authHeader != null ) {
System.Net.Http.Headers.AuthenticationHeaderValue authHeaderVal = System.Net.Http.Headers.AuthenticationHeaderValue.Parse(authHeader);
if ( authHeaderVal.Parameter != null ) {
byte[] unencoded = Convert.FromBase64String(authHeaderVal.Parameter);
string userpw = System.Text.Encoding.GetEncoding("iso-8859-1").GetString(unencoded);
string[] creds = userpw.Split(':');
CredentialCache.Credential cred = CredentialCache.GetCredential(creds[0], creds[1]);
if ( cred != null ) {
System.Security.Principal.GenericIdentity identity = new System.Security.Principal.GenericIdentity
(cred.Username);System.Threading.Thread.CurrentPrincipal = new System.Security.Principal.GenericPrincipal(identity, roles);
if ( string.IsNullOrWhiteSpace(cred.RolesList) ) {
System.Threading.Thread.CurrentPrincipal = new System.Security.Principal.GenericPrincipal(identity, null);
} else {
System.Threading.Thread.CurrentPrincipal = new System.Security.Principal.GenericPrincipal(identity, cred.RolesList.Split(','));
}
HttpContext.Current.User = System.Threading.Thread.CurrentPrincipal;
}
}
}
}
Api 控制器 - 当达到此控制器中的 Post
动作时,已设置 System.Threading.Thread.CurrentPrincipal
和 HttpContext.Current.User
到包含 System.Security.Claims.ClaimsIdentity
且 IsAuthenticated
= false 的 System.Security.Claims.ClaimsPrincipal
。
public class ConsumerAccountController : ApiController {
private ApplicationUserManager _userManager;
private ApplicationUserManager UserManager {
get {
return _userManager ?? Request.GetOwinContext().GetUserManager<ApplicationUserManager>();
}
set {
_userManager = value;
}
}
public async System.Threading.Tasks.Task<IHttpActionResult> Post( API.FinancialSamaritan.com.ViewModels.UserCredentials creds ) {
API.FinancialSamaritan.com.ViewModels.CreateUserResult cccur = null;
try {
string username = creds.Username;
string password = creds.Password;
var user = new API.FinancialSamaritan.com.Models.ApplicationUser {
UserName = username,
Email = username,
SecurityQuestion = creds.SecurityQuestion,
SecurityAnswer = UserManager.PasswordHasher.HashPassword(creds.SecurityAnswer),
IsPasswordChangeRequired = true,
EmailConfirmed = true
};
IdentityResult userResult = await UserManager.CreateAsync(user, password);
...
[Authorize]
属性派生自 System.Web.Http.AuthorizeAttribute
而不是 System.Web.Mvc.AuthorizeAttribute
。我必须完全限定属性的名称空间,以便使用 [Authorize]
的 MVC 版本。感谢@RonBrogan 为我指明了正确的方向!
在 ASP.Net Web API 方法上使用 [Authorize]
属性会导致“401 未经授权”响应。
我有一个处理 context.AuthenticateRequest
事件的 Http 模块,我在其中检查请求的授权 header(Basic
授权),如果有效,则设置 System.Threading.Thread.CurrentPrincipal
到包含新 GenericIdentity
的新 GenericPrincipal
,基于授权 header 中的信息。我还将 HttpContext.Current.User
设置为 GenericPrincipal
的相同实例。
此时,IIdentity
的IsAuthenticated
属性为真。但是,在调用控制器中的操作方法时,System.Threading.Thread.CurrentPrincipal
已设置为包含 System.Security.Claims.ClaimsIdentity
且 IsAuthenticated
= false.
System.Security.Claims.ClaimsPrincipal
所以...在我设置 CurrentPrincipal
的点和到达操作方法之间的管道中的某处,CurrentPrincipal
和身份被替换。
API获取ASP.Net身份用户的一些方法(相关网站,API本身不使用ASP.Net身份authentication/authorization),因此 API 项目设置了所有相关的 ASP.Net Identity NuGet 包等
我在其他 API 项目中使用了相同的 Http 模块,这些项目没有所有 ASP.Net Identity NuGet 包等,它工作得很好。
我怀疑 ASP.Net 身份配置导致我的 Basic
身份验证 System.Security.Claims.ClaimsPrincipal
被替换。
如有任何帮助,我们将不胜感激!
这是我的代码:
Http Module - 在此方法结束时,System.Threading.Thread.CurrentPrincipal
和 HttpContext.Current.User
已正确设置。
public class FsApiHttpAuthentication : IHttpModule, IDisposable {
public void Init( HttpApplication context ) {
context.AuthenticateRequest += AuthenticateRequests;
context.EndRequest += TriggerCredentials;
}
private static void AuthenticateRequests( object sender, EventArgs e ) {
string authHeader = HttpContext.Current.Request.Headers["Authorization"];
if ( authHeader != null ) {
System.Net.Http.Headers.AuthenticationHeaderValue authHeaderVal = System.Net.Http.Headers.AuthenticationHeaderValue.Parse(authHeader);
if ( authHeaderVal.Parameter != null ) {
byte[] unencoded = Convert.FromBase64String(authHeaderVal.Parameter);
string userpw = System.Text.Encoding.GetEncoding("iso-8859-1").GetString(unencoded);
string[] creds = userpw.Split(':');
CredentialCache.Credential cred = CredentialCache.GetCredential(creds[0], creds[1]);
if ( cred != null ) {
System.Security.Principal.GenericIdentity identity = new System.Security.Principal.GenericIdentity
(cred.Username);System.Threading.Thread.CurrentPrincipal = new System.Security.Principal.GenericPrincipal(identity, roles);
if ( string.IsNullOrWhiteSpace(cred.RolesList) ) {
System.Threading.Thread.CurrentPrincipal = new System.Security.Principal.GenericPrincipal(identity, null);
} else {
System.Threading.Thread.CurrentPrincipal = new System.Security.Principal.GenericPrincipal(identity, cred.RolesList.Split(','));
}
HttpContext.Current.User = System.Threading.Thread.CurrentPrincipal;
}
}
}
}
Api 控制器 - 当达到此控制器中的 Post
动作时,已设置 System.Threading.Thread.CurrentPrincipal
和 HttpContext.Current.User
到包含 System.Security.Claims.ClaimsIdentity
且 IsAuthenticated
= false 的 System.Security.Claims.ClaimsPrincipal
。
public class ConsumerAccountController : ApiController {
private ApplicationUserManager _userManager;
private ApplicationUserManager UserManager {
get {
return _userManager ?? Request.GetOwinContext().GetUserManager<ApplicationUserManager>();
}
set {
_userManager = value;
}
}
public async System.Threading.Tasks.Task<IHttpActionResult> Post( API.FinancialSamaritan.com.ViewModels.UserCredentials creds ) {
API.FinancialSamaritan.com.ViewModels.CreateUserResult cccur = null;
try {
string username = creds.Username;
string password = creds.Password;
var user = new API.FinancialSamaritan.com.Models.ApplicationUser {
UserName = username,
Email = username,
SecurityQuestion = creds.SecurityQuestion,
SecurityAnswer = UserManager.PasswordHasher.HashPassword(creds.SecurityAnswer),
IsPasswordChangeRequired = true,
EmailConfirmed = true
};
IdentityResult userResult = await UserManager.CreateAsync(user, password);
...
[Authorize]
属性派生自 System.Web.Http.AuthorizeAttribute
而不是 System.Web.Mvc.AuthorizeAttribute
。我必须完全限定属性的名称空间,以便使用 [Authorize]
的 MVC 版本。感谢@RonBrogan 为我指明了正确的方向!