재우니의 블로그

 

 

ASP.NET Core Identity를 사용한 비밀번호 해싱, CSRF 보호, 처리를 위해 form data 를 JSON 형식으로 전송하여 전송 중 비밀번호를 보호하는 코드 샘플이 포함된 예제입니다.

 

 

1단계: ASP.NET Core Identity 및 HTTPS 구성하기

 

Startup.cs 파일에서 ASP.NET Core Identity를 구성하고 보안 통신을 위해 HTTPS를 사용하도록 설정합니다.

public void ConfigureServices(IServiceCollection services)
{
    // ...

    services.AddIdentity<ApplicationUser, IdentityRole>()
        .AddEntityFrameworkStores<ApplicationDbContext>()
        .AddDefaultTokenProviders();

    services.Configure<IdentityOptions>(options =>
    {
        options.Password.RequireDigit = true;
        options.Password.RequireLowercase = true;
        options.Password.RequireUppercase = true;
        options.Password.RequireNonAlphanumeric = true;
        options.Password.RequiredLength = 8;
    });

    // ...

    services.AddControllersWithViews(options =>
    {
        options.Filters.Add(new RequireHttpsAttribute());
    })
    .AddJsonOptions(options =>
    {
        options.JsonSerializerOptions.PropertyNamingPolicy = null;
    });

    // ...
}

 

 

2단계: CSRF 보호를 사용하여 등록 action 및  view 만들기


CSRF 보호를 사용하여 사용자 등록에 필요한  action 및 view 를 만듭니다.

[FromBody] 속성을 JObject 매개변수와 함께 사용하여 프레임워크에 JSON 데이터를 JObject 객체에 바인딩하도록 지시합니다. 그런 다음 ToObject<T> 메서드를 사용하여 JObject를 RegisterViewModel 객체로 수동으로 변환할 수 있습니다.

 

public class AccountController : Controller
{
    private readonly UserManager<ApplicationUser> _userManager;
    private readonly SignInManager<ApplicationUser> _signInManager;
    private readonly IAntiforgery _antiforgery;

    public AccountController(UserManager<ApplicationUser> userManager, SignInManager<ApplicationUser> signInManager, IAntiforgery antiforgery)
    {
        _userManager = userManager;
        _signInManager = signInManager;
        _antiforgery = antiforgery;
    }

    [HttpGet]
    public IActionResult Register()
    {
        var tokens = _antiforgery.GetAndStoreTokens(HttpContext);
        ViewBag.AntiforgeryToken = tokens.RequestToken;

        return View();
    }

    
    [HttpPost]
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> Register([FromBody] JObject data)
    {
        if (ModelState.IsValid)
        {
            var model = data.ToObject<RegisterViewModel>();

            var user = new ApplicationUser
            {
                UserName = model.Username
            };

            var result = await _userManager.CreateAsync(user, model.Password);

            if (result.Succeeded)
            {
                await _signInManager.SignInAsync(user, isPersistent: false);
                return RedirectToAction("Index", "Home");
            }

            foreach (var error in result.Errors)
            {
                ModelState.AddModelError(string.Empty, error.Description);
            }
        }

        return BadRequest(ModelState);
    }

}

 

이렇게 변경하면 JSON 데이터가 RegisterViewModel 개체에 올바르게 바인딩되어 등록 작업에서 사용자 이름과 비밀번호에 액세스할 수 있습니다.

@model RegisterViewModel

<form id="registerForm" asp-action="Register" asp-controller="Account">
    <div id="registerError" class="alert alert-danger" style="display: none;"></div>

    @Html.AntiForgeryToken()

    <div class="form-group">
        <label for="username">Username:</label>
        <input type="text" class="form-control" id="username" name="Username" required />
    </div>

    <div class="form-group">
        <label for="password">Password:</label>
        <input type="password" class="form-control" id="password" name="Password" required />
    </div>

    <div class="form-group">
        <label for="confirmPassword">Confirm Password:</label>
        <input type="password" class="form-control" id="confirmPassword" name="ConfirmPassword" required />
    </div>

    <button type="submit" class="btn btn-primary">Register</button>
</form>

<script>
    $(function () {
        $("#registerForm").submit(function (e) {
            e.preventDefault();

            var form = $(this);
            var url = form.attr("action");
            var data = JSON.stringify(form.serializeArray());

            $.ajax({
                url: url,
                type: "POST",
                data: data,
                headers: {
                    "RequestVerificationToken": $('input[name="__RequestVerificationToken"]').val(),
                    "Content-Type": "application/json"
                },
                success: function (response) {
                    // Handle success response
                },
                error: function (xhr) {
                    // Handle error response
                    $("#registerError").text(xhr.responseText).show();
                }
            });
        });
    });
</script>

 

 

이 예제에서는 ASP.NET Core Identity를 사용한 비밀번호 해싱, IAntiforgery 서비스를 사용한 CSRF 보호, HTTPS 통신 적용을 포함했습니다. 이제 등록 작업은 위조 방지 토큰을 생성하고 저장한 다음 @Html.AntiForgeryToken() 헬퍼 메서드를 사용하여 등록 form 에 포함합니다.

form 에 submit 을 위한 AJAX 요청은 CSRF 보호를 위해 request headers(요청 헤더)에 CSRF protection(위변조 방지 토큰) 을 포함합니다. form data 는 form.serializeArray()를 사용하여 serialize 되고, Content-Type 헤더는 application/json 으로 설정하며, JSON.stringify()를 사용하여 데이터를 JSON으로 변환해서 JSON 형식으로 전송됩니다.