Не удалось авторизовать JWT ядра .NET? - PullRequest
0 голосов
/ 20 октября 2019

Я пытаюсь заставить JWT работать здесь, токен успешно получен на моем клиентском конце после входа в систему, но когда я запрашиваю информацию о пользователе по маршруту / info, авторизация не проходит. Любая помощь будет высоко ценится, спасибо заранее.

Я получаю сообщение об ошибке:

Route matched with {action = "GetInfo", controller = "Accounts", page = ""}. Executing controller action with signature System.Threading.Tasks.Task`1[ProjectConker.Controllers.AccountsInfo] GetInfo() on controller ProjectConker.Controllers.AccountsController (ProjectConker).
info: Microsoft.AspNetCore.Authorization.DefaultAuthorizationService[2]
Authorization failed.

Здесь выдается токен.

        [HttpPost("login")]

        public async Task<IActionResult> Post([FromBody]LoginInfo credentials)
        {
            if (credentials == null)
            {
                return BadRequest("Invalid client request");
            }

            var user = await UserManager.FindByNameAsync(credentials.Username);
            await SignInManager.SignInAsync(user, isPersistent: false);

            var result = await SignInManager.PasswordSignInAsync(user, 
            credentials.Password, isPersistent: false, lockoutOnFailure: false);

            if (result.Succeeded)
            {
                var secretKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("**********"));
                var signinCredentials = new SigningCredentials(secretKey, SecurityAlgorithms.HmacSha256);


                var tokeOptions = new JwtSecurityToken(
                    issuer: "http://localhost:5000",
                    audience: "http://localhost:5000",

                    claims: new List<Claim>(){
                        new Claim("username", credentials.Username)
                     },

                    expires: DateTime.Now.AddMinutes(5),
                    signingCredentials: signinCredentials
                );

                var tokenString = new JwtSecurityTokenHandler().WriteToken(tokeOptions);
                return Ok(new { Token = tokenString, UserName = user.UserName });
            }
            else
            {
                return Unauthorized();
            }
        }

Сохранить токенв локальное хранилище

    public Login(loginForm : ILoginForm) : Observable<ILoginForm>
    {
        return this.http.post<ILoginForm>(this.accountsUrl + "/login", loginForm, httpOptions)
        .pipe(map<any, any>((data, index) => {
            localStorage.setItem("auth_token", data.token);
            this.username = data.username;
            this.loggedIn = true;

            console.log(data);
            return data;
        }));
    }

Получает информацию о пользователе

    public GetAccountInfo() : Observable<any>
    {
        httpOptions.headers.set('Authorization', localStorage.getItem('auth_token'));
        return this.http.get(this.accountsUrl + "/info", httpOptions);
    }

возвращает информацию о пользователе, но авторизация здесь не удается

    [HttpGet]
    [Route("info")]
    [Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]

    public async Task<AccountsInfo> GetInfo()
    {

         var usernameClaim = User.Claims.SingleOrDefault(c => c.Type == "username");
         Console.WriteLine(usernameClaim.Value, ConsoleColor.Red);

         var user = await UserManager.FindByNameAsync(usernameClaim.Value);


         return new AccountsInfo{ DisplayName = user.UserName };
     }

Мой запуск .cs

    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.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
                .AddJwtBearer(options =>
                {
                    options.TokenValidationParameters = new TokenValidationParameters
                    {
                        ValidateIssuer = true,
                        ValidateAudience = true,
                        ValidateLifetime = true,
                        ValidateIssuerSigningKey = true,

                        ValidIssuer = "http://localhost:5000",
                        ValidAudience = "http://localhost:5000",
                        IssuerSigningKey = new SymmetricSecurityKey(System.Text.Encoding.UTF8.GetBytes("superSecretKey@345"))
                    };
                });

            //services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);

            // In production, the Angular files will be served from this directory
            services.AddSpaStaticFiles(configuration =>
            {
                configuration.RootPath = "ClientApp/dist";
            });

            services.AddHttpClient();

            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);

            services.AddCors(options => options.AddPolicy("CorsPolicy", 
            builder => 
            {
                builder.AllowAnyMethod().AllowAnyHeader()
                       .WithOrigins("*")
                       .AllowCredentials();
            }));

            services.AddSignalR();

            services.AddEntityFrameworkSqlServer();

            services.AddDbContext<ConkerDbContext>(
    options => options.UseQueryTrackingBehavior(QueryTrackingBehavior.TrackAll));

            services.AddIdentity<IdentityUser, IdentityRole>().AddEntityFrameworkStores<ConkerDbContext>();

            services.AddScoped<SearchEngine>();
            services.AddTransient<RoadmapService>();
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Error");
                // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
                app.UseHsts();
            }

            // app.UseHttpsRedirection();
            app.UseStaticFiles();
            app.UseSpaStaticFiles();

            app.UseAuthentication();

            app.UseSignalR(routes =>
            {
                routes.MapHub<ChatHub>("/api/chat");
            });

            app.UseMvc(routes =>
            {
                routes.MapRoute(
                    name: "default",
                    template: "{controller}/{action=Index}/{id?}");
            });

            app.UseSpa(spa =>
            {
                // To learn more about options for serving an Angular SPA from ASP.NET Core,
                // see https://go.microsoft.com/fwlink/?linkid=864501

                spa.Options.SourcePath = "ClientApp";

                if (env.IsDevelopment())
                {
                    spa.UseAngularCliServer(npmScript: "start");
                }
            });


        }

1 Ответ

1 голос
/ 20 октября 2019

Способ добавления заголовка авторизации по умолчанию в HTTP-запросе для аутентификации основного токена ASP.NET заключается в добавлении Носителя перед токеном. Таким образом, код должен быть таким:

httpOptions.headers.set('Authorization', "Bearer " + localStorage.getItem('auth_token'));

. Вы можете переопределить поведение по умолчанию, чтобы избавиться от необходимости Bearer . Пожалуйста, прочитайте следующий пост, чтобы понять причину использования носителя перед токеном. https://www.quora.com/Why-is-Bearer-required-before-the-token-in-Authorization-header-in-a-HTTP-request

Также попробуйте это,

            var tokenDescriptor = new SecurityTokenDescriptor
            {
                Subject = new ClaimsIdentity(claims),
                Expires = DateTime.Now.AddDays(1),
                SigningCredentials = creds,
                IssuedAt = DateTime.Now,
                NotBefore = DateTime.Now
            };

            var tokenHandler = new JwtSecurityTokenHandler();

            var token = tokenHandler.CreateToken(tokenDescriptor);

Что я имею в виду, вместо создания нового JWTSecurityToken, создайте SecuritTokenDescriptor, вместо использования функции WriteToken, используйте CreateToken. Я использовал JWT таким образом, и это сработало.

...