[ASP.NET Core MVC] 8-10. 회원가입, 로그인 기능 구현 정리

BruteForceA·2022년 6월 28일
2
post-thumbnail

개발환경

  • Visual Studio Community 2017
  • ASP.NET Core 2.2



로그인 2가지 방법론

기본적으로 HTTP 프로토콜 환경은 비연결성(Connectionless), 무상태(Stateless) 특성을 가지고 있기 때문에 서버에서 클라이언트의 사용자를 매번 확인해야 한다. 이러한 특성을 보완하기 위해 쿠키와 세션을 사용하게 되었다.



1. Session

  • 세션은 쿠키를 기반하고 있지만, 사용자 정보 파일을 브라우저에 저장하는 쿠키와 달리 세션은 서버 측에서 관리
  • 보안성 높지만 웹서버 메모리 부하 높아짐.

  • 웹 서버 로그인 -> 사용자 정보 -> 브라우저 전달
  • 쿠키는 클라이언트(브라우저) 로컬에 저장되는 키와 값이 들어있는 작은 데이터 파일
  • 클라이언트 컴퓨터에 저장
  • 웹 서버의 부하가 낮아지지만 보안성이 낮음

그림출처



  • Cookie -> 암호화 -> 복호화 / 위변조의 위험
  • SSL
  • 세션은 서버의 메모리가 감당할 수 없어질 수가 있고 속도가 느려질 수 있기 때문에 쿠키가 유리한 경우가 있습니다.
  • 최근에는 이런 문제들을 보완한 토큰 기반의 인증방식을 사용하는 추세 ex) JWTR



회원가입 기능 만들기

Model


namespace AspnetNote.MVC6.Models
{
    public class User
    {
        /// <summary>
        /// 사용자번호
        /// </summary>
        [Key] // PK 설정
        public int UserNo { get; set; }

        /// <summary>
        /// 사용자 이름
        /// </summary>
        [Required(ErrorMessage ="사용자 이름을 입력하세요.")] // Not Null 설정
        public string UserName { get; set; }

        /// <summary>
        /// 사용자 ID
        /// </summary>
         [Required(ErrorMessage = "사용자 아이디를 입력하세요.")] // Not Null 설정
        public string UserId { get; set; }

        /// <summary>
        /// 사용자 비밀번호
        /// </summary>
         [Required(ErrorMessage = "사용자 비밀번호를 입력하세요.")] // Not Null 설정
        public string UserPassword { get; set; }

    }
}



View

Index.cshtml

Register.cshtml

<!-- asp-for가 참조할 위치를 지정해준다. -->
@model AspnetNote.MVC6.Models.User 

<h2>회원가입</h2>

<!-- 폼을 Account 컨트롤러 Register 메서드로 넘겨준다. -->
<form class="form-horizontal" method="post" asp-controller="Account" asp-action="Register">
    <div class="form-group">
        <label> 사용자 ID</label> <!-- Models의 User의 UserId에 매칭시켜 값을 넘겨준다. -->
        <input type="text" class="form-control" asp-for="UserId" placeholder="사용자 ID 입력" />
        <!-- span 태그를 이용해 asp-validation-for 를 이용하면 값을 넣지 않을경우 경고문이 뜬다. -->
        <span class="text-danger" asp-validation-for="UserId"></span>
    </div>


    <div class="form-group">
        <label> 사용자 비밀번호</label>
        <input type="password" class="form-control" asp-for="UserPassword" placeholder="사용자 비밀번호 입력" />
        <span class="text-danger" asp-validation-for="UserPassword" ></span>
    </div>

    <div class="form-group">
        <label> 사용자 이름</label>
        <input type="text" class="form-control" asp-for="UserName" placeholder="사용자 이름 입력" />
        <span class="text-danger" asp-validation-for="UserName" ></span>
    </div>

    <div class="form-group">
        <button type="submit" class="btn btn-primary">회원가입</button>
        <a class="btn btn-warning" href="#">취소</a>
    </div>
</form>




Controller

 namespace AspnetNote.MVC6.Controllers
{
    public class AccountController : Controller
    {
        

        /// <summary>
        /// 회원가입
        /// </summary>
        /// <returns></returns>
        public IActionResult Register()
        {
            return View();
        }

        [HttpPost]
        public IActionResult Register(User model)
        {	//  IsValid : 모든값 입력 받았는지 검증 ID, 비밀번호 필수로 적어야 한다.
            // [Required] 어노테이션을 기준으로 판단한다. 
            if (ModelState.IsValid) 
            {	
             /* using문을 사용하여 DB 오픈 커넥션 후 자동으로 닫게 해준다. */
                using (var db = new AspnetNoteDbContext())
                {
                    db.Users.Add(model); // 메모리상에 올라감
                    db.SaveChanges(); // 메모리 -> DB에 저장
                }
                return RedirectToAction("Index", "Home");
            }
            return View(model);
        }
    }
}





GET? POST?

GET

GET method는 클라이언트에서 서버로 정보를 요청하기위해 사용되는 메서드 입니다.

  • 데이터 읽기(Read), 검색(Retrieve) 할때 사용되는 method
  • URL 주소 끝에 파라미터로 포함되어 전송되며, 이 부분을 쿼리 스트링(QueryString) 이라고 부른다.

POST

POST method는 리소스를 생성/업데이트 하기위해 서버에 데이터를 보내는 데 사용된다.

  • 전송해야될 데이터를 HTTP Body에 담아서 전송한다.
  • HTTP Body 길이의 제한이 없기 때문에 GET과 달리 대용량 데이터를 전송할 수 있다.

업로드중..그림출처



로그인 기능 만들기

ViewModel

namespace AspnetNote.MVC6.ViewModel
{ 	/* View를 위한 모델 작성 */
    public class LoginViewModel
    {
        // 로그인 할때만 사용할 View  모델
        [Required(ErrorMessage ="사용자 ID를 입력해주세요")]
        public string UserId{get; set;}

        [Required(ErrorMessage = "사용자 비밀번호를 입력해주세요")]
        public string UserPassword { get; set; }
    }
}



View

@model AspnetNote.MVC6.ViewModel.LoginViewModel

<h2>로그인</h2>

<form class="form-horizontal" method="post" asp-controller="Account" asp-action="Login">
<!-- asp-validation-summary=”ModelOnly”  :  전역적인 경고 메세지를 위해 사용한다.-->
<!-- 개별적으로 체크한 후 문제가 없으면 전역적인 체크를 하고 문제가 있으면 경고를 띄워준다. -->
    <div class="text-danger" asp-validation-summary="ModelOnly"></div>
    <div class="form-group">
        <label>사용자 ID</label>
        <input type="text" asp-for="UserId" class="form-control" placeholder="사용자 아이디 입력" />
        <span class="text-danger" asp-validation-for="UserId"></span>
    </div>

    <div class="form-group">
        <label>사용자 비밀번호</label>
        <input type="password" asp-for="UserPassword" class="form-control" placeholder="비밀번호 입력" />
        <span class="text-danger" asp-validation-for="UserPassword"></span>
    </div>

    <div class="form-group">
       <button type="submit"  class="btn btn-success">로그인</button>
    </div>
</form>



Controller

    public class AccountController : Controller
    {
        /// <summary>
        /// 로그인 페이지 이동
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        public IActionResult Login()
        {
            return View();
        }
		
        /* 로그인 */
        [HttpPost]
        public IActionResult Login(LoginViewModel model)
        {
            //  IsValid : 모든값 입력 받았는지 검증 ID, 비밀번호 필수로 적어야 한다.
            // [Required] 어노테이션을 기준으로 판단한다. 
            if (ModelState.IsValid)
            {
                // DB 오픈 커넥션 후 자동으로 닫음
                using (var db = new AspnetNoteDbContext())
                {
                    // Linq - 메서드 체이닝 (=> : A Go to B )
                    // 입력받은 아이디 와 Db 값 비교
                    // FirstOrDefault() : 첫 번째 입력값 출력하겠다.  ()안에 원하는 값 넣어서 찾을 수 있다.
                    // 비교할때 == 를 사용하면 메모리누수가 발생하기 때문에 Equals를 사용한다.
                    //var user = db.Users.FirstOrDefault(u=> u.UserId == model.UserId && u.UserPassword == model.UserPassword); 
                    var user = db.Users.FirstOrDefault(u => u.UserId.Equals(model.UserId) && u.UserPassword.Equals(model.UserPassword)); // 아이디 비밀번호 매칭
                    
                    /* 로그인 성공 */
                    if (user != null)
                    { 
                     	/* HttpContext.Session.SetInt32(key, value); */
                        /* "USER_LOGIN_KEY"라는 이름으로 Session에 담는다. */
                    	HttpContext.Session.SetInt32("USER_LOGIN_KEY", user.UserNo);
                        return RedirectToAction("LoginSuccess", "Home");
                    } 
        
                }
                // 로그인 실패,  사용자 ID 자체가 회원가입 X 경우
                ModelState.AddModelError(string.Empty, "사용자 ID 혹은 비밀번호가 올바르지 않습니다.");

            }
            return View(model);
        }
    }
}



실행화면




참조

0개의 댓글