【问题标题】:Angular and ASP.NET Core Role-Base ProblemAngular 和 ASP.NET Core 角色基础问题
【发布时间】:2021-03-09 00:41:14
【问题描述】:

我正在开发一个带有 ASP.NET Core 后端的 Angular Web 应用程序。我的角色有问题。成功登录后,我收到一个包含用户角色的令牌,但是当我尝试调用方法时,我总是从 asp.net 得到这个答案:http://localhost:5000/Account/Login?ReturnUrl=%2Fapi %2FClient%2F 详细信息。为什么?令牌有效且未过期。

角度:

getAllWithContactDetails(): Observable<ClientContact[]> {
  console.log(`here: ${localStorage.getItem('token')}`);
  return this.http.get<ClientContact[]>(`${links.API_URI}/api/Client/details`, {
    headers: new HttpHeaders({
      'Accept': 'application/json',
      'Authorization': `Bearer ${localStorage.getItem('token')}`
    })
  });
}

ASP.NET 核心

//Controller:
[HttpGet("details"), Authorize(Roles = "Admin,Employee,Seller")]
public IEnumerable<ClientContact> GetClientsWithContactDetails()
{
    ...
}

//Login:
...

var tokeOptions = new JwtSecurityToken(
    issuer: jwtAppSettingOptions[nameof(JwtIssuerOptions.Issuer)],
    audience: jwtAppSettingOptions[nameof(JwtIssuerOptions.Audience)],
    claims: new List<Claim>() {
        new Claim(ClaimTypes.NameIdentifier, user.Id),
        new Claim(ClaimTypes.Name, user.UserName),
        new Claim(ClaimTypes.Role, _userManager.GetRolesAsync(user).Result.First())
    },
    expires: DateTime.Now.AddMinutes(10),
    signingCredentials: new SigningCredentials(_signingKey, SecurityAlgorithms.HmacSha256)
);

return Ok(new { Token = new JwtSecurityTokenHandler().WriteToken(tokeOptions) });

ConfigureServices 中的Startup.cs

 public void ConfigureServices(IServiceCollection services)
    {
        services.AddCors(options =>
        {
            options.AddPolicy(name: MyAllowSpecificOrigins,
                builder =>
                {
                    builder.WithOrigins("http://localhost:4200")
                        .AllowAnyHeader()
                        .AllowAnyMethod();
                });
        });

        services.AddDbContext<WebApiContext>(opt =>
           opt.UseSqlServer(Configuration.GetConnectionString("SlkDatabase")));

        var jwtAppSettingOptions = Configuration.GetSection(nameof(JwtIssuerOptions));

        services.AddAuthentication(options =>
        {
            options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
            options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
        }).AddJwtBearer(options =>
        {
            options.TokenValidationParameters = new TokenValidationParameters
            {
                ValidateIssuer = true,
                ValidIssuer = jwtAppSettingOptions[nameof(JwtIssuerOptions.Issuer)],

                ValidateAudience = true,
                ValidAudience = jwtAppSettingOptions[nameof(JwtIssuerOptions.Audience)],

                ValidateIssuerSigningKey = true,
                IssuerSigningKey = _signingKey,

                ValidateLifetime = true,
                ClockSkew = TimeSpan.Zero
            };
        });

        services.AddIdentity<User, IdentityRole>(options =>
            {
                options.Password.RequireNonAlphanumeric = false;
                options.Password.RequireDigit = false;
                options.Password.RequireUppercase = false;
            })
            .AddEntityFrameworkStores<WebApiContext>()
            .AddDefaultTokenProviders();

        services.AddControllers();
        services.AddSwaggerGen(c =>
        {
            c.SwaggerDoc("v1", new OpenApiInfo { Title = "WebApi", Version = "v1" });
        });

        services.AddMvc().AddControllersAsServices();
    }

回复:

【问题讨论】:

  • 你的意思是“但是当我尝试调用一个方法时,我总是从 asp.net 得到这个答案:”服务器响应重定向到 http://localhost:5000/Account/Login?ReturnUrl=%2Fapi%2FClient%2Fdetails 你甚至发出的每个请求如果您已经通过身份验证?
  • 没错。我不知道它为什么要将我重定向到 /Account/Login 页面(该页面不存在)。登录页面的路径就是 /login。
  • 你能分享Startup.csConfigureServices吗?我怀疑可能使用了AddDefaultIdentity 配置,它想要使用默认的 Razor 页面和身份重定向。 (docs.microsoft.com/en-us/dotnet/api/…)
  • @Leaky 感谢您等待我与AddDefaultIdentity 一起检查这个想法。 :) 根据更新后的帖子,情况似乎并非如此。请求-响应管道可能无法处理在 GetClientsWithContactDetails 操作方法中创建的令牌。但我不明白,究竟为什么,所以如果你有一个想法,你可以将它作为答案发布。 :)
  • 在我看来,重定向仍然存在一些问题,因为 404 似乎与登录端点有关,即使原始请求被发送到不同的端点。我认为一个问题是,在调用AddEntityFrameworkStores() 之前,我看不到使用AddRoles&lt;IdentityRole&gt;() 添加的角色支持,并且据我记得在使用AddIdentity() 时需要这样做。另外,我遇​​到了ClaimTypes.NameIdentifier 的一些奇怪的转换问题,所以我怀疑应该改用JwtRegisteredClaimNames.Sub。但我没有任何具体的东西。 ://

标签: angular asp.net-core roles


【解决方案1】:

因此,我设法使用您的配置在一个新项目中重现了该问题。在这样做的同时,我记得我之前遇到了完全相同的问题。

问题是您先调用AddAuthentication(),然后再调用AddIdentity()

解决方案

ConfigureServices() 中,您必须先调用AddIdentity(),然后使用您的自定义身份验证选项调用AddAuthentication()

原因

在后台发生的事情是 AddIdentity() 扩展方法正在调用一堆其他扩展方法来添加 Identity 认为必要的服务,以及它认为必要的配置。其中一部分是使用自己的身份验证选项调用AddAuthentication()

因此,如果您在调用 AddAuthentication() 之后调用它,它只会覆盖您的身份验证选项。这会导致可怕的重定向行为(顺便说一句,它会执行正确的 302 重定向,我检查了它)。


如果这能解决这个问题,请告诉我。如果您在使用基于角色的授权时遇到其他问题,也请告诉我,因为我怀疑您会遇到。 (编辑:我也测试了角色授权,实际上它对我有用。)

【讨论】:

  • 感谢您的回答,但我已经通过将AddIdentity 更改为AddDefaultIdentity 解决了问题。
  • Oki,但如果您想使用自己的身份验证而不是身份验证,则仍应将AddAuthentication 放在Add(Defaullt)Identity(Core) 之后,无论您使用哪种令人困惑的身份扩展方法。 :) AddDefaultIdentity 还包含对 AddAuthentication 的调用,带有自己的身份验证设置(加上 cookie,加上 UI),它恰好不会导致您遇到的问题。但我想没有什么能保证他们不会以将来会导致问题的方式更改此扩展方法。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-11-26
  • 1970-01-01
  • 2021-03-19
  • 2017-01-27
  • 2020-04-29
  • 2019-08-29
  • 1970-01-01
相关资源
最近更新 更多