C#[Authorize]属性不适用于集成测试中的Microsoft.Owin.Testing
我正在尝试使用with[Authorize]属性为WebApi项目创建IntegrationTests。我对授权一点经验都没有。 我们正在服务项目中使用承载令牌类型的授权注册:C#[Authorize]属性不适用于集成测试中的Microsoft.Owin.Testing,c#,authorization,integration-testing,owin,in-memory,C#,Authorization,Integration Testing,Owin,In Memory,我正在尝试使用with[Authorize]属性为WebApi项目创建IntegrationTests。我对授权一点经验都没有。 我们正在服务项目中使用承载令牌类型的授权注册: public static void ConfigureBasicWithJWT(IAppBuilder app) { app.UseOAuthAuthorizationServer(new OAuthAuthorizationServerOptions { AllowInsecureHttp = true,
public static void ConfigureBasicWithJWT(IAppBuilder app)
{
app.UseOAuthAuthorizationServer(new OAuthAuthorizationServerOptions
{
AllowInsecureHttp = true,
TokenEndpointPath = new PathString("/auth/token"),
AccessTokenExpireTimeSpan = TimeSpan.FromDays(1),//token expiration time
Provider = new OauthProvider()
});
// token consumption
var oauthConfig = new OAuthBearerAuthenticationOptions
{
AuthenticationMode = AuthenticationMode.Active,
AuthenticationType = "Bearer"
};
app.UseOAuthBearerAuthentication(oauthConfig);
}
OAuth提供程序:
public class OauthProvider : OAuthAuthorizationServerProvider
{
public override async Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
{
await Task.Run(() => context.Validated());
}
private bool IsAuthorized(MobileSecLogin login, OAuthGrantResourceOwnerCredentialsContext context)
{
if (login == null || context == null) return false;
//verify by login/pwd first
if (SecurePasswordHasher.Verify(context.Password, login.PassHash))
return true;
//verify by login/token
if (SecurePasswordHasher.Verify(context.Password, login.LoginTokenHash) && login.LoginTokenExpiration < DateTimeOffset.Now)
return true;
return false;
}
public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
var identity = new ClaimsIdentity(context.Options.AuthenticationType);
using (var db = APIContext.MobileDBContext)
{
if (db != null)
{
//verify by login + password
//verify by login + token, but token must be valid in time
var login = db.Logins.GetLoginObjByLogin(context.UserName);
if (!IsAuthorized(login, context))
{
context.SetError("Wrong Credentials", "Provided username and password is incorrect");
return;
}
var user = login?.User;
if (user != null)
{
//get all functional roles from all asigned groups or their children groups
var childGroups = db.Groups.GetChildGroups(user.Groups).ToList();
var funcRoles = db.Roles.GetAllRoles(childGroups);
foreach (var secRole in funcRoles)
{
identity.AddClaim(new Claim(ClaimTypes.Role, secRole.Name));
}
//including all role names
var loggedDate = DateTime.Now;
foreach (var childGroup in childGroups)
{
identity.AddClaim(new Claim(ClaimTypes.Role, childGroup.Name));
}
identity.AddClaim(new Claim(ClaimTypes.Name, user.Name));
identity.AddClaim(new Claim(ClaimTypes.Surname, user.LastName));
identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, login.Id.ToString()));
identity.AddClaim(new Claim(ClaimTypes.Email, user.Email));
identity.AddClaim(new Claim("LoggedOn", loggedDate.ToString()));
//set lastLoginDate
login.LastLoginDate = loggedDate;
APIContext.AuditUser = login.User;
db.AuditUser = login.User;
db.SaveChanges();
await Task.Run(() => context.Validated(identity));
}
else
{
APIContext.AuditUser = null;
db.AuditUser = null;
context.SetError("Wrong Credentials", "Provided username and password is incorrect");
}
}
else
{
APIContext.AuditUser = null;
db.AuditUser = null;
context.SetError("Wrong Credentials", "Provided username and password is incorrect");
}
return;
}
}
}
当我实际构建和运行服务时,此设置始终有效。我可以请求承载令牌并在其他请求中使用它,它可以工作,我可以获得请求授权
在集成测试项目中,我正在使用Owin。测试TestServer:
public class WebAPITestStartup : Program
{
public override void Configuration(IAppBuilder appBuilder)
{
var configuration = new HttpConfiguration();
configuration.MapHttpAttributeRoutes();
configuration.Formatters.Clear();
configuration.Formatters.Add(new JsonMediaTypeFormatter());
appBuilder.UseCors(CorsOptions.AllowAll);
appBuilder.UseWebApi(configuration);
CallControllersStaticConstructors();
ConfigureBasicWithJWTTest(appBuilder);
}
public static void ConfigureBasicWithJWTTest(IAppBuilder app)
{
app.UseOAuthAuthorizationServer(new OAuthAuthorizationServerOptions
{
AllowInsecureHttp = true,
TokenEndpointPath = new PathString("/auth/token"),
AccessTokenExpireTimeSpan = TimeSpan.FromDays(1),//token expiration time
Provider = new OauthProvider()
});
var oauthConfig = new OAuthBearerAuthenticationOptions
{
AuthenticationMode = AuthenticationMode.Active,
AuthenticationType = "Bearer",
};
app.UseOAuthBearerAuthentication(oauthConfig);
}
protected void CallControllersStaticConstructors()
{
foreach (var type in Assembly.GetExecutingAssembly().DefinedTypes.Where(type => type.IsSubclassOf(typeof(ApiController))))
InvokeStaticConstractor(type);
}
private void InvokeStaticConstractor(Type type)
{
RuntimeHelpers.RunClassConstructor(type.TypeHandle);
}
}
我使用:var server=TestServer.Create()
具体化这个TestServer。
当我使用这个具体化的TestServer调用端点“/auth/token”时,我能够获得承载令牌。
然后我尝试在其他请求中使用此令牌,如:
var msg = new HttpRequestMessage(HttpMethod.Get, "auth/users/8bb677a6-39e7-4343-9087-2bc4e004d4df");
msg.Content = content;
msg.Headers.Add("Authorization","Bearer "+_bearerToken);
response=server.HttpClient.SendAsync(msg).Result;
然后响应总是未经授权的(401)。我试图在库内部进行调试,以检查它们如何处理此令牌,但没有找到任何结果
当我删除[Authorize]属性或使用[AllowAnonymous]时,该方法被正确调用。当删除此属性时,我还检查了授权标头值,其中填充了数据。因此我找到了解决方案。我在安装方法中的顺序不正确。在第二段代码中:
appBuilder.UseWebApi(配置)代码>应在该方法中最后使用。
var msg = new HttpRequestMessage(HttpMethod.Get, "auth/users/8bb677a6-39e7-4343-9087-2bc4e004d4df");
msg.Content = content;
msg.Headers.Add("Authorization","Bearer "+_bearerToken);
response=server.HttpClient.SendAsync(msg).Result;