代码之家  ›  专栏  ›  技术社区  ›  saviour123

即使包含不记名令牌,Netcore API也返回401

  •  1
  • saviour123  · 技术社区  · 6 年前

    我想保护我的API端点,以便它只能通过身份验证进行访问,最后我得到了这个错误。我使用register方法注册用户并获取令牌。然后,我使用请求头中的长令牌访问受保护的区域。但我一直得到401授权错误。到底怎么回事!

    http Get http://localhost:5000/Account/Protected 'authorization:Bearer       eyJhb....fx0IM'
    HTTP/1.1 401 Unauthorized
    Content-Length: 0
    Date: Fri, 27 Jul 2018 12:36:46 GMT
    Server: Kestrel
    WWW-Authenticate: Bearer error="invalid_token", error_description="The token as no expiration"
    

    我有这个控制器配置用于 Account Controller . 注册方法很好地工作并且注册了这个人,现在如果我想用受保护的控制器添加一个测试API。我得到401错误。

    namespace Lemon.Auth.Controllers
    {
    [Route("[controller]/[action]")]
    public class AccountController : ControllerBase
    {
    
        private readonly SignInManager<IdentityUser> _signInManager;
        private readonly UserManager<IdentityUser> _userManager;
        private readonly IConfiguration _configuration;
    
        public AccountController(
            UserManager<IdentityUser> userManager,
            SignInManager<IdentityUser> signInManager,
            IConfiguration configuration
        )
        {
            _userManager = userManager;
            _signInManager = signInManager;
            _configuration = configuration;
        }
    
        [Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)
        [HttpGet]
        public async Task<object> Protected()
        {
            return "Protected area";
        }
    
        // Handlers
        [HttpPost]
        public async Task<object> Login([FromBody] LoginDto model)
        {
    
            var result = await _signInManager.PasswordSignInAsync(model.Email, model.Password, false, false);
    
            if(result.Succeeded)
            {
                var appUser = _userManager.Users.SingleOrDefault(r => r.Email == model.Email);
                return await GenerateJwtToken(model.Email, appUser);
            }
    
            throw new ApplicationException("Invalid Login Attempt");
        }
    
        // Handler :Register:
        public async Task<object> Register([FromBody] RegisterDto model)
        {
            var user = new IdentityUser
            {
                UserName = model.Email,
                Email = model.Email
            };
    
            // debuggi
            try
            {
                var result = await _userManager.CreateAsync(user, model.Password);
                if (result.Succeeded)
                {
                    await _signInManager.SignInAsync(user, false);
                    return await GenerateJwtToken(model.Email, user);
                }
            }
            catch (System.Exception ex)
            {
                Console.WriteLine(ex.ToString());
            }
    
            throw new ApplicationException("Unknown Error");
        }
    
        private async Task<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["JwtExpiresDays"]));
            Console.WriteLine("hello");
    
            var token = new JwtSecurityToken(
                _configuration["JwtIssuer"],
                _configuration["JwtIssuer"],
                claims,
                signingCredentials: creds
            );
    
            return new JwtSecurityTokenHandler().WriteToken(token);
        }
    }
    }
    

    这是我的初创公司.cs

            public void ConfigureServices(IServiceCollection services)
        {
            // Db and context
            services.AddEntityFrameworkNpgsql().AddDbContext<ApplicationDbContext>(options =>
                {
                    options.UseNpgsql(Configuration.GetConnectionString("DefaultConnection"));
                }
            );
    
            // add Identity
            services.AddIdentity<IdentityUser, IdentityRole>()
                .AddEntityFrameworkStores<ApplicationDbContext>()
                .AddDefaultTokenProviders();
    
            // add jwt
            JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear(); // clear default behaviour
            services.AddAuthentication(options => 
            {
                options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
                options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
            })
            .AddJwtBearer(cfg => 
            {
                cfg.RequireHttpsMetadata = false;
                cfg.SaveToken = true;
                cfg.TokenValidationParameters = new TokenValidationParameters
                    {
                        ValidIssuer = Configuration["JwtIssuer"],
                        ValidAudience = Configuration["JwtIssuer"],
                        IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["JwtKey"])),
                        ClockSkew = TimeSpan.Zero // remove delay of token when expire
    };
                });
    
            // add mvc
            services.AddMvc().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, ApplicationDbContext dbContext)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseHsts();
            }
    
            // app.UseHttpsRedirection();
            app.UseMvc();
            app.UseAuthentication();
    
            // ensure tables are created
            dbContext.Database.EnsureCreated();
        }
    

    我要做的就是保护API。我参考了这个教程 https://medium.com/@ozgurgul/asp-net-core-2-0-webapi-jwt-authentication-with-identity-mysql-3698eeba6ff8

    2 回复  |  直到 6 年前
        1
  •  3
  •   alsami    6 年前

    private async Task<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["JwtExpiresDays"]));
        Console.WriteLine("hello");
    
        var token = new JwtSecurityToken(
            _configuration["JwtIssuer"],
            _configuration["JwtIssuer"],
            claims,
            expires: DatimeTime.UtcNow.AddHours(1), // or smth else
            signingCredentials: creds
        );
    

    services.AddIdentity<,> here here

    public void Configure(IApplicationBuilder app, IHostingEnvironment env, ApplicationDbContext dbContext)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseHsts();
        }
    
        // app.UseHttpsRedirection();
        app.UseAuthentication();
        app.UseMvc();
    
        // ensure tables are created
        dbContext.Database.EnsureCreated();
    }
    
        2
  •  1
  •   johnny 5    6 年前

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

    link