Angular14与.NET7页面刷新时Http解析失败问题求助
Angular 14 + .NET 7 刷新页面Http解析失败问题解决
问题现象
刷新页面时触发以下错误:
Http failure during parsing for https://localhost:6001/Account/Login?ReturnUrl=%2Fapi%2Faccount%2Fcurrentuser
错误截图:
问题定位
移除下方代码并删除GetCurrentUser中角色相关逻辑后,应用恢复正常但丢失角色功能,说明问题出在Identity服务配置和角色处理逻辑上:
builder.Services.AddIdentity<ApplicationUser, ApplicationRole>() .AddRoles<ApplicationRole>() .AddEntityFrameworkStores<ShopDbContext>();
核心原因
- Identity服务重复注册:代码先调用
AddIdentityCore<ApplicationUser>(),又重复调用AddIdentity<ApplicationUser, ApplicationRole>(),导致服务冲突,触发默认Cookie认证流程而非JWT认证,后端返回登录页面HTML而非预期JSON,前端解析失败。 - 角色关联配置缺失:自定义
ApplicationRole与ApplicationUser的关联实体(ApplicationUserRole)未在DbContext中正确配置,角色操作时触发异常。
解决方案
步骤1:修复Identity服务注册逻辑
修改AddIdentityServices方法,避免重复注册,统一用AddIdentityCore扩展角色支持:
public static IServiceCollection AddIdentityServices(this IServiceCollection services, IConfiguration config) { // 初始注册IdentityCore并指定用户类型 var builder = services.AddIdentityCore<ApplicationUser>(options => { // 可按需添加密码复杂度、账号锁定等配置 }); // 传入角色类型构建IdentityBuilder builder = new IdentityBuilder(builder.UserType, typeof(ApplicationRole), builder.Services); // 添加SignInManager、角色管理器及EF存储支持 builder.AddSignInManager<SignInManager<ApplicationUser>>() .AddRoles<ApplicationRole>() .AddRoleManager<RoleManager<ApplicationRole>>() .AddEntityFrameworkStores<ShopDbContext>(); // 配置JWT认证 services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddJwtBearer(options => { options.TokenValidationParameters = new TokenValidationParameters { ValidateIssuerSigningKey = true, IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(config["Token:Key"])), ValidIssuer = config["Token:Issuer"], ValidateIssuer = true, ValidateAudience = false }; }); return services; }
步骤2:配置DbContext角色关联
确保ShopDbContext继承带自定义角色的IdentityDbContext,并配置用户角色关联表:
public class ShopDbContext : IdentityDbContext<ApplicationUser, ApplicationRole, int, IdentityUserClaim<int>, ApplicationUserRole, IdentityUserLogin<int>, IdentityRoleClaim<int>, IdentityUserToken<int>> { public ShopDbContext(DbContextOptions<ShopDbContext> options) : base(options) { } protected override void OnModelCreating(ModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); // 配置用户角色关联表映射 modelBuilder.Entity<ApplicationUserRole>(userRole => { userRole.HasKey(ur => new { ur.UserId, ur.RoleId }); userRole.HasOne(ur => ur.Role) .WithMany(r => r.UserRoles) .HasForeignKey(ur => ur.RoleId) .IsRequired(); userRole.HasOne(ur => ur.User) .WithMany(u => u.UserRoles) .HasForeignKey(ur => ur.UserId) .IsRequired(); }); } }
同时给ApplicationUser添加角色集合属性:
public class ApplicationUser : IdentityUser<int> { // 原有属性... public virtual ICollection<ApplicationUserRole> UserRoles { get; set; } }
步骤3:完善GetCurrentUser方法逻辑
添加角色后保存上下文,同时规范异常返回:
[Authorize] [HttpGet] public async Task<ActionResult<UserDto>> GetCurrentUser() { var user = await _userManager.FindByEmailFromClaimsPrincipal(User); if (user == null) { return NotFound(); // 用NotFound替代null,符合REST规范 } var role = (await _userManager.GetRolesAsync(user)).FirstOrDefault(); if (role == null) { role = Role.Standard.ToString("f"); var result = await _userManager.AddToRoleAsync(user, role); if (result.Succeeded) { await _context.SaveChangesAsync(); // 保存角色添加操作 } else { return BadRequest(result.Errors); // 返回角色添加失败的错误信息 } } return new UserDto { Email = user.Email, Token = _tokenService.CreateToken(user), DisplayName = user.DisplayName, Role = role, }; }
步骤4:前端请求添加格式声明
在请求头中明确指定接受JSON格式,避免解析异常:
loadCurrentUser(token: string | null): Observable<void> { if (token === null) { this.currentUserSource.next(null); return of(); } let headers = new HttpHeaders() .set('Authorization', `Bearer ${token}`) .set('Accept', 'application/json'); // 添加Accept头指定JSON格式 return this.http.get(this.baseUrl + 'account', { headers }).pipe( map((user: any) => { console.log("user = ", user); if (user) { localStorage.setItem('token', user.token); this.currentUserSource.next(user); } }), catchError(error => { console.error('请求错误:', error); return throwError(() => error); }) ); }
内容的提问来源于stack exchange,提问作者x19
相关产品推荐
相关产品推荐

