add jwt auth
This commit is contained in:
parent
0c94c926a5
commit
0bf5823652
@ -7,6 +7,8 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="FluentValidation.AspNetCore" Version="11.3.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="6.0.4" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="6.0.14" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="6.0.6">
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
@ -14,6 +16,7 @@
|
||||
</PackageReference>
|
||||
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="6.0.7" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" />
|
||||
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="6.35.0" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
104
Cloud/Controllers/AuthController.cs
Normal file
104
Cloud/Controllers/AuthController.cs
Normal file
@ -0,0 +1,104 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Cloud.Models;
|
||||
using Cloud.Requests;
|
||||
using Microsoft.IdentityModel.Tokens;
|
||||
using System.IdentityModel.Tokens.Jwt;
|
||||
using System.Text;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using System.Security.Claims;
|
||||
|
||||
namespace Cloud.Controllers;
|
||||
|
||||
[ApiController]
|
||||
[Route("api/[controller]")]
|
||||
public class AuthController : ControllerBase
|
||||
{
|
||||
private PasswordHasher<User> _passwordHasher;
|
||||
private IConfiguration _config;
|
||||
private ApplicationContext _context;
|
||||
|
||||
public AuthController(IConfiguration config, ApplicationContext context)
|
||||
{
|
||||
_passwordHasher = new PasswordHasher<User>();
|
||||
_config = config;
|
||||
_context = context;
|
||||
}
|
||||
|
||||
[HttpPost("register")]
|
||||
public async Task<IActionResult> Register([FromBody] RegisterRequest request)
|
||||
{
|
||||
var existUser = await _context.Users.SingleOrDefaultAsync(u => u.Email == request.Email);
|
||||
|
||||
if (existUser != null) {
|
||||
return BadRequest("Пользователь с такой эл. почтой уже существует");
|
||||
}
|
||||
|
||||
var user = new User
|
||||
{
|
||||
Name = request.Name,
|
||||
Email = request.Email,
|
||||
Password = _passwordHasher.HashPassword(null, request.Password)
|
||||
};
|
||||
|
||||
_context.Users.Add(user);
|
||||
await _context.SaveChangesAsync();
|
||||
|
||||
return Ok("Пользователь успешно зарегистрирован");
|
||||
}
|
||||
|
||||
[HttpPost("login")]
|
||||
public async Task<IActionResult> Login([FromBody] LoginRequest request)
|
||||
{
|
||||
var user = await _context.Users.SingleOrDefaultAsync(u => u.Email == request.Email);
|
||||
|
||||
if (user == null) {
|
||||
return Unauthorized("Пользователя с такой эл. почтой не существует");
|
||||
}
|
||||
|
||||
var verificationResult = _passwordHasher.VerifyHashedPassword(null, user.Password, request.Password);
|
||||
|
||||
if (verificationResult == PasswordVerificationResult.Failed) {
|
||||
return Unauthorized("Неверный пароль");
|
||||
}
|
||||
|
||||
var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_config["Jwt:Key"]));
|
||||
var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256);
|
||||
|
||||
var claims = new[]
|
||||
{
|
||||
new Claim(ClaimTypes.Name, user.Email),
|
||||
};
|
||||
|
||||
var Sectoken = new JwtSecurityToken(_config["Jwt:Issuer"],
|
||||
_config["Jwt:Issuer"],
|
||||
claims: claims,
|
||||
expires: DateTime.Now.AddMinutes(120),
|
||||
signingCredentials: credentials);
|
||||
|
||||
var token = new JwtSecurityTokenHandler().WriteToken(Sectoken);
|
||||
|
||||
return Ok(token);
|
||||
}
|
||||
|
||||
[Authorize]
|
||||
[HttpGet("user")]
|
||||
public async Task<IActionResult> GetAuthUser()
|
||||
{
|
||||
var userEmail = User.Identity.Name;
|
||||
|
||||
var user = await _context.Users.SingleOrDefaultAsync(u => u.Email == userEmail);
|
||||
|
||||
if (user == null) {
|
||||
return NotFound("Пользователь не найден");
|
||||
}
|
||||
|
||||
return Ok(new
|
||||
{
|
||||
user.Id,
|
||||
user.Name,
|
||||
user.Email
|
||||
});
|
||||
}
|
||||
}
|
@ -1,17 +1,73 @@
|
||||
using Cloud;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
||||
using Microsoft.IdentityModel.Tokens;
|
||||
using System.Text;
|
||||
using FluentValidation;
|
||||
using FluentValidation.AspNetCore;
|
||||
using Cloud.Validation;
|
||||
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
|
||||
// Add services to the container.
|
||||
|
||||
//Jwt configuration starts here
|
||||
var jwtIssuer = builder.Configuration.GetSection("Jwt:Issuer").Get<string>();
|
||||
var jwtKey = builder.Configuration.GetSection("Jwt:Key").Get<string>();
|
||||
|
||||
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
|
||||
.AddJwtBearer(options =>
|
||||
{
|
||||
options.TokenValidationParameters = new TokenValidationParameters
|
||||
{
|
||||
ValidateIssuer = true,
|
||||
ValidateAudience = true,
|
||||
ValidateLifetime = true,
|
||||
ValidateIssuerSigningKey = true,
|
||||
ValidIssuer = jwtIssuer,
|
||||
ValidAudience = jwtIssuer,
|
||||
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtKey))
|
||||
};
|
||||
});
|
||||
|
||||
builder.Services.AddDbContext<ApplicationContext>(options =>
|
||||
options.UseNpgsql("Host=localhost;Port=5438;Database=main_database;Username=postgres;Password=12345"));
|
||||
|
||||
builder.Services.AddControllers();
|
||||
builder.Services.AddFluentValidationAutoValidation();
|
||||
builder.Services.AddFluentValidationClientsideAdapters();
|
||||
builder.Services.AddValidatorsFromAssemblyContaining<LoginValidator>();
|
||||
builder.Services.AddValidatorsFromAssemblyContaining<RegisterValidator>();
|
||||
|
||||
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
|
||||
builder.Services.AddEndpointsApiExplorer();
|
||||
builder.Services.AddSwaggerGen();
|
||||
builder.Services.AddSwaggerGen(c =>
|
||||
{
|
||||
c.SwaggerDoc("v1", new Microsoft.OpenApi.Models.OpenApiInfo { Title = "Cloud API", Version = "v1" });
|
||||
|
||||
c.AddSecurityDefinition("Bearer", new Microsoft.OpenApi.Models.OpenApiSecurityScheme
|
||||
{
|
||||
Description = "Введите ваш Bearer токен",
|
||||
Name = "Authorization",
|
||||
In = Microsoft.OpenApi.Models.ParameterLocation.Header,
|
||||
Type = Microsoft.OpenApi.Models.SecuritySchemeType.ApiKey
|
||||
});
|
||||
|
||||
c.AddSecurityRequirement(new Microsoft.OpenApi.Models.OpenApiSecurityRequirement
|
||||
{
|
||||
{
|
||||
new Microsoft.OpenApi.Models.OpenApiSecurityScheme
|
||||
{
|
||||
Reference = new Microsoft.OpenApi.Models.OpenApiReference
|
||||
{
|
||||
Type = Microsoft.OpenApi.Models.ReferenceType.SecurityScheme,
|
||||
Id = "Bearer"
|
||||
}
|
||||
},
|
||||
new string[] {}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
var app = builder.Build();
|
||||
|
||||
@ -19,11 +75,17 @@ var app = builder.Build();
|
||||
if (app.Environment.IsDevelopment())
|
||||
{
|
||||
app.UseSwagger();
|
||||
app.UseSwaggerUI();
|
||||
app.UseSwaggerUI(c =>
|
||||
{
|
||||
c.SwaggerEndpoint("/swagger/v1/swagger.json", "Cloud API V1");
|
||||
c.RoutePrefix = string.Empty;
|
||||
});
|
||||
}
|
||||
|
||||
app.UseHttpsRedirection();
|
||||
|
||||
app.UseAuthentication();
|
||||
|
||||
app.UseAuthorization();
|
||||
|
||||
app.MapControllers();
|
||||
|
13
Cloud/Requests/LoginRequest.cs
Normal file
13
Cloud/Requests/LoginRequest.cs
Normal file
@ -0,0 +1,13 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Cloud.Requests;
|
||||
|
||||
public class LoginRequest
|
||||
{
|
||||
public string Email { get; set; }
|
||||
|
||||
public string Password { get; set; }
|
||||
}
|
15
Cloud/Requests/RegisterRequest.cs
Normal file
15
Cloud/Requests/RegisterRequest.cs
Normal file
@ -0,0 +1,15 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Cloud.Requests;
|
||||
|
||||
public class RegisterRequest
|
||||
{
|
||||
public string Name { get; set; }
|
||||
|
||||
public string Email { get; set; }
|
||||
|
||||
public string Password { get; set; }
|
||||
}
|
18
Cloud/Validation/LoginValidator.cs
Normal file
18
Cloud/Validation/LoginValidator.cs
Normal file
@ -0,0 +1,18 @@
|
||||
using Cloud.Requests;
|
||||
using FluentValidation;
|
||||
|
||||
namespace Cloud.Validation;
|
||||
|
||||
public class LoginValidator : AbstractValidator<LoginRequest>
|
||||
{
|
||||
public LoginValidator()
|
||||
{
|
||||
RuleFor(request => request.Email)
|
||||
.NotEmpty().WithMessage("Email обязателен для заполнения")
|
||||
.EmailAddress().WithMessage("Некорректный формат Email");
|
||||
|
||||
RuleFor(request => request.Password)
|
||||
.NotEmpty().WithMessage("Пароль обязателен для заполнения")
|
||||
.MinimumLength(8).WithMessage("Пароль должен быть не менее 8 символов");
|
||||
}
|
||||
}
|
22
Cloud/Validation/RegisterValidator.cs
Normal file
22
Cloud/Validation/RegisterValidator.cs
Normal file
@ -0,0 +1,22 @@
|
||||
using Cloud.Requests;
|
||||
using FluentValidation;
|
||||
|
||||
namespace Cloud.Validation;
|
||||
|
||||
public class RegisterValidator : AbstractValidator<RegisterRequest>
|
||||
{
|
||||
public RegisterValidator()
|
||||
{
|
||||
RuleFor(user => user.Name)
|
||||
.NotEmpty().WithMessage("Имя обязательно для заполнения")
|
||||
.MaximumLength(50).WithMessage("Имя должно быть не более 50 символов");
|
||||
|
||||
RuleFor(user => user.Email)
|
||||
.NotEmpty().WithMessage("Email обязателен для заполнения")
|
||||
.EmailAddress().WithMessage("Некорректный формат Email");
|
||||
|
||||
RuleFor(user => user.Password)
|
||||
.NotEmpty().WithMessage("Пароль обязателен для заполнения")
|
||||
.MinimumLength(8).WithMessage("Пароль должен быть не менее 8 символов");
|
||||
}
|
||||
}
|
@ -5,5 +5,9 @@
|
||||
"Microsoft.AspNetCore": "Warning"
|
||||
}
|
||||
},
|
||||
"AllowedHosts": "*"
|
||||
}
|
||||
"AllowedHosts": "*",
|
||||
"Jwt": {
|
||||
"Key": "m7TyhE20s0dVtUDAr9EnFdPZnAG8maxgBTaiW5j6kO6RQhWDAGxYmXyu0suDnE0o",
|
||||
"Issuer": "localhost"
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user