当尝试发出 JOIN 请求时,Tokens 属性结果为 null:
var user = await dbContext.Tokens
.Where(t => t.refresh_token == hashRefreshToken)
.Join(dbContext.Users, token => token.user_id, user => user.id, (token, user) => user)
.FirstOrDefaultAsync();
虽然如果您发出 2 个单独的请求,则 token 中不会有空值:
var token = await dbContext.Tokens.FirstOrDefaultAsync(t => t.refresh_token == hashRefreshToken);
var user = await dbContext.Users.FindAsync(token.user_id);
这是代币模型:
[Table("tokens")]
public class TokenModel
{
[Key]
public int token_id { get; set; }
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public string? refresh_token { get; set; }
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public DateTime? expiry_date { get; set; }
[ForeignKey("user_id")]
public int user_id { get; set; }
[JsonIgnore]
public UserModel User { get; set; }
}
用户模型:
[Table("users")]
public class UserModel
{
[Key]
[Required]
public int id { get; set; }
[Required]
public string username { get; set; }
[Required]
public string role { get; set; }
[EmailAddress]
[Required]
public string email { get; set; }
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public string password_hash { get; set; }
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public string? api_key { get; set; }
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public UserQuotasModel Quotas { get; set; }
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public UserKeyModel Keys { get; set; }
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public ICollection<UserFileModel> Files { get; set; }
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public TokenModel Tokens { get; set; }
//[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
//public ApiModel API { get; set; }
}
这是 modelBuilder 中关系的配置方式:
modelBuilder.Entity<UserModel>()
.HasOne(u => u.Tokens)
.WithOne(t => t.User)
.HasForeignKey<TokenModel>(t => t.user_id)
.OnDelete(DeleteBehavior.Cascade);
那么数据库集:
public DbSet<TokenModel> Tokens { get; set; }
这是一个使用 Join 和 token 属性 == null 的中间件选项
public async Task Invoke(HttpContext context, FileCryptDbContext dbContext, ITokenService tokenService)
{
if(context.Request.Cookies.TryGetValue("JwtToken", out string? JwtToken))
{
context.Request.Headers.Add("Authorization", $"Bearer {JwtToken}");
}
else
{
if(context.Request.Cookies.TryGetValue("RefreshToken", out string? RefreshToken))
{
var hashRefreshToken = tokenService.HashingToken(RefreshToken);
//var token = await dbContext.Tokens.FirstOrDefaultAsync(t => t.refresh_token == hashRefreshToken);
var user = await dbContext.Tokens
.Where(t => t.refresh_token == hashRefreshToken)
.Join(dbContext.Users, token => token.user_id, user => user.id, (token, user) => user)
.FirstOrDefaultAsync();
if (user is not null && user.Tokens.expiry_date.HasValue)
{
if (user.Tokens.expiry_date > DateTime.UtcNow)
{
//var user = await dbContext.Users.FindAsync(token.user_id);
var userModel = new UserModel { id = user.id, username = user.username, email = user.email, role = user.role };
string NewJwtToken = tokenService.GenerateJwtToken(userModel, 20);
var JwtCookieOptions = tokenService.SetCookieOptions(TimeSpan.FromMinutes(20));
context.Response.Cookies.Append("JwtToken", NewJwtToken, JwtCookieOptions);
context.Request.Headers.Add("Authorization", $"Bearer {NewJwtToken}");
}
}
}
}
await _next(context);
}
好吧,这里有一个选项,其中使用了 2 个单独的请求,并且一切正常:
public async Task Invoke(HttpContext context, FileCryptDbContext dbContext, ITokenService tokenService)
{
if(context.Request.Cookies.TryGetValue("JwtToken", out string? JwtToken))
{
context.Request.Headers.Add("Authorization", $"Bearer {JwtToken}");
}
else
{
if(context.Request.Cookies.TryGetValue("RefreshToken", out string? RefreshToken))
{
var hashRefreshToken = tokenService.HashingToken(RefreshToken);
var token = await dbContext.Tokens.FirstOrDefaultAsync(t => t.refresh_token == hashRefreshToken);
if (token is not null && token.expiry_date.HasValue)
{
if (token.expiry_date > DateTime.UtcNow)
{
var user = await dbContext.Users.FindAsync(token.user_id);
var userModel = new UserModel { id = user.id, username = user.username, email = user.email, role = user.role };
string NewJwtToken = tokenService.GenerateJwtToken(userModel, 20);
var JwtCookieOptions = tokenService.SetCookieOptions(TimeSpan.FromMinutes(20));
context.Response.Cookies.Append("JwtToken", NewJwtToken, JwtCookieOptions);
context.Request.Headers.Add("Authorization", $"Bearer {NewJwtToken}");
}
}
}
}
await _next(context);
}
我注意到,如果您使用 Include,那么一切正常:
var user = await dbContext.Tokens
.Where(t => t.refresh_token == hashRefreshToken)
.Include(t => t.User)
.FirstOrDefaultAsync();
在您的请求中
Join明确指出仅返回用户:将 resultSelector 更正为以下表达式:
两种类型都会返回。
该变量将是匿名类型。我会给她打电话
tokenAndUser。它将有两个属性。我想你会明白的。启用生成的 SQL 查询的日志记录以使其更易于理解。
PS你的命名太糟糕了!纠正它。
嗯,没错。包括加载相关的文档数据。如果你想获得用户
或者