- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
UPDATE: If I change return new OkObjectResult(token); to return Ok("test"); then it's not empty.
要使用 API,您必须调用 AuthenticateAsync 来创建并返回一个 token 。
[AllowAnonymous]
[HttpPost]
public async Task<IActionResult> AuthenticateAsync([FromBody]string apiKey)
{
return await StopwatchLogger.LogExecutionTime($"Authenticate user: {apiKey}", async () =>
{
EnsureValidLoginRequest(apiKey);
//Validate user credentials
AuthenticationInfo authenticationInfo = await _authenticationService.AuthenticateUser(apiKey);
if (!authenticationInfo.IsAuthenticated)
{
throw new RestApiExceptionNoLogging(ErrorCode.AuthenticationInvalidApiKey, "");
}
//Login current user and get the created token with claims identifying current user
Token token = _authenticationService.LoginApiUser(HttpContext, authenticationInfo.SystemUser);
return new OkObjectResult(token);
});
}
token 已正确创建,据我所知,一切都和以前一样,除了响应正文变为空。不会抛出任何错误。
编辑:添加startup.cs
public class Startup
{
private const string LogText = "An error occurred during startup.";
private readonly List<Exception> _exceptions = new List<Exception>();
private IWebHostEnvironment _HostingEnvironment;
public IConfiguration Configuration { get; }
public Startup(IConfiguration configuration, IWebHostEnvironment env)
{
Configuration = configuration;
_HostingEnvironment = env;
}
/// <summary>
/// This method gets called by the runtime. Use this method to add services to the container.
/// </summary>
/// <param name="services"></param>
/// <remarks>Is called before Configure</remarks>
public void ConfigureServices(IServiceCollection services)
{
try
{
if (_exceptions.Any())
{
return;
}
// Add framework services. See configuration class (implementing IConfigureOptions<MvcOptions>) for specific implementation details.
services.AddApiVersioning(o =>
{
o.ReportApiVersions = true;
o.AssumeDefaultVersionWhenUnspecified = true;
o.DefaultApiVersion = new ApiVersion(1, 0);
});
// Adds services required for using options.
services.AddOptions();
services.AddLogging(logging =>
{
logging.AddConsole();
logging.AddDebug();
});
//Add scoped services (New service for every request)
services.AddScoped<IJwtBearerService, JwtBearerService>();
services.AddScoped<IApiAuthService, ApiAuthService>();
services.AddScoped<ILoggingService, LoggingService>();
services.AddScoped<IResponseDatabaseLogger, ResponseDatabaseLogger>();
services.AddScoped<IRequestDatabaseLogger, RequestDatabaseLogger>();
services.AddScoped<IAuthService, AuthService>();
services.AddScoped<IOrderService, OrderService>();
services.AddScoped<IApiOrderService, ApiOrderService>();
services.AddScoped<IHaikomService, HaikomService>();
services.AddDbContext<LoggingContext>(options => options.UseSqlServer(connection));
services.AddDbContext<OrderContext>(options => options.UseSqlServer(connection));
services.AddDbContext<AuthContext>(options => options.UseSqlServer(connection));
////Add application setting as options to enable dependency injection for settings
services.Configure<Mediacreator.RestApi.Models.AuthenticationModel.Options.AuthenticationOptions>(options =>
{
// Get the setting from environment variable or user secret.
// For more info: https://blogcarlosperez.com/2016/05/24/user-secrets/ eller http://asp.net-hacker.rocks/2016/07/11/user-secrets-in-aspnetcore.html
options.JwtEncryptionSigningSecret = Configuration["Tokens:Key"];
options.Audience = Configuration["Tokens:Issuer"];
options.Issuer = Configuration["Tokens:Issuer"];
});
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
services.AddSingleton<IResponseFileLogger, ResponseFileLogger>();
services.AddSingleton<IRequestFileLogger, RequestFileLogger>();
var sp = services.BuildServiceProvider();
// Resolve the services from the service provider
var jwtBearerService = sp.GetService<IJwtBearerService>();
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(options =>
{
options.TokenValidationParameters = jwtBearerService.CreateTokenValidationParameters(Configuration["Tokens:Key"]);
});
services.Configure<IISOptions>(options =>
{
options.ForwardClientCertificate = false;
options.AutomaticAuthentication = false;
});
services.AddMvc(options =>
{
//The services should only support JSON as output format for avoiding supporting for example XML
//By specifying this property, the client will get a 406 error message if the accept header is for example "Accept: application/xml".
options.ReturnHttpNotAcceptable = true;
options.EnableEndpointRouting = false;
//Enable events executed before, and after an action has been executed.
options.Filters.Add(typeof(ActionFilter));
//Make all controllers be protected by authorization
var policy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.Build();
options.Filters.Add(new AuthorizeFilter(policy));
});
}
catch (Exception ex)
{
_exceptions.Add(ex);
}
}
/// <summary>
/// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
/// </summary>
/// <param name="app"></param>
/// <param name="env"></param>
/// <param name="loggerFactory"></param>
/// <remarks>Is called after ConfigureServices</remarks>
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILoggerFactory loggerFactory)
{
ILogger logger = null;
try
{
NLog.LogManager.LoadConfiguration("NLog.config");
loggerFactory.EnsureApiLoggersExists();
logger = loggerFactory.CreateLogger(this.GetType());
logger.LogInformation($"Current environment: {env.EnvironmentName}");
//Check if any exceptions occurred during startup
if (_exceptions.Any())
{
//Terminate the pipeline and return a response to the client
app.Run(async httpContext =>
{
await ExceptionHandler.HandleExceptionWriteErrorResponse(logger, httpContext, _exceptions.First(), LogText);
});
}
//Important to add this middleware first as exceptions in other middleware are also to be caught
app.UseCustomExceptionHandler();
//Important to add this middleware before UseMvc is added as the middleware component otherwise may not be called for all requests.
app.UseRequestLogger();
app.UseResponseLogger();
app.UseAuthentication();
app.UseMvcWithDefaultRoute();
}
catch (Exception ex)
{
//Terminate the pipeline and return a response to the client
app.Run(async httpContext =>
{
await ExceptionHandler.HandleExceptionWriteErrorResponse(logger, httpContext, ex, LogText);
});
}
}
}
我不得不将 IHostingEnvironment 更改为 IWebHostEnvironment。日志记录发生了一些变化,我不得不将 options.EnableEndpointRouting = false 添加到 MVC 选项中。还有一些事情我一时想不起来了。
编辑 2,添加响应记录:
public class ResponseLogger : MiddlewareBase
{
private readonly IResponseFileLogger _IResponseLogger;
public ResponseLogger(RequestDelegate nextRequestDelegate, ILoggerFactory loggerFactory, IResponseFileLogger respLogger) : base(nextRequestDelegate, loggerFactory)
{
_IResponseLogger = respLogger;
}
public async Task InvokeAsync(HttpContext context)
{
//Adds an identifier to the response headers. The identifier is used for connecting a response to log posts for corresponding requests and responses.
context.AddTraceIdentifierToResponseHeaders();
//The original response body needs to be stored locally as it can not be rewind after reading and logging it.
//http://stackoverflow.com/questions/37855384/log-httpresponse-body-for-asp-net-core-1-0-rest-api/38275942#38275942
using (var responseBodyBufferStream = new MemoryStream())
{
//Store the original body stream in a local variable
var responseBodyStream = context.Response.Body;
try
{
//Replace the context response with the newly created buffer as the original stream is not readable.
context.Response.Body = responseBodyBufferStream;
//Invoke the rest of the pipeline
await InvokeNextDelegate(context);
//Reset the buffer so the content can be read
responseBodyBufferStream.Seek(0, SeekOrigin.Begin);
//Create a stream reader to be able to read the response
using (var bufferStreamReader = new StreamReader(responseBodyBufferStream))
{
//Read the body from the stream
string responseBody = await bufferStreamReader.ReadToEndAsync();
//Reset the buffer
responseBodyBufferStream.Seek(0, SeekOrigin.Begin);
//Copy the content to the original stream and put it back
await responseBodyBufferStream.CopyToAsync(responseBodyStream);
//var responseFileLogger = new ResponseFileLogger(LoggerFactory, context, responseBody);
_IResponseLogger.Log(context, responseBody);
}
}
finally
{
//Ensure original body stream is is written back to the response body even if an exception occurs in another middleware.
context.Response.Body = responseBodyStream;
}
}
}
}
我尝试注释掉响应记录的代码以查看这是否是问题的一部分,但似乎与我所知道的没有区别。
编辑 3,从请求中添加输出:
info: Microsoft.AspNetCore.Hosting.Diagnostics[1]
Request starting HTTP/1.1 POST http://localhost:5000/api/v1.0/authentication application/json; charset=utf-8 41
info: Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker[3]
Route matched with {action = "Authenticate", controller = "Authentication"}. Executing controller action with signature System.Threading.Tasks.Task`1[Microsoft.AspNetCore.Mvc.IActionResult] AuthenticateAsync(System.String) on controller Mediacreator.RestApi.Controllers.AuthenticationController (CoreRestApi).
info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
Entity Framework Core 3.1.1 initialized 'LoggingContext' using provider 'Microsoft.EntityFrameworkCore.SqlServer' with options: None
info: Microsoft.EntityFrameworkCore.Database.Command[20101]
Executed DbCommand (70ms) [Parameters=[@p0='?' (Size = 4000), @p1='?' (Size = 4000), @p2='?' (Size = 4000), @p3='?' (DbType = DateTime2), @p4='?' (DbType = DateTime2), @p5='?' (DbType = Int32), @p6='?' (Size = 4000), @p7='?' (DbType = Int64), @p8='?' (Size = 4000), @p9='?' (Size = 4000)], CommandType='Text', CommandTimeout='30']
SET NOCOUNT ON;
INSERT INTO [ApiLogs] ([Action], [RemoteAddress], [RequestData], [RequestDateUtc], [ResponseDateUtc], [ResponseStatusCode], [Status], [SystemUserId], [TraceIdentifier], [Url])
VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7, @p8, @p9);
SELECT [Id]
FROM [ApiLogs]
WHERE @@ROWCOUNT = 1 AND [Id] = scope_identity();
info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
Entity Framework Core 3.1.1 initialized 'AuthContext' using provider 'Microsoft.EntityFrameworkCore.SqlServer' with options: None
info: Microsoft.EntityFrameworkCore.Database.Command[20101]
Executed DbCommand (22ms) [Parameters=[@__apiKey_0='?' (Size = 4000)], CommandType='Text', CommandTimeout='30']
SELECT [t].[Id], [t].[ApiKey], [t].[Deleted], [t].[Description], [t].[IsActive], [t].[Password], [t].[Permissions], [t].[Username], [t0].[SystemUserId], [t0].[UserRoleId], [t0].[Id], [t0].[Description], [t0].[Name]
FROM (
SELECT TOP(2) [s].[Id], [s].[ApiKey], [s].[Deleted], [s].[Description], [s].[IsActive], [s].[Password], [s].[Permissions], [s].[Username]
FROM [SystemUsers] AS [s]
WHERE [s].[ApiKey] = @__apiKey_0
) AS [t]
LEFT JOIN (
SELECT [s0].[SystemUserId], [s0].[UserRoleId], [u].[Id], [u].[Description], [u].[Name]
FROM [SystemUserRole] AS [s0]
INNER JOIN [UserRoles] AS [u] ON [s0].[UserRoleId] = [u].[Id]
) AS [t0] ON [t].[Id] = [t0].[SystemUserId]
ORDER BY [t].[Id], [t0].[SystemUserId], [t0].[UserRoleId], [t0].[Id]
info: Mediacreator.RestApi.Services.Authentication.ApiAuthService[0]
User with ApiKey <xxx> authenticated
info: Mediacreator.RestApi.Services.Authentication.ApiAuthService[0]
Token created for user '<yyy>' (5). Token is valid '3600' seconds
info: Microsoft.EntityFrameworkCore.Database.Command[20101]
Executed DbCommand (20ms) [Parameters=[@__logId_0='?' (DbType = Int64)], CommandType='Text', CommandTimeout='30']
SELECT TOP(2) [a].[Id], [a].[Action], [a].[RemoteAddress], [a].[RequestData], [a].[RequestDateUtc], [a].[ResponseDateUtc], [a].[ResponseStatusCode], [a].[Status], [a].[SystemUserId], [a].[TraceIdentifier], [a].[Url]
FROM [ApiLogs] AS [a]
WHERE [a].[Id] = @__logId_0
info: Microsoft.EntityFrameworkCore.Database.Command[20101]
Executed DbCommand (20ms) [Parameters=[@p3='?' (DbType = Int64), @p0='?' (DbType = DateTime2), @p1='?' (DbType = Int32), @p2='?' (Size = 4000)], CommandType='Text', CommandTimeout='30']
SET NOCOUNT ON;
UPDATE [ApiLogs] SET [ResponseDateUtc] = @p0, [ResponseStatusCode] = @p1, [Status] = @p2
WHERE [Id] = @p3;
SELECT @@ROWCOUNT;
info: Microsoft.AspNetCore.Mvc.Infrastructure.ObjectResultExecutor[1]
Executing ObjectResult, writing value of type 'Mediacreator.RestApi.Models.AuthenticationModel.Entities.Token'.
info: Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker[2]
Executed action Mediacreator.RestApi.Controllers.AuthenticationController.AuthenticateAsync (CoreRestApi) in 8305.5034ms
info: Microsoft.AspNetCore.Hosting.Diagnostics[2]
Request finished in 11069.4992ms 200 application/json; charset=utf-8
编辑 4:添加 Token 类
public class Token
{
public readonly string access_token;
public readonly string token_type = Constants.TokenTypeBearer;
public readonly int expires_in;
public Token(string encodedJsonWebToken, int expiresInSeconds)
{
access_token = encodedJsonWebToken;
expires_in = expiresInSeconds;
}
}
最佳答案
它不起作用的原因是@Ian Kemp 建议我的 Token 类的序列化不起作用。我读到他们在 Core 3.0 中添加了一个带有 System.Text.Json 的新序列化,但出于某种原因,它无法与
一起使用public class Token
{
public readonly string access_token;
public readonly string token_type = Constants.TokenTypeBearer;
public readonly int expires_in;
public Token(string encodedJsonWebToken, int expiresInSeconds)
{
access_token = encodedJsonWebToken;
expires_in = expiresInSeconds;
}
}
所以我决定试用 Newtonsoft,现在它像以前一样工作了。
解决方案是将其添加到 Startup.cs 中的 ConfigureServices
services.AddControllers().AddNewtonsoftJson();
关于c# - 从 Core 2.0 更新到 3.1.1 后响应正文为空,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59932578/
我查看了网站上的一些问题,但还没有完全弄清楚我做错了什么。我有一些这样的代码: var mongoose = require('mongoose'), db = mongoose.connect('m
基本上,根据 this bl.ocks,我试图在开始新序列之前让所有 block 都变为 0。我认为我需要的是以下顺序: 更新为0 退出到0 更新随机数 输入新号码 我尝试通过添加以下代码块来遵循上述
我试图通过使用随机数在循环中设置 JSlider 位置来模拟“赛马”的投注结果。我的问题是,当然,我无法在线程执行时更新 GUI,因此我的 JSlider 似乎没有在竞赛,它们从头到尾都在运行。我尝试
该功能非常简单: 变量:$table是正在更新的表$fields 是表中的字段,$values 从帖子生成并放入 $values 数组中而$where是表的索引字段的id值$indxfldnm 是索引
让我们想象一个环境:有一个数据库客户端和一个数据库服务器。数据库客户端可以是 Java 程序或其他程序等;数据库服务器可以是mysql、oracle等。 需求是在数据库服务器上的一个表中插入大量记录。
在我当前的应用程序中,我正在制作一个菜单结构,它可以递归地创建自己的子菜单。然而,由于这个原因,我发现很难也允许某种重新排序方法。大多数应用程序可能只是通过“排序”列进行排序,但是在这种情况下,尽管这
Provisioning Profile 有 key , key 链依赖于它。我想知道 key 什么时候会改变。 Key will change after renew Provisioning Pr
截至目前,我在\server\publications.js 中有我的 MongoDB“选择”,例如: Meteor.publish("jobLocations", function () { r
我读到 UI 应该始终在主线程上更新。但是,当谈到实现这些更新的首选方法时,我有点困惑。 我有各种函数可以执行一些条件检查,然后使用结果来确定如何更新 UI。我的问题是整个函数应该在主线程上运行吗?应
我在代理后面,我无法构建 Docker 镜像。 我试过 FROM ubuntu , FROM centos和 FROM alpine ,但是 apt-get update/yum update/apk
我构建了一个 Java 应用程序,它向外部授权客户端公开网络服务。 Web 服务使用带有证书身份验证的 WS-security。基本上我们充当自定义证书颁发机构 - 我们在我们的服务器上维护一个 ja
因此,我有时会在上传新版本时使用 app_offline.htm 使应用程序离线。 但是,当我上传较大的 dll 时,我收到黄色错误屏幕,指出无法加载 dll。 这似乎与我对 app_offline.
我刚刚下载了 VS Apache Cordova Tools Update 5,但遇到了 Node 和 NPM 的问题。我使用默认的空白 cordova 项目进行测试。 版本 如果我在 VS 项目中对
所以我有一个使用传单库实例化的 map 对象。 map 实例在单独的模板中创建并以这种方式路由:- var app = angular.module('myApp', ['ui', 'ngResour
我使用较早的 Java 6 u 3 获得的帧速率是新版本的两倍。很奇怪。谁能解释一下? 在 Core 2 Duo 1.83ghz 上,集成视频(仅使用一个内核)- 1500(较旧的 java)与 70
我正在使用 angular 1.2 ng-repeat 创建的 div 也包含 ng-click 点击时 ng-click 更新 $scope $scope 中的变化反射(reflect)在使用 $a
这些方法有什么区别 public final void moveCamera(CameraUpdate更新)和public final void animateCamera (CameraUpdate
我尝试了另一篇文章中某人评论中关于如何将树更改为列表的建议。但是,我在某处(或某物)有未声明的变量,所以我列表中的值是 [_G667, _G673, _G679],而不是 [5, 2, 6],这是正确
实现以下场景的最佳方法是什么? 我需要从java应用程序调用/查询包含数百万条记录的数据库表。然后,对于表中的每条记录,我的应用程序应该调用第三方 API 并获取状态字段作为响应。然后我的应用程序应该
只是在编写一些与 java 图形相关的代码,这是我今天的讲座中的非常简单的示例。不管怎样,互联网似乎说更新不会被系统触发器调用,例如调整框架大小等。在这个例子中,更新是由这样的触发器调用的(因此当我只
我是一名优秀的程序员,十分优秀!