Tôi đang cố di chuyển dự án này https://github.com/asadsahi/AspNetCoreSpa từ .net lõi 1.1 đến 2.0 nhưng gặp sự cố sau khi đăng nhập thành công. Sau khi đăng nhập, GET GET của tôi gọi e. g. đến https://localhost:44331/api/profile/test kết thúc bằng chuyển hướng (302) và tôi không biết tại sao. Tôi đã nhận được một mã thông báo mang và nó có vẻ tốt.Cuộc gọi API ASP.NET Core 2 được chuyển hướng (302)
định dạng tiêu đềYêu cầu: ủy quyền: Bearer [thẻ]
[Route("api/[controller]")]
public class ProfileController : BaseController
{
private readonly UserManager<ApplicationUser> _userManager;
private readonly ILogger _logger;
public ProfileController(ILoggerFactory loggerFactory, UserManager<ApplicationUser> userManager)
{
_logger = loggerFactory.CreateLogger<ProfileController>();
_userManager = userManager;
}
[HttpGet("test")]
public async Task<IActionResult> Test()
{
return Json(ModelState.GetModelErrors());
}
}
[Authorize]
[ServiceFilter(typeof(ApiExceptionFilter))]
[ResponseCache(Location = ResponseCacheLocation.None, NoStore = true)]
public class BaseController : Controller
{
public BaseController()
{
}
}
Startup.cs:
public void ConfigureServices(IServiceCollection services)
{
if (_hostingEnv.IsDevelopment())
{
services.AddSslCertificate(_hostingEnv);
}
else
{
services.Configure<MvcOptions>(o => o.Filters.Add(new RequireHttpsAttribute()));
}
services.AddOptions();
services.AddCors();
services.AddLogging();
services.AddResponseCompression(options =>
{
options.MimeTypes = Helpers.DefaultMimeTypes;
});
services.AddAuthentication(sharedOptions =>
{
sharedOptions.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
sharedOptions.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
sharedOptions.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(cfg =>
{
cfg.SaveToken = true;
cfg.TokenValidationParameters = new TokenValidationParameters
{
ValidIssuer = Configuration["Authentication:BearerTokens:Issuer"],
ValidAudience = Configuration["Authentication:BearerTokens:Audience"],
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["Authentication:BearerTokens:Key"])),
ValidateIssuerSigningKey = false,
ValidateLifetime = true,
ClockSkew = TimeSpan.Zero
};
cfg.Events = new JwtBearerEvents
{
OnAuthenticationFailed = context =>
{
var logger = context.HttpContext.RequestServices.GetRequiredService<ILoggerFactory>().CreateLogger(nameof(JwtBearerEvents));
logger.LogError("Authentication failed.", context.Exception);
return Task.CompletedTask;
},
OnMessageReceived = context =>
{
return Task.CompletedTask;
},
OnChallenge = context =>
{
var logger = context.HttpContext.RequestServices.GetRequiredService<ILoggerFactory>().CreateLogger(nameof(JwtBearerEvents));
logger.LogError("OnChallenge error", context.Error, context.ErrorDescription);
return Task.CompletedTask;
}
};
});
services.AddDbContext<ApplicationDbContext>(options =>
{
string useSqLite = Startup.Configuration["Data:useSqLite"];
if (useSqLite.ToLower() == "true")
{
options.UseSqlite(Startup.Configuration["Data:SqlLiteConnectionString"]);
}
else
{
options.UseSqlServer(Startup.Configuration["Data:SqlServerConnectionString"]);
}
options.UseOpenIddict();
});
services.AddIdentity<ApplicationUser, ApplicationRole>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
//services.ConfigureApplicationCookie(options =>
//{
// options.LoginPath = "/login";
// options.Events.OnRedirectToLogin = context =>
// {
// if (context.Request.Path.StartsWithSegments("/api") &&
// context.Response.StatusCode == (int)HttpStatusCode.OK)
// {
// context.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
// }
// else
// {
// context.Response.Redirect(context.RedirectUri);
// }
// return Task.FromResult(0);
// };
//});
services.AddOAuthProviders();
services.AddCustomOpenIddict();
services.AddMemoryCache();
services.RegisterCustomServices();
services.AddAntiforgery(options => options.HeaderName = "X-XSRF-TOKEN");
services.AddCustomizedMvc();
// Node services are to execute any arbitrary nodejs code from .net
services.AddNodeServices();
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new Info { Title = "AspNetCoreSpa", Version = "v1" });
});
}
public void Configure(IApplicationBuilder app)
{
app.AddDevMiddlewares();
if (_hostingEnv.IsProduction())
{
app.UseResponseCompression();
}
app.SetupMigrations();
app.UseXsrf();
app.UseStaticFiles();
app.UseAuthentication();
app.UseMvc(routes =>
{
// http://stackoverflow.com/questions/25982095/using-googleoauth2authenticationoptions-got-a-redirect-uri-mismatch-error
routes.MapRoute(name: "signin-google", template: "signin-google", defaults: new { controller = "Account", action = "ExternalLoginCallback" });
routes.MapSpaFallbackRoute(
name: "spa-fallback",
defaults: new { controller = "Home", action = "Index" });
});
}
My IServiceCollection-Extensions:
public static IServiceCollection AddCustomizedMvc(this IServiceCollection services)
{
services.AddMvc(options =>
{
options.Filters.Add(typeof(ModelValidationFilter));
})
.AddJsonOptions(options =>
{
options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
});
return services;
}
public static IServiceCollection AddOAuthProviders(this IServiceCollection services)
{
services.AddAuthentication()
.AddFacebook(o =>
{
o.AppId = Startup.Configuration["Authentication:Facebook:AppId"];
o.AppSecret = Startup.Configuration["Authentication:Facebook:AppSecret"];
});
services.AddAuthentication()
.AddGoogle(o =>
{
o.ClientId = Startup.Configuration["Authentication:Google:ClientId"];
o.ClientSecret = Startup.Configuration["Authentication:Google:ClientSecret"];
});
services.AddAuthentication()
.AddTwitter(o =>
{
o.ConsumerKey = Startup.Configuration["Authentication:Twitter:ConsumerKey"];
o.ConsumerSecret = Startup.Configuration["Authentication:Twitter:ConsumerSecret"];
});
services.AddAuthentication()
.AddMicrosoftAccount(o =>
{
o.ClientId= Startup.Configuration["Authentication:Microsoft:ClientId"];
o.ClientSecret = Startup.Configuration["Authentication:Microsoft:ClientSecret"];
});
return services;
}
public static IServiceCollection AddCustomOpenIddict(this IServiceCollection services)
{
// Configure Identity to use the same JWT claims as OpenIddict instead
// of the legacy WS-Federation claims it uses by default (ClaimTypes),
// which saves you from doing the mapping in your authorization controller.
services.Configure<IdentityOptions>(options =>
{
options.ClaimsIdentity.UserNameClaimType = OpenIdConnectConstants.Claims.Name;
options.ClaimsIdentity.UserIdClaimType = OpenIdConnectConstants.Claims.Subject;
options.ClaimsIdentity.RoleClaimType = OpenIdConnectConstants.Claims.Role;
});
// Register the OpenIddict services.
services.AddOpenIddict()
// Register the Entity Framework stores.
.AddEntityFrameworkCoreStores<ApplicationDbContext>()
// Register the ASP.NET Core MVC binder used by OpenIddict.
// Note: if you don't call this method, you won't be able to
// bind OpenIdConnectRequest or OpenIdConnectResponse parameters.
.AddMvcBinders()
// Enable the token endpoint.
.EnableTokenEndpoint("/connect/token")
// Enable the password and the refresh token flows.
.AllowPasswordFlow()
.AllowRefreshTokenFlow()
// During development, you can disable the HTTPS requirement.
.DisableHttpsRequirement()
// Register a new ephemeral key, that is discarded when the application
// shuts down. Tokens signed using this key are automatically invalidated.
// This method should only be used during development.
.AddEphemeralSigningKey();
// On production, using a X.509 certificate stored in the machine store is recommended.
// You can generate a self-signed certificate using Pluralsight's self-cert utility:
// https://s3.amazonaws.com/pluralsight-free/keith-brown/samples/SelfCert.zip
//
// services.AddOpenIddict()
// .AddSigningCertificate("7D2A741FE34CC2C7369237A5F2078988E17A6A75");
//
// Alternatively, you can also store the certificate as an embedded .pfx resource
// directly in this assembly or in a file published alongside this project:
//
// services.AddOpenIddict()
// .AddSigningCertificate(
// assembly: typeof(Startup).GetTypeInfo().Assembly,
// resource: "AuthorizationServer.Certificate.pfx",
// password: "OpenIddict");
return services;
}
public static IServiceCollection AddCustomDbContext(this IServiceCollection services)
{
// Add framework services.
return services;
}
public static IServiceCollection RegisterCustomServices(this IServiceCollection services)
{
// New instance every time, only configuration class needs so its ok
services.Configure<SmsSettings>(options => Startup.Configuration.GetSection("SmsSettingsTwillio").Bind(options));
services.AddTransient<UserResolverService>();
services.AddTransient<IEmailSender, EmailSender>();
services.AddTransient<ISmsSender, SmsSender>();
services.AddScoped<ApiExceptionFilter>();
return services;
}
Đây gói của tôi:
<ItemGroup>
<PackageReference Include="AspNet.Security.OAuth.Introspection" Version="2.0.0-*" />
<PackageReference Include="AspNet.Security.OAuth.Validation" Version="2.0.0-*" />
<PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.Cookies" Version="2.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="2.0.0" />
<PackageReference Include="Microsoft.AspNetCore.AzureAppServicesIntegration" Version="2.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Diagnostics" Version="2.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore" Version="2.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="2.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Cors" Version="2.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Antiforgery" Version="2.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Authorization" Version="2.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.Google" Version="2.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.Facebook" Version="2.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.MicrosoftAccount" Version="2.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.Twitter" Version="2.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Server.IISIntegration" Version="2.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" Version="2.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Server.Kestrel.Https" Version="2.0.0" />
<PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="2.0.0" />
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="2.0.0" />
<PackageReference Include="Microsoft.AspNetCore.ResponseCompression" Version="2.0.0" />
<PackageReference Include="Microsoft.AspNetCore.WebSockets" Version="2.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="2.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="2.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="2.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="2.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="2.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="2.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="2.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="2.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="2.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="2.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Http.Abstractions" Version="2.0.0" />
<PackageReference Include="Microsoft.AspNetCore.AngularServices" Version="1.1.0-beta-000002" />
<PackageReference Include="AspNet.Security.OAuth.GitHub" Version="1.0.0-beta3-final" />
<PackageReference Include="AspNet.Security.OAuth.LinkedIn" Version="1.0.0-beta3-final" />
<PackageReference Include="OpenIddict" Version="2.0.0-*" />
<PackageReference Include="OpenIddict.EntityFrameworkCore" Version="2.0.0-*" />
<PackageReference Include="OpenIddict.Mvc" Version="2.0.0-*" />
<PackageReference Include="SendGrid" Version="9.9.0" />
<PackageReference Include="MailKit" Version="1.18.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="1.0.0" />
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerUI" Version="1.0.0" />
<PackageReference Include="Twilio" Version="5.6.3" />
<PackageReference Include="Stripe.net" Version="10.4.0" />
<PackageReference Include="Newtonsoft.Json" Version="10.0.3" />
<PackageReference Include="Webpack" Version="4.0.0" />
<PackageReference Include="Serilog" Version="2.5.0" />
<PackageReference Include="Serilog.Extensions.Logging" Version="2.0.2" />
<PackageReference Include="Serilog.Sinks.Seq" Version="3.3.3" />
<PackageReference Include="Bogus" Version="17.0.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="2.0.0">
<PrivateAssets>All</PrivateAssets>
</PackageReference>
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="2.0.0">
<PrivateAssets>All</PrivateAssets>
</PackageReference>
<PackageReference Include="Microsoft.AspNetCore.Mvc.Razor.ViewCompilation" Version="2.0.0" PrivateAssets="All" />
</ItemGroup>
<ItemGroup>
<DotNetCliToolReference Include="Microsoft.DotNet.Watcher.Tools" Version="2.0.0" />
<DotNetCliToolReference Include="Microsoft.EntityFrameworkCore.Tools.DotNet" Version="2.0.0" />
<DotNetCliToolReference Include="Microsoft.Extensions.SecretManager.Tools" Version="2.0.0" />
<DotNetCliToolReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Tools" Version="2.0.0" />
</ItemGroup>
Dưới đây là các bản ghi của tôi:
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
Request starting HTTP/1.1 GET http://localhost:44331/api/profile/test
application/json; charset=UTF-8
info: Microsoft.AspNetCore.Authorization.DefaultAuthorizationService[2]
Authorization failed for user: (null).
info: Microsoft.AspNetCore.Authorization.DefaultAuthorizationService[2]
Authorization failed for user: (null).
info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[3]
Authorization failed for the request at filter
'Microsoft.AspNetCore.Mvc.Authorization.AuthorizeFilter'.
info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[3]
Authorization failed for the request at filter
'Microsoft.AspNetCore.Mvc.Authorization.AuthorizeFilter'.
info: Microsoft.AspNetCore.Mvc.ChallengeResult[1]
Executing ChallengeResult with authentication schemes().
info: Microsoft.AspNetCore.Mvc.ChallengeResult[1]
Executing ChallengeResult with authentication schemes().
info:
Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationHandler[12]
AuthenticationScheme: Identity.Application was challenged.
info:
Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationHandler[12]
AuthenticationScheme: Identity.Application was challenged.
info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
Executed action
AspNetCoreSpa.Server.Controllers.api.ProfileController.Test (AspNetCoreSpa)
in 43.3105ms
info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
Executed action
AspNetCoreSpa.Server.Controllers.api.ProfileController.Test (AspNetCoreSpa)
in 43.3105ms
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
Request finished in 67.4133ms 302
infoinfo: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
Request finished in 67.4133ms 302
: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
Request starting HTTP/1.1 GET http://localhost:44331/Account/Login?
ReturnUrl=%2Fapi%2Fprofile%2Ftest application/json; charset=UTF-8
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
Request starting HTTP/1.1 GET http://localhost:44331/Account/Login?
ReturnUrl=%2Fapi%2Fprofile%2Ftest application/json; charset=UTF-8
info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
Executing action method
AspNetCoreSpa.Server.Controllers.HomeController.Index (AspNetCoreSpa) with
arguments ((null)) - ModelState is Valid
info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
Executing action method
AspNetCoreSpa.Server.Controllers.HomeController.Index (AspNetCoreSpa) with
arguments ((null)) - ModelState is Valid
info: Microsoft.AspNetCore.Mvc.ViewFeatures.Internal.ViewResultExecutor[1]
Executing ViewResult, running view at path /Views/Home/Index.cshtml.
info: Microsoft.AspNetCore.Mvc.ViewFeatures.Internal.ViewResultExecutor[1]
Executing ViewResult, running view at path /Views/Home/Index.cshtml.
info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
Executed action AspNetCoreSpa.Server.Controllers.HomeController.Index
(AspNetCoreSpa) in 13.2746ms
info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
Executed action AspNetCoreSpa.Server.Controllers.HomeController.Index
(AspNetCoreSpa) in 13.2746ms
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
Request finished in 79.2352ms 200 text/html; charset=utf-8
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
Request finished in 79.2352ms 200 text/html; charset=utf-8
Tôi tự hỏi về dòng sau:
Authorization sai đối với user: (null)
Đã tìm thấy ASP.NET Core - Authorization failed for user: (null) này nhưng có không có câu trả lời nào được nêu ra và tôi nghĩ rằng nó là một .net lõi 1 vấn đề.
Cảm ơn sự giúp đỡ của bạn!
Trân trọng Simon
Tôi gặp sự cố chính xác tương tự. 302 đang cố đưa tôi đến ~/Tài khoản/Đăng nhập. Sau đó, tôi nhận được 404 vì tuyến đường đó không tồn tại. – Bloodhound
Tôi cũng phải đối mặt với cùng một vấn đề sau khi nâng cấp lên lõi asp.net 2 – cuppy
bạn có giải quyết được vấn đề này không? – Hristo