Добавление аутентификации в конечную точку api - ASP. Net Core - PullRequest
0 голосов
/ 07 мая 2020

Я создал собственный сайт с кодом ASP. NET Core и React. Я получаю код basi c для создания бэкэнда ASP с аутентификацией из этого https://jasonwatmore.com/post/2019/10/14/aspnet-core-3-simple-api-for-authentication-registration-and-user-management#running -react

Я создал конечную точку для своего API, которая позволяет добавлять фото в мои server, и он работает

 [HttpPost("{username}/photos/")]
        public IActionResult AddPhoto(String username, [FromForm]IFormFile photo)
        {

            //add img to static folder
            var wwww_root = _webHostEnvironment.WebRootPath;
            var path = @"\profiles\" + username + @"\profile_photos\";
            var upload_path = wwww_root + path;

            var pathForFile = upload_path + photo.FileName;

            try
            {
                using (FileStream fileStream = System.IO.File.Create(pathForFile))
                {
                    photo.CopyTo(fileStream);
                    fileStream.Flush();
                }
            }
            catch(DirectoryNotFoundException e)
            {
                return NotFound("This username does not exists");
            }
            var pathOnServer = "http://" + Request.Host.Value + path + photo.FileName;
            var photoImage = _profileService.AddPhoto(username, pathOnServer);

            return Ok();

        }

, но я хочу также добавить аутентификацию для использования этой конечной точки на основе заданного «имени пользователя», т.е. эта конечная точка возвращает OK, когда токен носителя совпадает с токеном, назначенным имени пользователя.

В данной ссылке я нашел метод настройки аутентификации:

        public void ConfigureServices(IServiceCollection services)
        {
            // use sql server db in production and sqlite db in development
            if (_env.IsProduction())
                services.AddDbContext<DataContext>();
            else
                services.AddDbContext<DataContext, SqliteDataContext>();

            services.AddCors();
            services.AddControllers();
            services.AddAutoMapper(AppDomain.CurrentDomain.GetAssemblies());

            // configure strongly typed settings objects
            var appSettingsSection = _configuration.GetSection("AppSettings");
            services.Configure<AppSettings>(appSettingsSection);

            // configure jwt authentication
            var appSettings = appSettingsSection.Get<AppSettings>();
            var key = Encoding.ASCII.GetBytes(appSettings.Secret);
            services.AddAuthentication(x =>
            {
                x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
            })
            .AddJwtBearer(x =>
            {
                x.Events = new JwtBearerEvents
                {
                    OnTokenValidated = context =>
                    {
                        var userService = context.HttpContext.RequestServices.GetRequiredService<IUserService>();
                        var userId = int.Parse(context.Principal.Identity.Name);
                        var user = userService.GetById(userId);
                        if (user == null)
                        {
                            // return unauthorized if user no longer exists
                            context.Fail("Unauthorized");
                        }
                        return Task.CompletedTask;
                    }
                };
                x.RequireHttpsMetadata = false;
                x.SaveToken = true;
                x.TokenValidationParameters = new TokenValidationParameters
                {
                    ValidateIssuerSigningKey = true,
                    IssuerSigningKey = new SymmetricSecurityKey(key),
                    ValidateIssuer = false,
                    ValidateAudience = false
                };
            });

И конечная точка api для аутентификации:

        [AllowAnonymous]
        [HttpPost("authenticate")]
        public IActionResult Authenticate([FromBody]AuthenticateModel model)
        {
            var user = _userService.Authenticate(model.Username, model.Password);

            if (user == null)
                return BadRequest(new { message = "Username or password is incorrect" });

            var tokenHandler = new JwtSecurityTokenHandler();
            var key = Encoding.ASCII.GetBytes(_appSettings.Secret);
            var tokenDescriptor = new SecurityTokenDescriptor
            {
                Subject = new ClaimsIdentity(new Claim[]
                {
                    new Claim(ClaimTypes.Name, user.Id.ToString())
                }),
                Expires = DateTime.UtcNow.AddDays(7),
                SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
            };
            var token = tokenHandler.CreateToken(tokenDescriptor);
            var tokenString = tokenHandler.WriteToken(token);

            // return basic user info and authentication token
            return Ok(new
            {
                Id = user.Id,
                Username = user.Username,
                FirstName = user.FirstName,
                LastName = user.LastName,
                Token = tokenString
            });
        }

, но я не могу перевести это на решение моей проблемы. Прошу совета, как это сделать

1 Ответ

0 голосов
/ 07 мая 2020

РЕДАКТИРОВАТЬ 1
Вы можете проверить утверждения и токен в своем методе загрузки
Добавьте в ConfigureService это

services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();

В методе загрузки используйте это:

// works if the token is in the header
var tokenFromHeader = HttpContext.Request.Headers["Authorization"];
// or try this if .Net Core is < 3.0
var tokenFromAuth = await HttpContext.Authentication.GetTokenAsync("access_token");

// Get Claims
var identity = HttpContext.User.Identity as ClaimsIdentity;

// Get user id from claims.
var userIdClaim = identity.Claims.FirstOrDefault(x => x.Type == ClaimTypes.Name);

// Use the value.
if (userIdClaim != null && userIdClaim.value != null) {
   // your logic here
}

Чтобы проверить авторизацию при вызове API, установите атрибут [Authorize] на вашем контроллере или в вашем методе.

[Authorize]
[HttpPost("{username}/photos/")]
public IActionResult AddPhoto(String username, [FromForm]IFormFile photo)

Подробнее здесь: https://docs.microsoft.com/en-us/aspnet/core/security/authentication/?view=aspnetcore-3.1

Основной c код: Startup.cs -> ConfigureServices

            // configure jwt authentication
            var jwtSettings = jwtSettingsSection.Get<JwtSettings>();
            var key = Encoding.ASCII.GetBytes(jwtSettings.JwtKey);
            services.AddAuthentication(x =>
            {
                x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
            })
            .AddJwtBearer(x =>
            {
                x.RequireHttpsMetadata = false;
                x.SaveToken = true;
                x.TokenValidationParameters = new TokenValidationParameters
                {

                    ValidateIssuerSigningKey = true,
                    IssuerSigningKey = new SymmetricSecurityKey(key),

                    ValidateIssuer = true,
                    ValidIssuer = jwtSettings.JwtIssuer,

                    ValidateAudience = true,
                    ValidAudience = jwtSettings.JwtAudience,

                    //RequireExpirationTime = false,
                    ValidateLifetime = true,
                    ClockSkew = TimeSpan.Zero
                };
            });

Startup.cs -> Настроить

app.UseAuthentication();
app.UseAuthorization();

Контроллер аутентификации

        [AllowAnonymous]
        [HttpPost()]
        public async Task<IActionResult> AuthenticateUser([FromBody] UserAuthentication userResource)
        {
            //Your logic of authorization here
            //if not authorized
            //return Unauthorized();

            var tokenString = CreateJwtToken(user);

            // return basic user info (without password) and token to store client side
            return Ok(new
            {
                Token = tokenString
            });
        }

Создать токен JWT

public string CreateJwtToken(McUsers user)
{
    var key = Encoding.ASCII.GetBytes(jwtSettings.JwtKey);
    var tokenDescriptor = new SecurityTokenDescriptor
    {
        Issuer = jwtSettings.JwtIssuer,
        Audience = jwtSettings.JwtAudience,
        Subject = new ClaimsIdentity(new Claim[]
       {
            new Claim(ClaimTypes.NameIdentifier, user.Id.ToString()),
            new Claim(ClaimTypes.Name, user.UserName),
            new Claim(ClaimTypes.GivenName, user.FirstName),
            new Claim(ClaimTypes.Surname, user.LastName),
            new Claim(ClaimTypes.Role, user.UserRole.Description)
       }),
        NotBefore = DateTime.UtcNow,
        Expires = DateTime.UtcNow.AddMinutes(120),
        SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha512Signature)
    };

    var tokenHandler = new JwtSecurityTokenHandler();
    var token = tokenHandler.CreateToken(tokenDescriptor);
    var tokenString = tokenHandler.WriteToken(token);

    return tokenString;
}

Ваш метод в контроллере

    [Authorize]
    [HttpPost("{username}/photos/")]
    public IActionResult AddPhoto(String username, [FromForm]IFormFile photo)
    {

        //add img to static folder
        var wwww_root = _webHostEnvironment.WebRootPath;
        var path = @"\profiles\" + username + @"\profile_photos\";
        var upload_path = wwww_root + path;

        var pathForFile = upload_path + photo.FileName;

        try
        {
            using (FileStream fileStream = System.IO.File.Create(pathForFile))
            {
                photo.CopyTo(fileStream);
                fileStream.Flush();
            }
        }
        catch(DirectoryNotFoundException e)
        {
            return NotFound("This username does not exists");
        }
        var pathOnServer = "http://" + Request.Host.Value + path + photo.FileName;
        var photoImage = _profileService.AddPhoto(username, pathOnServer);

        return Ok();

    }
...