【问题标题】:Use JWT token in multiple projects在多个项目中使用 JWT 令牌
【发布时间】:2021-08-19 00:45:21
【问题描述】:

我有 3 个项目 JWT.IDP、JWT.API、JWT.MVC。

  1. JWT.IDP - API 项目验证用户并颁发 JWT 令牌。
  2. JWT.API - 我的业务逻辑、CURD 等的 API 项目
  3. JWT.MVC - 用于 UI 的 MVC 应用程序。

我的意图是使用在 JWT.IDP 中生成的这个令牌并从 JWT.MVC 调用 JWT.API 函数

IDP 令牌工作正常,我可以生成令牌并且我的 JWT.MVC 登录控制器能够接收它。但是当我尝试使用此令牌访问 JWT.API 时,它会给出 500 错误(请参阅下面代码中的最后一个函数 (GetWeatherData))。

谁能帮忙,我不是高级用户,下面写的代码取自几个示例。所以我不确定它是否真的是正确的代码。

namespace JWT.MVC.Controllers
{
    public class LoginController : Controller
    {

        public IActionResult DoLogin()
        {

            return View();
        }


        [HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<IActionResult> DoLogin([Bind("EmailOrName,Password")] LoginRequestModel loginRequestModel)
        {
            var apiName = $"https://localhost:44318/api/User/login";

            HttpClient httpClient = new HttpClient();
            HttpResponseMessage response = await httpClient.PostAsJsonAsync(apiName, loginRequestModel);
            var jasonString = await response.Content.ReadAsStreamAsync();

            var data = await JsonSerializer.DeserializeAsync<IEnumerable<AccessibleDb>>
                    (jasonString, new JsonSerializerOptions() { PropertyNameCaseInsensitive = true });

            foreach (var item in data)
            {
                item.UserName = loginRequestModel.EmailOrName;
            }

            return View("SelectDatabase" , data);
        }

      
        public async Task<IActionResult> PostLogin(string db, string user)
        {
            TokenRequestModel tokenRequestModel = new TokenRequestModel() { Database = db, UserName = user };

            var apiName = $"https://localhost:44318/api/User/tokenonly";

            HttpClient httpClient = new HttpClient();
            HttpResponseMessage response = await httpClient.PostAsJsonAsync(apiName, tokenRequestModel);
            var jasonString = await response.Content.ReadAsStreamAsync();

            var data = await JsonSerializer.DeserializeAsync<AuthenticationModel>
                    (jasonString, new JsonSerializerOptions() { PropertyNameCaseInsensitive = true });

            var stream = data.Token;
            var handler = new JwtSecurityTokenHandler();
            var jsonToken = handler.ReadToken(stream);
            var tokenS = jsonToken as JwtSecurityToken;
            var selectedDb = tokenS.Claims.First(claim => claim.Type == "Database").Value;

            ViewBag.SelectedDb = selectedDb;

            return View(data);
        }

        public async Task<IActionResult> GetWeatherData(string token)
        {

            var apiName = $"https://localhost:44338/weatherforecast";

            HttpClient httpClient = new HttpClient();
            httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
            HttpResponseMessage response = await httpClient.GetAsync(apiName);
            if (!response.IsSuccessStatusCode)
            {
                ViewBag.Error = response.StatusCode;
                return View("Weatherdata");
            }
            var jasonString = await response.Content.ReadAsStreamAsync();
            var data = await JsonSerializer.DeserializeAsync<WeatherForecast>
                    (jasonString, new JsonSerializerOptions() { PropertyNameCaseInsensitive = true });

        
            return View("Weatherdata" , data);
        }
    }
}

JWT.MVC 的启动类如下


 public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllersWithViews();
            services.AddAuthentication("Bearer")
             .AddJwtBearer("Bearer", options =>
             {

                 options.Audience = "SecureApiUser";
                 options.Authority = "https://localhost:44318";
                 options.TokenValidationParameters = new TokenValidationParameters
                 {
                     ValidateAudience = false
                 };
             });

          
        }


JWT.API 的启动类如下

  public void ConfigureServices(IServiceCollection services)
        {

            services.AddControllers();
            //Copy from IS4
            services.AddAuthentication("Bearer")
              .AddJwtBearer("Bearer", options =>
              {
                  
                  options.Audience = "SecureApiUser";
                  options.Authority = "https://localhost:44318";
                  options.TokenValidationParameters = new TokenValidationParameters
                  {
                      ValidateAudience = false
                  };
              });

          
            //End
            services.AddSwaggerGen(c =>
            {
                c.SwaggerDoc("v1", new OpenApiInfo { Title = "JWT.API", Version = "v1" });
            });
        }

JWT.IDP 的启动类如下

  public void ConfigureServices(IServiceCollection services)
        {

            services.AddControllers();

            //Configuration from AppSettings
            services.Configure<JwtSettings>(Configuration.GetSection("JWT"));
            //User Manager Service
            services.AddIdentity<ApplicationUser, IdentityRole>().AddEntityFrameworkStores<IdentityDbContext>();
            services.AddScoped<IUserService, UserService>();
            //Adding DB Context with MSSQL
            services.AddDbContext<IdentityDbContext>(options =>
                options.UseSqlServer(
                    Configuration.GetConnectionString("IdentityDbConnectionString"),
                    b => b.MigrationsAssembly(typeof(IdentityDbContext).Assembly.FullName)));

            //Adding Athentication - JWT
            services.AddAuthentication(options =>
            {
                options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
            })
                .AddJwtBearer(o =>
                {
                    o.RequireHttpsMetadata = false;
                    o.SaveToken = false;
                    o.TokenValidationParameters = new TokenValidationParameters
                    {
                        ValidateIssuerSigningKey = true,
                        ValidateIssuer = true,
                        ValidateAudience = true,
                        ValidateLifetime = true,
                        ClockSkew = TimeSpan.FromMinutes(Convert.ToInt32(Configuration["JWT:DurationInMinutes"])),
                        ValidIssuer = Configuration["JWT:Issuer"],
                        ValidAudience = Configuration["JWT:Audience"],
                        IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["JWT:Key"]))
                    };
                });

           

            services.AddSwaggerGen(c =>
            {
                c.SwaggerDoc("v1", new OpenApiInfo { Title = "JWT.IDP", Version = "v1" });
            });
        }

JWT 设置如下

 "JWT": {
    "key": "C1CF4B7DC4C4175B6618DE4F55CA4",
    "Issuer": "http://localhost:44318",
    "Audience": "SecureApiUser",
    "DurationInMinutes": 60
  },

【问题讨论】:

  • 这看起来与您在stackoverflow.com/questions/67662711/… 的问题相同。在任何情况下,如果您收到 500 错误,您至少需要从产生它的服务器发布错误消息/输出。
  • 不,肖恩,问题不同。在那里,我想知道如何将 JWT 传递给我得到答案的 API,在将其标记为答案之后,只有我的下一个挑战出现了。因为在那里帮助我的人似乎知识渊博,我想在那里发布问题,但他没有回应这就是为什么它在这里被创建为一个新帖子。对了,你知道解决办法吗,能帮忙吗?
  • 正如我所说,您确实需要说明导致 500 错误代码的实际错误是什么。查看服务器的输出或尝试从响应中提取更多信息。仅 500 个代码是不够的。
  • Shaun,我在过去 12 小时内尝试查看内部错误的原因。除了内部错误,我什么也得不到。错误出现在 LoginController 中,GetWheatherData 代码 HttpResponseMessage response = await httpClient.GetAsync(apiName);这里响应对象的 IsSuccessStatusCode 为 false,如果您在调试模式下评估响应对象,它会显示 InternalServerError。你能帮忙吗
  • 你需要调试服务端代码——即GetWeatherData中的API实现。在这种情况下,LoginController 是客户端。

标签: asp.net-core asp.net-web-api jwt


【解决方案1】:

令人惊讶的是,没有人能够识别出错误。我做了以下更改,现在效果很好。

在 MVC 和 API 项目中,ConfigureServices 如下所示。没有对任何其他代码进行其他更改。


         public void ConfigureServices(IServiceCollection services)
        {

            services.AddControllers();

            var authenticationProviderKey = "IdentityApiKey";
            var signingKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes("C1CF4B7DC4C4175B6618DE4F55CA4"));
            var tokenValidationParameters = new TokenValidationParameters
            {
                ValidateIssuerSigningKey = true,
                IssuerSigningKey = signingKey,
                ValidateIssuer = true,
                ValidIssuer = "http://localhost:44318",
                ValidateAudience = true,
                ValidAudience = "SecureApiUser",
                ValidateLifetime = true,
                ClockSkew = TimeSpan.Zero,
                RequireExpirationTime = true,
            };

            services.AddAuthentication(o =>
            {
                o.DefaultAuthenticateScheme = authenticationProviderKey;
            })
            .AddJwtBearer(authenticationProviderKey, x =>
            {
                x.RequireHttpsMetadata = false;
                x.TokenValidationParameters = tokenValidationParameters;
            });

            //services.AddAuthentication(options =>
            //{
            //    options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
            //    options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;

            //}).AddJwtBearer(options =>
            //{
            //    options.Authority = "https://localhost:44318"; ;
            //    options.RequireHttpsMetadata = false;
            //    options.Audience = "SecureApiUser";
            //});

            //End

            services.AddSwaggerGen(c =>
            {
                c.SwaggerDoc("v1", new OpenApiInfo { Title = "JWT.API2", Version = "v1" });
            });
        }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-11-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-11
    • 2021-11-21
    • 1970-01-01
    相关资源
    最近更新 更多