【问题标题】:UseJwtBearerAuthentication returns 404 instead of 401UseJwtBearerAuthentication 返回 404 而不是 401
【发布时间】:2018-06-16 09:53:09
【问题描述】:

我想使用 JwtAuthentication。我在 Startup.cs 类中做了一些设置。 并将一个控制器设置为 [Authorized],但是当我调用该控制器时响应是 404 而不是 401,为什么? 当我调用控制器为我生成令牌时,它生成成功,但由于某种原因不能在邮递员中使用他,我再次收到错误 404。 你知道为什么吗?

using AutoMapper;
using Test.Core;
using Test.Persistence;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.IdentityModel.Tokens;
using System.Text;

namespace Test
{
    public class Startup
    {

        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)
        {
            services.AddAutoMapper();

            services.AddDbContext<ApplicationDbContext>(options =>
            {
                options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"));
            });

            services.AddIdentity<ApplicationUser, IdentityRole>(config =>
            {
                config.Password.RequireDigit = false;
                config.Password.RequiredLength = 4;
                config.Password.RequireLowercase = false;
                config.Password.RequireNonAlphanumeric = false;
                config.Password.RequireUppercase = false;
            })
                .AddEntityFrameworkStores<ApplicationDbContext>()
                .AddDefaultTokenProviders();

            // ===== Add Jwt Authentication ========
            services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
        .AddJwtBearer(options =>
        {
            options.TokenValidationParameters = new TokenValidationParameters
            {
                ValidateActor = true,
                ValidateAudience = true,
                ValidateLifetime = true,
                ValidateIssuerSigningKey = true,
                ValidIssuer = Configuration["JwtIssuer"],
                ValidAudience = Configuration["JwtAudience"],
                IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["JwtKey"]))
            };
        });

            services.AddMvc();
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            app.UseAuthentication();
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseAuthentication();
            app.UseMvc();
        }
    }
}

生成令牌只是 loing 中包含的私有方法

 [HttpPost]
    [ActionName("login")]
    public async Task<Object> Login([FromBody] LoginResource login)
    {
        var result = await _signInManager.PasswordSignInAsync(login.Email, login.Password, false, false);
        if (result.Succeeded)
        {
            var appUser = _userManager.Users.SingleOrDefault(r => r.Email == login.Email);
            return  GenerateJwtToken(login.Email, appUser);
        }
        throw new ApplicationException("INVALID_LOGIN_ATTEMPT");
    }

    private  object GenerateJwtToken(string email, IdentityUser user)
    {
        var claims = new List<Claim>
        {
            new Claim(JwtRegisteredClaimNames.Sub, email),
            new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
            new Claim(ClaimTypes.NameIdentifier, user.Id)
        };

        var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration["JwtKey"]));
        var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
        var expires = DateTime.Now.AddDays(Convert.ToDouble(_configuration["JwtExpireDays"]));

        var token = new JwtSecurityToken(
            _configuration["JwtIssuer"],
            _configuration["JwtIssuer"],
            claims,
            expires: expires,
            signingCredentials: creds
        );

        return new JwtSecurityTokenHandler().WriteToken(token);
    }

【问题讨论】:

  • “当我调用控制器响应是 404 而不是 401”时,你是否被重定向到任何其他 URL?你是如何通过浏览器调用控制器的?
  • 对不起,它只是一个 API,不应该重定向到任何地方。
  • 如果通过浏览器浏览到控制器,会发生什么?
  • 这很可能是您从邮递员那里调用它时发生的事情。您需要在某个端点生成令牌并将其传递到 Authentication 标头中,其值为 Bearer TOKEN

标签: c# asp.net jwt asp.net-core-2.0


【解决方案1】:

使用services.AddIdentityCore&lt;ApplicationUser&gt; 而不是services.AddIdentity&lt;ApplicationUser, IdentityRole&gt; 应该可以解决这个问题。请注意,在 AddIdentityCore 中包含角色并没有重载:

默认不添加角色服务,但可以使用 AddRoles() 添加。

(^ 来自documentation for AddIdentityCore)

这可以这样实现:

services.AddIdentityCore<ApplicationUser>(config =>
            {
                config.Password.RequireDigit = false;
                config.Password.RequiredLength = 4;
                config.Password.RequireLowercase = false;
                config.Password.RequireNonAlphanumeric = false;
                config.Password.RequireUppercase = false;
            })
                .AddEntityFrameworkStores<ApplicationDbContext>()
                .AddDefaultTokenProviders()
                .AddRoles<IdentityRole>();

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-06-09
    • 2016-04-27
    • 1970-01-01
    • 2022-01-17
    • 1970-01-01
    • 2018-06-28
    • 2011-05-04
    • 2017-10-26
    相关资源
    最近更新 更多