【问题标题】:Cannot access Authorized content in .NET Core using JWT authentication无法使用 JWT 身份验证访问 .NET Core 中的授权内容
【发布时间】:2019-12-21 09:22:05
【问题描述】:

我开发了一个示例应用,我在其中使用 JWT 身份验证来访问私有内容。

在 Postman 中获取令牌后,我还可以通过 Postman 将其传递给私有控制器操作,并且一切正常。

但是当我尝试使用SignInManager 访问时,它不起作用。 User.Identity.NameUser.Identity.IsAuthenticated 始终为空

这是我的启动代码

public class Startup
{
    private AppModule appModule;
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        appModule = new AppModule();
        AppModule.Configuration = Configuration; //setting up of static variable

        services.Configure<CookiePolicyOptions>(options =>
        {
            // This lambda determines whether user consent for non-essential cookies is needed for a given request.
            options.CheckConsentNeeded = context => true;
            options.MinimumSameSitePolicy = SameSiteMode.None;
        });

        string connectionSring = null;
        if (true) //(env.IsDevelopment())
            connectionSring = appModule.GetConnectionString(EuConstants.LOCAL_CONNECTION_NAME);
        else
            connectionSring = appModule.GetConnectionString(EuConstants.DEFAULT_CONNECTION_NAME);



        services.AddDbContext<ApplicationDbContext>(options =>
        {
            options.UseSqlServer(connectionSring);
        });



        /* tell the framework to use our cusom user and role classes */
        services.AddIdentity<Gn_User, Gn_Role>(options =>

        {
            options.Stores.MaxLengthForKeys = 128;
        })
            .AddEntityFrameworkStores<ApplicationDbContext>()
            .AddDefaultTokenProviders();

        services.ConfigureApplicationCookie(o => {
            o.LoginPath = "/portal/login";
        });

        services.AddAuthorization();

        services.AddAuthentication(option => {
            option.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
            option.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
            option.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
        }).AddJwtBearer(options => {
            options.SaveToken = true;
            options.RequireHttpsMetadata = true;
            options.TokenValidationParameters = new TokenValidationParameters()
            {
                ValidateIssuer = true,
                ValidateAudience = true,
                ValidAudience = Configuration["Jwt:Site"],
                ValidIssuer = Configuration["Jwt:Site"],
                IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["Jwt:SigningKey"]))
            };
        });


        services.AddScoped<AppModule>(sp => appModule
        );

        services.AddMvc(
            options =>
            {
                // make sure that all attributes by default required authentication
               // options.Filters.Add(new AuthorizeFilter(new AuthorizationPolicyBuilder().RequireAuthenticatedUser().Build()));
            }
            ).SetCompatibilityVersion(CompatibilityVersion.Version_2_1);

    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IHostingEnvironment env, IServiceProvider provider)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseExceptionHandler("/Home/Error");
            app.UseHsts();
        }
        app.UseAuthentication();
        app.UseHttpsRedirection();
        app.UseStaticFiles();
        app.UseCookiePolicy();



        // tell the application to use the authentication
        app.UseMvc(routes =>
        {
            routes.MapRoute(
                name: "default",
                template: "{controller=Portal}/{action=Index}/{id?}");
        });
    }
}

这是生成令牌的身份验证方法

public async Task<ActionResult> Login([FromBody] Gn_User model)
    {
        string password = "yaser@1234";
        var user = await _userManager.FindByNameAsync(model.UserName);
        if (user != null && await _userManager.CheckPasswordAsync(user, password))
        {
            var claim = new[] {
                new Claim(JwtRegisteredClaimNames.Sub, user.UserName)
            };
            var signinKey = new SymmetricSecurityKey(
              Encoding.UTF8.GetBytes(AppModule.Configuration["Jwt:SigningKey"]));

            int expiryInMinutes = Convert.ToInt32(AppModule.Configuration["Jwt:ExpiryInMinutes"]);

            var token = new JwtSecurityToken(
              issuer: AppModule.Configuration["Jwt:Site"],
              audience: AppModule.Configuration["Jwt:Site"],
              expires: DateTime.UtcNow.AddMinutes(expiryInMinutes),
              signingCredentials: new SigningCredentials(signinKey, SecurityAlgorithms.HmacSha256)
            );

            return Ok(
              new
              {
                  token = new JwtSecurityTokenHandler().WriteToken(token),
                  expiration = token.ValidTo
              });
        }
        return Unauthorized();
    }

【问题讨论】:

  • SignInManager to access 是什么意思?你是如何在没有邮递员的情况下请求安全内容的?

标签: asp.net asp.net-mvc asp.net-core postman


【解决方案1】:

您忘记将声明添加到您的 JWT。

public async Task<ActionResult> Login([FromBody] Gn_User model)
{
    string password = "yaser@1234";
    var user = await _userManager.FindByNameAsync(model.UserName);
    if (user != null && await _userManager.CheckPasswordAsync(user, password))
    {
        var claim = new[] {
            new Claim(JwtRegisteredClaimNames.Sub, user.UserName)
        };
        var signinKey = new SymmetricSecurityKey(
          Encoding.UTF8.GetBytes(AppModule.Configuration["Jwt:SigningKey"]));

        int expiryInMinutes = Convert.ToInt32(AppModule.Configuration["Jwt:ExpiryInMinutes"]);

        var token = new JwtSecurityToken(
          issuer: AppModule.Configuration["Jwt:Site"],
          audience: AppModule.Configuration["Jwt:Site"],
          /////////////////////////////////
          claims : claim,// Dont Forget To Add Claims To Your JWT
          /////////////////////////////////
          expires: DateTime.UtcNow.AddMinutes(expiryInMinutes),
          signingCredentials: new SigningCredentials(signinKey, SecurityAlgorithms.HmacSha256)
        );

        return Ok(
          new
          {
              token = new JwtSecurityTokenHandler().WriteToken(token),
              expiration = token.ValidTo
          });
    }
    return Unauthorized();
}

【讨论】:

  • 通过添加缺少的声明仍然无法正常工作,但我不知道登录参数与 startup.cs 中标识的参数是否不匹配。当然,它仍然可以通过从 Postman 调用它并为标头提供身份验证令牌来工作
【解决方案2】:

我通过添加以下代码来注册身份为我工作。

services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)

而不是将参数作为选项传递

services.AddAuthentication(op => {
      op.defaultSchema...... = JwtBearerDefaults.AuthenticationScheme
})

【讨论】:

    猜你喜欢
    • 2018-12-20
    • 2021-12-18
    • 2017-04-15
    • 2023-04-01
    • 2017-07-09
    • 2013-04-17
    • 2021-03-25
    • 2021-07-17
    • 1970-01-01
    相关资源
    最近更新 更多