我当前正在使用异步Task方法来实现IAuthenticationFilter接口。成功登录后,我将尝试访问具有此属性的API,它将正常工作。但是,一旦我返回并再次访问API,就会抛出异常。
public async Task AuthenticateAsync(HttpAuthenticationContext context, CancellationToken cancellationToken)
{
var token = context.Request.Headers.Authorization.Parameter;
var principal = await AuthenticateToken(token)
// Other code here ...
}
protected Task<IPrincipal> AuthenticateToken(string token)
{
var secretKey = _authenticationBusiness.GetSecretKey(); // error triggers here.
if (principal == null)
context.ErrorResult = new AuthenticationFailureResult("Invalid token", request);
else
context.Principal = principal;
}
//AuthenticationBusiness.cs
public string GetSecretKey()
{
using (_unitOfWork)
{
var token = _unitOfWork.Tokens.GetToken();
return token.SecretKey ?? string.Empty;
}
}
//Dependency Injection using Unity
container.RegisterType<IUnitOfWork, UnitOfWork>(new HierarchicalLifetimeManager());
container.RegisterType<IContext, Context>(new HierarchicalLifetimeManager());
//UnitOfWork.cs
private readonly IContext _context;
public UnitOfWork(IContext context, IJWTRepository tokens)
{
_context = context;
Tokens = tokens;
}
public IJWTRepository Tokens { get; private set; }
public void Dispose()
{
_context.Dispose();
}
//Context.cs
public class Context : DbContext, IContext
{
public new void SaveChanges()
{
base.SaveChanges();
}
public new void Dispose()
{
base.Dispose();
}
}
//JWTRepository.cs
public class JWTRepository : Repository<JsonWebToken>, IJWTRepository
{
public JWTRepository(Context context) : base(context) { }
public JsonWebToken GetToken()
{
return Context.Tokens
.OrderBy(jwt => jwt.Id)
.Take(1)
.SingleOrDefault();
}
private Context Context => _context as Context;
}
如果我尝试删除此属性并多次访问API,那么不会发生任何错误,因此我认为这与该属性具有异步方法有关吗?
答案 0 :(得分:2)
当IDisposable对象的生存期限制为单个时 方法,您应该在using语句中声明并实例化它。 using语句在对象中的对象上调用Dispose方法。 正确的方式,并且(当您如前所述使用时)也会导致 调用Dispose时,对象本身将超出范围。中 using块,该对象是只读的,无法修改,或者 重新分配。
using Statement (C# Reference)
在您的代码中,问题在于您将GetSecretkey()
包装到using()
中,这将处置_unitOfWork
,并且当您再次尝试访问它时将显示错误。
希望此代码对您有用。
//AuthenticationBusiness.cs
public string GetSecretKey()
{
var token = _unitOfWork.Tokens.GetToken();
return token.SecretKey ?? string.Empty;
}
答案 1 :(得分:0)
函数AuthenticateToken
中的问题。使用async-await时,如果Task处理了项目,请确保在返回之前先等待每个Task。参见what is the purpose of return await。第一个答案集中在一次性物品上
我假设您省略了方法AuthenticateToken
的某些部分,因为我没有说返回值。
解决方案:声明方法async,并在返回之前等待Task
async Task<IPrincipal> AuthenticateToken(string token)
{
var secretKey = _authenticationBusiness.GetSecretKey();
...
// Somewhere there is a Task involved,
Task<IPrincipal> myTask = ...
// instead of return myTask:
return await myTask;
}