Код: Выделить всё
import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Router } from '@angular/router';
import { Observable } from 'rxjs';
@Injectable({
providedIn: 'root',
})
export class UrlService {
private apiCreateUrlUrl = 'https://localhost:7183/api/url/create';
constructor(private http: HttpClient) {}
create(urlData: { originalUrl: string }): Observable {
console.log(localStorage.getItem('authToken')) // console log prints auth token on screenshot below
const headers = new HttpHeaders({
'Content-Type': 'application/json',
'Authorization': localStorage.getItem('authToken') ?? ''
});
return this.http.post(this.apiCreateUrlUrl, urlData, { headers });
}
}
Код: Выделить всё
[ApiController]
[Route("api/url")]
public class UrlController : ControllerBase
{
private readonly IUrlService _urlService;
private readonly UserManager _userManager;
public UrlController(IUrlService shortUrlService, UserManager userManager)
{
_urlService = shortUrlService;
_userManager = userManager;
}
[Authorize]
[HttpPost("create")]
public async Task CreateShortUrl([FromBody] UrlDTO url)
{
var dddfd = Request;
var shortCode = Guid.NewGuid().ToString()[..6];
var a = await _userManager.GetUserAsync(User);
var newUrl = new UrlEntity
{
OriginalUrl = url.OriginalUrl,
ShortCode = $"https://short.ly/{shortCode}",
UserId = User.FindFirstValue(ClaimTypes.NameIdentifier),
};
await _urlService.CreateUrlAsync(newUrl);
return CreatedAtAction(nameof(GetShortUrl), url);
}
}

Я не могу понять, почему я получаю ответ 302 от сообщения, если JWT был представлен так же, как и в Swagger.
Дополнительная информация о Ядро ASP.NET MVC:
Мой секретный ключ: "f0cb5f06980e5be436a66caf5b74c1fe8792f51c7251885bcab19d8af06cf73b"
Program.cs:
Код: Выделить всё
using System.Security.Cryptography;
using System.Text;
using back.Data;
using back.Data.Models;
using back.Services.Authentication;
using back.Services.ShortUrl;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using Microsoft.IdentityModel.Tokens;
var CORS_POLICY = "MY_CORS";
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddScoped();
builder.Services.AddScoped();
builder.Services.AddCors(options =>
{
options.AddPolicy(name: CORS_POLICY, builder =>
{
builder
.WithOrigins("http://localhost:4200")
.AllowAnyHeader()
.AllowAnyMethod();
});
});
builder.Services.AddDbContext(options =>
options.UseNpgsql(builder.Configuration.GetConnectionString("DefaultConnection")
?? throw new ArgumentNullException("DefaultConnection")));
builder.Services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
ValidIssuer = "https://localhost:7183",
ValidAudience = "https://localhost:7183",
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(builder.Configuration.GetSection("Auth").GetValue("SecretKey")!))
};
});
builder.Services.AddAuthorization();
builder.Services
.AddIdentity(options =>
{
options.Password.RequireDigit = false;
options.Password.RequiredLength = 8;
options.Password.RequireNonAlphanumeric = false;
options.Password.RequireUppercase = false;
options.Password.RequireLowercase = false;
options.Password.RequiredUniqueChars = 0;
options.Lockout.MaxFailedAccessAttempts = 5;
options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(5);
options.Lockout.AllowedForNewUsers = true;
})
.AddEntityFrameworkStores()
.AddDefaultTokenProviders();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen(c =>
{
c.AddSecurityDefinition("Bearer", new Microsoft.OpenApi.Models.OpenApiSecurityScheme
{
Description = "JWT Authorization header using the Bearer scheme (Example: 'Bearer 12345abcdef')",
Name = "Authorization",
In = Microsoft.OpenApi.Models.ParameterLocation.Header,
Type = Microsoft.OpenApi.Models.SecuritySchemeType.ApiKey,
Scheme = "Bearer"
});
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[] {}
}
});
});
// Add services to the container.
builder.Services.AddControllersWithViews();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Home/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
else
{
app.UseSwagger();
app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint("/swagger/v1/swagger.json", "inforce-tech v1");
c.RoutePrefix = "swagger"; // Use "swagger" as the base path for UI access
});
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseCors(CORS_POLICY);
app.UseAuthentication();
app.UseAuthorization();
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}")
.RequireCors(CORS_POLICY);
app.Run();
Код: Выделить всё
public class AuthenticationService : IAuthenticationService
{
private readonly UserManager _userManager;
private readonly SignInManager _signInManager;
private readonly IConfiguration _configuration;
public AuthenticationService(UserManager userManager, SignInManager signInManager,
IConfiguration configuration)
{
_userManager = userManager;
_signInManager = signInManager;
_configuration = configuration;
}
// Log in user
public async Task LogInAsync(string username, string password)
{
if (string.IsNullOrWhiteSpace(username) || string.IsNullOrWhiteSpace(password))
{
throw new ArgumentException("Username and password are required.");
}
var user = await _userManager.FindByNameAsync(username) ?? throw new InvalidOperationException("User does not exist.");
var result = await _signInManager.PasswordSignInAsync(user, password, isPersistent: false, lockoutOnFailure: false);
if (!result.Succeeded)
{
throw new InvalidOperationException("Invalid login attempt.");
}
return result;
}
// Sign up user
public async Task SignUpAsync(UserEntity user, string password)
{
if (user == null || string.IsNullOrWhiteSpace(password))
{
throw new ArgumentException("User and password are required.");
}
var result = await _userManager.CreateAsync(user, password);
if (!result.Succeeded)
{
throw new InvalidOperationException(string.Join(", ", result.Errors.Select(e => e.Description)));
}
await _signInManager.SignInAsync(user, isPersistent: false);
return result;
}
public string GenerateJwtToken(string username)
{
var claims = new[]
{
new Claim(JwtRegisteredClaimNames.Sub, username),
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString())
};
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration.GetSection("Auth").GetValue("SecretKey")!));
var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
var token = new JwtSecurityToken(
issuer: "https://localhost:7183",
audience: "https://localhost:7183",
claims: claims,
expires: DateTime.Now.AddMinutes(30),
signingCredentials: creds
);
return new JwtSecurityTokenHandler().WriteToken(token);
}
}

Я также пытался добавить в заголовок "Авторизация" "Носитель" ключевое слово:
Код: Выделить всё
@Injectable({
providedIn: 'root',
})
export class UrlService {
private apiCreateUrlUrl = 'https://localhost:7183/api/url/create';
constructor(private http: HttpClient) {}
create(urlData: { originalUrl: string }): Observable {
console.log(localStorage.getItem('authToken'))
const headers = new HttpHeaders({
'Content-Type': 'application/json',
'Authorization': `Bearer ${localStorage.getItem('authToken') ?? ''}`
});
return this.http.post(this.apiCreateUrlUrl, urlData, { headers });
}
}
Подробнее здесь: https://stackoverflow.com/questions/792 ... th-angular
Мобильная версия