0
我正在使用ASP.NET MVC核心作爲後端API的Angular SPA,並且我的 讓我的JWT身份驗證正常工作時遇到了很多麻煩。JWT使用Angular和MVC Core進行身份驗證/授權
我使用Openiddict作爲我的JWT中間件來發放令牌。我可以成功向我的控制器發送令牌請求,將用戶登錄並將令牌發送回客戶端。
但是,當我嘗試訪問受保護的API路由時,我收到401未經授權的消息。我可以看到這個令牌是在請求的頭部發送的,所以它不能在服務器端正確讀取,所以我認爲這只是一個配置問題。我所看到的每個資源都使得看起來沒有其他配置明智的做法。
這裏是代碼的相關部分:
啓動配置服務
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.AddAuthorization();
services.AddEntityFramework()
.AddEntityFrameworkSqlServer()
.AddDbContext<DbContext>();
services.AddIdentity<User, IdentityRole>(config =>
{
config.User.RequireUniqueEmail = true;
config.Password.RequiredLength = 8;
})
.AddEntityFrameworkStores<DbContext>()
.AddDefaultTokenProviders();
services.AddOpenIddict<DbContext>()
.AddMvcBinders()
.EnableTokenEndpoint("/auth/token")
.UseJsonWebTokens()
.AllowPasswordFlow()
.AddEphemeralSigningKey()
//.AddSigningCertificate()
.DisableHttpsRequirement();
services.AddLogging();
}
啓動配置應用
public void Configure(IApplicationBuilder app, RequestJockeyDataSeeder seeder, ILoggerFactory factory)
{
app.UseDefaultFiles(new DefaultFilesOptions()
{
DefaultFileNames = new[] { "index.html" }
});
app.UseStaticFiles();
app.UseOpenIddict();
app.UseJwtBearerAuthentication(new JwtBearerOptions()
{
AutomaticAuthenticate = true,
AutomaticChallenge = true,
Audience = "http://localhost:5000",
Authority = "http://localhost:5000",
RequireHttpsMetadata = false,
});
app.UseMvc();
}
控制器 - 我得到這個從一個例子在網上
[HttpPost("~/auth/token"), Produces("application/json")]
public async Task<IActionResult> Token(OpenIdConnectRequest request)
{
if (!request.IsPasswordGrantType())
{
// Return bad request if the request is not for password grant type
return BadRequest(new OpenIdConnectResponse
{
Error = OpenIdConnectConstants.Errors.UnsupportedGrantType,
ErrorDescription = "The specified grant type is not supported."
});
}
var user = await _userManager.FindByNameAsync(request.Username);
if (user == null)
{
// Return bad request if the user doesn't exist
return BadRequest(new OpenIdConnectResponse
{
Error = OpenIdConnectConstants.Errors.InvalidGrant,
ErrorDescription = "Invalid username or password"
});
}
// Check that the user can sign in and is not locked out.
// If two-factor authentication is supported, it would also be appropriate to check that 2FA is enabled for the user
if (!await _signInManager.CanSignInAsync(user) || (_userManager.SupportsUserLockout && await _userManager.IsLockedOutAsync(user)))
{
// Return bad request is the user can't sign in
return BadRequest(new OpenIdConnectResponse
{
Error = OpenIdConnectConstants.Errors.InvalidGrant,
ErrorDescription = "The specified user cannot sign in."
});
}
if (!await _userManager.CheckPasswordAsync(user, request.Password))
{
// Return bad request if the password is invalid
return BadRequest(new OpenIdConnectResponse
{
Error = OpenIdConnectConstants.Errors.InvalidGrant,
ErrorDescription = "Invalid username or password"
});
}
// The user is now validated, so reset lockout counts, if necessary
if (_userManager.SupportsUserLockout)
{
await _userManager.ResetAccessFailedCountAsync(user);
}
// Create the principal
var principal = await _signInManager.CreateUserPrincipalAsync(user);
// Claims will not be associated with specific destinations by default, so we must indicate whether they should
// be included or not in access and identity tokens.
foreach (var claim in principal.Claims)
{
// For this sample, just include all claims in all token types.
// In reality, claims' destinations would probably differ by token type and depending on the scopes requested.
claim.SetDestinations(OpenIdConnectConstants.Destinations.AccessToken, OpenIdConnectConstants.Destinations.IdentityToken);
}
// Create a new authentication ticket for the user's principal
var ticket = new AuthenticationTicket(
principal,
new AuthenticationProperties(),
OpenIdConnectServerDefaults.AuthenticationScheme);
// Include resources and scopes, as appropriate
var scope = new[]
{
OpenIdConnectConstants.Scopes.OpenId,
OpenIdConnectConstants.Scopes.Email,
OpenIdConnectConstants.Scopes.Profile,
OpenIdConnectConstants.Scopes.OfflineAccess,
OpenIddictConstants.Scopes.Roles
}.Intersect(request.GetScopes());
ticket.SetResources("http://localhost:5000/");
ticket.SetScopes(scope);
ticket.Properties.ExpiresUtc = DateTimeOffset.Now.AddMinutes(15);
// Sign in the user
return SignIn(ticket.Principal, ticket.Properties, ticket.AuthenticationScheme);
}
我將省略角度http攔截器,因爲路由既通過應用程序也通過郵遞員失敗。有沒有什麼我錯過配置MVC正確處理這些令牌?
Outch不,不這樣做:禁用簽名密鑰會允許任何人創建僞造的令牌。請用您的日誌更新您的問題,這將會更容易幫助您。 – Pinpoint