使用 JWT 令牌授权仍然返回未授权

Authorize using JWT token still returning unauthorized

我的startup.cs(asp.net核心5.0)

 public void ConfigureServices(IServiceCollection services)
    {
        services.AddControllersWithViews();
        services.AddAuthentication (options =>
        {
            options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
            options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
            options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
        })
            .AddJwtBearer(options =>
            {
                options.SaveToken = true;
                options.RequireHttpsMetadata = false;
                options.TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters()
                {
                    ValidateIssuer = true,
                    ValidateAudience = true,
                    ValidAudience = "https://www.yogihosting.com",
                    ValidIssuer = "https://www.yogihosting.com",
                    ClockSkew = TimeSpan.Zero,// It forces tokens to expire exactly at token expiration time instead of 5 minutes later
                    IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("MynameisJamesBond007"))
                };
            });
    }

我正在尝试调用 http://localhost:31254/Reservation 我想从 CallAPIController.cs

调用的航班预订列表列表 returns

ReservationController.cs

  [Authorize]
    public IEnumerable<Reservation> Index()
    {
        return CreateDummyReservations();
    }

    [HttpGet]
    public IEnumerable<Reservation> Get() => CreateDummyReservations();

    public List<Reservation> CreateDummyReservations()
    {
        List<Reservation> rList = new List<Reservation> {
        new Reservation { Id=1, Name = "Ankit", StartLocation = "New York", EndLocation="Beijing" },
        new Reservation { Id=2, Name = "Bobby", StartLocation = "New Jersey", EndLocation="Boston" },
        new Reservation { Id=3, Name = "Jacky", StartLocation = "London", EndLocation="Paris" }
        };
        return rList;
    }

CallAPIController.cs

  //entry point of the controller
  public async Task<IActionResult> Index(string message)
    {
        ViewBag.Message = message;
        var accessToken = GenerateJSONWebToken(); //generating the token
        SetJWTCookie(accessToken);  //setting the cookie

        List<Reservation>  list = await FlightReservation();

        return RedirectToAction("Home");
    }

     private string GenerateJSONWebToken()
    {
        var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("MynameisJamesBond007"));
        var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256);

        var token = new JwtSecurityToken(
            issuer: "https://www.yogihosting.com",
            audience: "https://www.yogihosting.com",
            expires: DateTime.Now.AddHours(3),
            signingCredentials: credentials
            );

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

    private void SetJWTCookie(string token)
    {
        var cookieOptions = new CookieOptions
        {
            HttpOnly = true,
            Expires = DateTime.UtcNow.AddHours(3),
        };
        Response.Cookies.Append("jwtCookie", token, cookieOptions);
    }

    public  async Task<List<Reservation>> FlightReservation()
    {
        var jwt = Request.Cookies["jwtCookie"];

        List<Reservation> reservationList = new List<Reservation>();

        using (var httpClient = new HttpClient())
        {
            httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", jwt);
      //calling the reservation controller asynchronously but returning 
            unauthorised.
            using (var response =  await httpClient.GetAsync("http://localhost:31254/Reservation")) // change API URL to yours 
            {
                if (response.StatusCode == System.Net.HttpStatusCode.OK)
                {
                    string apiResponse =   await response.Content.ReadAsStringAsync();
                    reservationList = JsonConvert.DeserializeObject<List<Reservation>>(apiResponse);
                }

                if (response.StatusCode == System.Net.HttpStatusCode.Unauthorized)
                {
                    //return RedirectToAction("Index", new { message = "Please Login again" });
                }
            }
        }

        return reservationList;
    }

不过,当我调用预订控制器时,我收到 401 未经授权的错误。如果我删除授权属性,它就可以工作。关键是它没有识别 JWT 令牌或正确验证它。我错过了什么吗?

您的问题出在这一行:

SetJWTCookie(accessToken); 

List<Reservation>  list = await FlightReservation();

当你设置cookie时,必须在浏览器中收到响应才能在浏览器中设置cookie,以便在后续请求中发送,但响应尚未发送到浏览器,你调用此方法

await FlightReservation();

该方法请求的cookie还没有在浏览器中设置,也没有发送给本次请求,所以这里收到的token为空

 var jwt = Request.Cookies["jwtCookie"];   //cookie is null

并且未授权的错误returns,但是如果本次请求结束,后续的请求不会有问题,因为浏览器中设置了cookie。因此,对于您的代码,它将始终 return 在第一个请求中未授权。

但是如果所有请求都失败了,看看你有没有设置UseAuthentication中间件

app.UseRouting();

app.UseAuthentication();  //here

app.UseAuthorization();

您在 SetJWTCookie(string token) 方法中设置了 cookie:

Response.Cookies.Append("jwtCookie", token, cookieOptions)

并且您尝试在 FlightReservation() 方法中获取 cookie:

var jwt = Request.Cookies["jwtCookie"];

您的请求不包含 jwtCookie。所以你无法获得你的智威汤逊的价值 代币

试试下面的方法:

[HttpPost]
        public async Task<IActionResult> Authenticate(UserModel someuser)
        {
            
            var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("MynameisJamesBond007"));
            var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256);

            var token = new JwtSecurityToken(
             issuer: "https://www.yogihosting.com",
             audience: "https://www.yogihosting.com",
             expires: DateTime.Now.AddHours(3),
             signingCredentials: credentials
             );
            

            string jwtToken = new JwtSecurityTokenHandler().WriteToken(token);


            using (var httpClient = new HttpClient())
            {
                httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", jwtToken);

                var response = await httpClient.GetAsync(url); // change API URL to yours 

            }

            return Content(jwtToken);
        }

结果: