问题描述
我正在尝试使用带有[Authorize]属性的Owin创建WebApi项目的IntegrationTests。我完全没有授权方面的经验。 我们正在Service项目中使用Bearer令牌类型的授权注册:
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;
}
}
}
示例控制器方法:
[HttpGet]
[Route("auth/users/{guid}")]
[Authorize]
public HttpResponseMessage GetMobileUser(string guid)
{
var manager = new MobileSecUserManager(context);
return Request.CreateJsonResponseFromObject(manager.GetByGuid(guid));
}
当我实际构建并运行该服务时,此设置始终有效。我可以请求Bearer令牌并在其他请求中使用它,并且它可以正常工作,我已获得请求的授权。
在集成测试项目中,我正在使用Owin.Testing 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,//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<WebAPITestStartup>()
来实现此TestServer。
当我使用这个实体化的TestServer调用端点“ / auth / token”时,我能够获得Bearer令牌。
然后,我尝试在这样的其他请求中使用此令牌:
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]时,此方法将被正确调用。删除此属性后,我还检查了Authorization标头值,并在其中填充了数据。
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)