401 Unauthorized:WWW-Authenticate:Bearer

问题描述 投票:-2回答:2

我已经看到了这个问题的类似线索,但我没有运气解决它。 LogIn工作成功但当我尝试获取用户登录的数据时,我收到了这个错误401未经授权同样的错误也显示在Postman中

我的startup.cs

 public class Startup
    {
        private string _connectionString=null;
        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)
        {
            //Inject AppSettings
            services.Configure<ApplicationSettings>(Configuration.GetSection("ApplicationSettings"));
            _connectionString = Configuration["secretConnectionstring"];

            //without this it will define for example id to Id 
            services.AddMvc()
                .SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
                .AddJsonOptions(options => {
                    var resolver = options.SerializerSettings.ContractResolver;
                    if (resolver != null)
                        (resolver as DefaultContractResolver).NamingStrategy = null;
                });

            services.AddEntityFrameworkNpgsql()
                .AddDbContext<ApiContext>(
                opt => opt.UseNpgsql(_connectionString));

            services.AddEntityFrameworkNpgsql()
                .AddDbContext<AuthentificationContext>(
                options => options.UseNpgsql(_connectionString));
            services.AddDefaultIdentity<ApplicationUser>()
                .AddEntityFrameworkStores<AuthentificationContext>();

            services.Configure<IdentityOptions>(options => {
                options.Password.RequireDigit = false;
                options.Password.RequireNonAlphanumeric = false;
                options.Password.RequireLowercase = false;
                options.Password.RequireUppercase = false;
                options.Password.RequiredLength = 4;
                });

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

            // Jwt Authentification
           var key = Encoding.UTF8.GetBytes(Configuration["ApplicationSettings:JWT_Secret"].ToString());

            services.AddAuthentication(x =>
            {
                x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
                x.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
            }).AddJwtBearer(x=> {
                x.RequireHttpsMetadata = false;
                x.SaveToken = false;
                x.TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters
                {
                    ValidateIssuerSigningKey = true,
                    IssuerSigningKey = new SymmetricSecurityKey(key),
                    ValidateIssuer = false,
                    ValidateAudience = false,
                    ClockSkew = TimeSpan.Zero
                };
            });

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

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env, dataSeed seed)
        {
            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();

            // global policy - assign here or on each controller
            app.UseCors("CorsPolicy");


            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");
                }
            });

            app.UseAuthentication();



        }
    }
}

用户配置文件控制器

{
    [Route("api/[controller]")]
    [ApiController]
    public class UserProfileController : ControllerBase
    {
        private UserManager<ApplicationUser> _userManager;
        public UserProfileController(UserManager<ApplicationUser> userManager)
        {
            _userManager = userManager;
        }

        [HttpGet]
        [Authorize]
        //GET : /api/UserProfile
        public async Task<Object> GetUserProfile()
        {
            string userId = User.Claims.First(c => c.Type == "UserID").Value;
            var user = await _userManager.FindByIdAsync(userId);
            return new
            {
                user.fullName,
                user.Email,
                user.UserName
            };
        }
    }
}

UserServices

 headers = {
    headers: new HttpHeaders({
      'Content-Type': 'application/json',
      'Accept': 'application/json'
    })
  }
  readonly BaseUrl = 'http://localhost:53847/api';

  constructor(private fb: FormBuilder, private http: HttpClient) { }

  formModel = this.fb.group({
    UserName: ['', Validators.required],
    Email: ['', Validators.email],
    fullName: ['', Validators.required],
    Passwords: this.fb.group({
      Password: ['',[Validators.required, Validators.minLength(4)]],
      ConfirmPassword: ['', Validators.required],
    }, { validator : this.comparePasswords})


  });
  comparePasswords(fb: FormGroup) {

    let confirmPswdCtrl = fb.get('ConfirmPassword');
    //passowrdMismatch
    //confirmPswdCtrl.errors={passowrdMismatch:true}
    if (confirmPswdCtrl.errors == null || 'passowrdMismatch' in confirmPswdCtrl.errors) {
      if (fb.get('Password').value != confirmPswdCtrl.value)
        confirmPswdCtrl.setErrors({ passowrdMismatch: true });
      else
        confirmPswdCtrl.setErrors(null);

    }

  }

  register() {
    var body = {
      UserName: this.formModel.value.UserName,
      Email: this.formModel.value.Email,
      fullName: this.formModel.value.fullName,
      Password: this.formModel.value.Passwords.Password,

    };
    return this.http.post(this.BaseUrl + '/ApplicationUser/Register', body, this.headers);
  }

  login(formData) {
    return this.http.post(this.BaseUrl + '/ApplicationUser/Login', formData, this.headers);

  }
  getUserProfile() {
    var tokenHeader = new HttpHeaders({ 'Authorization': 'Bearer' + localStorage.getItem('token'), 'Content-Type': 'application/json' });
    return this.http.get(this.BaseUrl + '/UserProfile', { headers: tokenHeader });
  }
}

应用程序UserController的Post方法

  [HttpPost]
        [Route("Login")]
        //POST : /api/ApplicationUser/Login
        public async Task<IActionResult> Login(LoginModel model)
        {
            var user = await _userManager.FindByNameAsync(model.UserName);
            if (user != null && await _userManager.CheckPasswordAsync(user, model.Password))
            {
                var tokenDescriptor = new SecurityTokenDescriptor
                {
                    Subject = new ClaimsIdentity(new Claim[]
                    {
                        new Claim("UserID",user.Id.ToString())
                    }),
                    Expires = DateTime.UtcNow.AddDays(1),
                    SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_appSettings.JWT_Secret)), SecurityAlgorithms.HmacSha256Signature)
                };
                var tokenHandler = new JwtSecurityTokenHandler();
                var securityToken = tokenHandler.CreateToken(tokenDescriptor);
                var token = tokenHandler.WriteToken(securityToken);
                return Ok(new { token });
            }
            else
                return BadRequest(new { message = "Username or password is incorrect." });
        }
    }

帮助Plz .. Thx

asp.net-mvc jwt angular7 bearer-token
2个回答
1
投票

我看到的一个问题是:

var tokenHeader = new HttpHeaders({ 'Authorization': 'Bearer' + localStorage.getItem('token'), 'Content-Type': 'application/json' });

在指定Bearer标记时,需要在Bearer和标记本身之间留一个空格,以便结果看起来像this

Authorization: <type> <credentials>

在您的情况下,这将转化为:

Authorization: Bearer token

但是,如果你看一下上面的代码,你会发现你实际上会像这样提供它:

Authorization: Bearertoken

哪个不行。因此,将您的代码更改为:

var tokenHeader = new HttpHeaders({ 'Authorization': 'Bearer ' + localStorage.getItem('token'), 'Content-Type': 'application/json' });
// ---------------------------------------------------------^ Notice I've added a space here.

1
投票

在我的情况下,我没有收到错误,一切似乎都有效,但我的API每次都返回401。在此问题上我的头脑很多。我有......

[Authorize]

在我的控制器上发现该网站正在尝试使用cookie身份验证,所以尽管我的JWT工作正常,但缺少cookie身份验证使其失败。我将属性更改为...

[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]

这解决了问题,因为现在控制器忽略了cookie auth并且只集中在jwt上。希望这有助于某人

© www.soinside.com 2019 - 2024. All rights reserved.