У меня есть проблема, и мне нужна ясность.У меня есть AccountController с действием Login, которое обрабатывает имя входа, и, если оно прошло успешно, оно перенаправляет пользователя на домашнюю страницу, которую я хочу защитить с помощью jwt.Таким образом, мой вопрос заключается в следующем: я знаю, что правильно перенаправляю на свой дом / индекс, но мне не хватает чего-то для аутентификации предоставленного токена.1. Какой тег атрибута мне нужно добавить в начало класса HomeController?2. Как я могу передать с помощью '@ Url.Action ("Index", "Home") "?
РЕДАКТИРОВАТЬ: После успешного входа в систему, он говорит, что я успешно вошел в систему, но поскольку мне требуется, чтобы токен находился в заголовках, когда я пытаюсь перенаправить с помощью @ Url.Action (), он отправляет неверный запрос, потому что я не уверен, как заполнять заголовки этим.
Вот Startup.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Chat.Controllers;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.HttpsPolicy;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.IdentityModel.Tokens;
namespace Chat
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidateAudience = true,
ValidateIssuerSigningKey = true,
ValidIssuer = "localhost",
ValidAudience = "localhost",
IssuerSigningKey = AccountController.SIGNING_KEY
};
});
services.Configure<CookiePolicyOptions>(options =>
{
// This lambda determines whether user consent for non-essential cookies is needed for a given request.
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
});
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseCookiePolicy();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Account}/{action=Index}/{id?}");
});
}
}
}
Вот AccountController с действием для входа:
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Chat.Models;
using Chat.DatabaseAccessObject;
using Chat.Identity;
using Chat.DatabaseAccessObject.CommandObjects;
using System.Linq.Expressions;
using System.Net.Mime;
using System.Security.Claims;
using System.Text;
using Microsoft.AspNetCore.Authentication;
using Microsoft.IdentityModel.Tokens;
namespace Chat.Controllers
{
public class AccountController : Controller
{
private const string SECRET_KEY = "CHATSECRETKEY";
public static SymmetricSecurityKey SIGNING_KEY = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(SECRET_KEY));
private ServerToStorageFacade serverToStorageFacade = new ServerToStorageFacade();
private AuthenticateUser authenticateUser = new AuthenticateUser();
public IActionResult Index()
{
return View();
}
[HttpPost]
public async Task<IActionResult> Login([FromBody]LoginModel loginModel)
{
if (ModelState.IsValid)
{
var mapLoginModelToUser = new MapLoginModelToUser();
var user = await mapLoginModelToUser.MapObject(loginModel);
// If login user with those credentials does not exist
if(user == null)
{
return BadRequest();
}
else
{
var result = await this.authenticateUser.Authenticate(user);
if(result.Result == Chat.Enums.AuthenticateResult.Success)
{
// SUCCESSFUL LOGIN
// Creating and storing cookies
var token = Json(new
{
data = this.GenerateToken(user.Email, user.PantherID),
redirectUrl = Url.Action("Index","Home"),
success = true
});
return Ok(token);
}
else
{
// Unsuccessful login
return Unauthorized();
}
}
}
return BadRequest();
}
private string GenerateToken(string email, string pantherId)
{
var claimsData = new[] { new Claim(ClaimTypes.Email, email), new Claim(ClaimTypes.Actor, pantherId) };
var signInCredentials = new SigningCredentials(SIGNING_KEY, SecurityAlgorithms.HmacSha256);
var token = new JwtSecurityToken(
issuer: "localhost",
audience: "localhost",
expires: DateTime.Now.AddDays(7),
claims: claimsData,
signingCredentials: signInCredentials
);
return new JwtSecurityTokenHandler().WriteToken(token);
}
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
public async Task<IActionResult> Error() => View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
}
Вот Index.cshtml, расположенный в '/Views / Account / Index.cshtml ':
@{
Layout = null;
ViewData["Title"] = "Login";
}
@model Chat.Models.LoginModel
<!doctype html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
<link href="/css/signin.css" rel="stylesheet">
<script src="~/lib/jquery/dist/jquery.js"></script>
<script src="~/lib/bootstrap/dist/js/bootstrap.js"></script>
<script src="~/js/Login.js"></script>
</head>
<body class="text-center">
<form id="formSubmit" method="post" class="form-signin">
<img class="mb-4" src="~/images/Chat-Curved.png" alt="" width="150" height="150">
<h1 class="h3 mb-3 font-weight-normal">Please sign in</h1>
<label for="inputEmail" class="sr-only">Email address</label>
@Html.TextBoxFor(m => m.inputEmail, new { @class = "form-control", @type="email", @placeholder = "Email address", @required = "required", @autofocus = "" })
<label for="inputPassword" class="sr-only">Password</label>
@Html.PasswordFor(m => m.inputPassword, new { @class = "form-control", @type="password", @placeholder = "Password", @required = "required"})
<div class="checkbox mb-3">
<label>
@Html.CheckBoxFor(m => m.rememberMe) Remeber me
</label>
</div>
<button id="btnLogin" class="btn btn-lg btn-primary btn-block" type="submit">Sign in</button>
<p class="mt-5 mb-3 text-muted">© 2017-2018</p>
</form>
</body>
</html>
Вот HomeController с действием Index:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
namespace Chat.Controllers
{
public class HomeController : Controller
{
public IActionResult Index()
{
return View();
}
}
}
Это Login.js, на который ссылается Index.cshtml:
$(document).ready(function () {
$("#formSubmit").submit(function (event) {
event.preventDefault();
var email = $("#inputEmail").val();
var password = $("#inputPassword").val();
var remember = $("#rememberMe").val();
var loginModel = {
inputEmail: email,
inputPassword: password,
rememberMe: remember
};
$.ajax({
type: 'POST',
url: 'Account/Login',
data: JSON.stringify(loginModel),
contentType: 'application/json; charset=utf-8;',
success: function (response) {
var token = response.value.data;
localStorage.setItem("token", token);
window.location.href = response.value.redirectUrl;
}
});
});
});