Programming/.NET

 1. 인증

 

웹사이트에서 사용하는 대부분의 인증은 Form인증방식입니다. 사이트 자체에서 사용자의 정보를 확인하고 인증을 처리해 주는 방식입니다. 이 방식의 인증을 활용하기 위해서는 우선 web.config의 <system.web>하위에 다음과 같이 인증방식을 설정합니다.

 

<authentication mode="Forms"/>

 

필요에 따라 <forms> 요소를 통해 인증과 관련된 여러가지 설정사항을 등록할 수 있습니다.

 

<authentication mode="Forms">
  <forms name="_auth_" loginUrl="login.aspx" protection="All" timeout="30" requireSSL="false" 

slidingExpiration="true" cookieless="AutoDetect"></forms>
</authentication>

 

ASP.NET은 인증이 완료되면 사용자에게 특정 쿠키값을 제공하는데 name은 이 쿠기값의 이름을 의미합니다. 이름의 기본값은 .ASPXAUTH입니다.

 

사용자가 인증이 필요한 페이지에 접속을 시도하거나 로그인을 시도하는 경우 보여줄 로그인을 페이지는 loginUrl로 지정합니다.

 

인증이 완료되고 나면 쿠키값을 받게 되는데 이때 쿠키의 보호수준을 protection으로 지정합니다. 기본으로 적용되는 All은 쿠키의 암호화와 유효성을 확인하는 옵션이며 Encryption은 암호화만 수행할뿐 유효성검사는 수행하지 않습니다. 반면 Validation은 암호화를 수행하지 않지만 유효성은 확인하며 None은 쿠키보호에 대한 어떤 작업도 하지 않습니다. All값을 권장합니다.

 

쿠키만료시간은 timeout으로 설정합니다. 단위는 '분'이며 기본은 30분입니다.

 

로그인시도시 관련 사용자정보를 전송할때 SSL통신이 필요한지를 requireSSL로 지정합니다.

 

timeout이 30으로 설정되어 있다면 사용자가 로그인을 하고 난 후 아무런 작업도 하지 않은채 30분이 경과할시 쿠키는 만료됩니다.(로그아웃처리) 만약 30분이 되기 전에 어떤 작업이라도 수행해서 웹서버로부터 HTTP통신을 한다면 이 시간은 자동으로 갱신되 다시 30분주기를 갖게 됩니다. 그런데 만일 slidingExpiration을 false로 설정하면 최초로그인부터 쿠키만료시간은 30분간격으로 일정하게 유지됩니다. 사용자가 중간에 어떤 작업을 하더라도 이 시간은 갱신되지 않으며 30분이 지나면 쿠키는 만료될 것입니다.

 

쿠키는 다양한 방법으로 처리될 수 있습니다. cookieless를 UseUri로 하면 URL을 통해 처리되며 UseDeviceProfile은 사용자 웹브라우저 상황을 판단하여 쿠키를 사용할지 결정하게 됩니다. UseCookies는 항상 쿠키를 사용하여 인증처리하도록 하고 AutoDetect는 쿠키전달을 UseUri로 할지 UseCookies로 할지 자동으로 판단합니다.

 

참고로 UseUri는 일단 먼저 쿠키에 값을 저장하고 해당 값을 Url을 통해 전달하는 방식입니다.(쿠키를 사용하지 않는게 아닙니다.)

 

인증에 필요한 설정에서 mode값은 Forms이외에 다음과 같은 값을 가질 수도 있습니다.

 

<authentication mode="Windows"></authentication>

 

Windows는 윈도우서버상에서 사용자를 생성하고 해당 사용자에 대한 접근처리를 수행하는 인증방식입니다. Passport는 장담하건데 쓸일이 없으므로 넘어가도 좋습니다. 그외 None값이 있으며 이는 인증모드를 사용하지 않음을 의미합니다.

 

사용자가 소수로 제한되어 있다면 Web.config의 forms요소 하위에 인증할 수 있는 사용자를 특정할 수도 있습니다.

 

<forms name="_auth_" loginUrl="login.aspx" protection="All" timeout="30" requireSSL="false" slidingExpiration="true" cookieless="AutoDetect">
    <credentials passwordFormat="Clear">
      <user name="cliel" password="12345"/>
    </credentials>
  </forms>

 

credentials 요소에는 passwordFormat 속성으로 암호화 방식을 지정하며 Clear값은 일반 텍스트로 암호를 비교할 것임을 의미합니다. 만일 암호화 형식을 바꾸면 암호도 그에 맞게 지정되어야 합니다.

 

<credentials passwordFormat="SHA1">
  <user name="cliel" password="A6H0A6H70AYT7HTYH359HWNPBWPEJBSJN5IJ6"/>
</credentials>

 

그러나 실제 일반텍스트에서 암호로 변한 문자가 어떻게 될지는 모를일인데 이런 경우 HashPasswordForStringInConfigFile 메소드로 암호를 확인하고 설정하시면 됩니다.

 

string password = FormsAuthentication.HashPasswordForStoringInConfigFile("12345", "SHA1");

 

이렇게 설정한 사용자의 유효성 확인은 '3.로그인' 에서 다시 살펴보겠습니다.

 

참고로 사용자 인증후에는 User개체를 통해 인증과 관련된 몇가지 정보를 조회할 수 있습니다. 사용가능한 항목은 아래 표를 참고해 주십시오.

 

 AuthenticationType

 사용자의 인증타입을 가져옵니다. Basic, NTLM, Forms, Passport 등이 있습니다.

 IsAuthenticated

 현재 사용자가 인증된 상태인지를 확인합니다.

 Name

 사용자의 아이디(이름)을 가져옵니다. 윈도우 인증이라면 도메인명도 같이 가져오게 됩니다.

 

 2. 접근제어

 

웹 사이트의 특정 페이지가 인증된 사용자만이 접근할 수 있는 페이지라면 해당 페이지에 익명사용자는 거부되고 인증된 사용자만이 접근할 수 있도록 설정해야할 필요가 있을 것입니다.

 

이를 위해서는 우선 접근제어가 필요한 웹페이지와 같은 위치에 web.config를 생성하고 <authorization>요소와 <deny>요소를 이용해 익명사용자를 거부하도록 합니다.

 

<?xml version="1.0"?>
<configuration>
    <system.web>
      <authorization>
        <deny users="?"/>
      </authorization>
    </system.web>
</configuration>

 

users에 ?를 설정하는건 인증되지 않은 모든 사용자(익명사용자)를 의미합니다. 또한 특정한 페이지를 따로 지정하지 않는다면 해당 경로(위 설정이 적용된 web.config가 존재하는)에 있는 모든 페이지가 영향을 받게 됩니다. 만약 같은 위치에 익명사용자에 대한 접근거부 페이지와 접근허용페이지가 혼재하는 경우에는 거부되어야할 페이지를 다음과 같이 명시해야 합니다.

 

참고로 이러한 개념은 allow의 경우에도 마찬가지 입니다.

 

<?xml version="1.0"?>
<configuration>
  <system.web>
    <authorization>
      <deny roles="mygroup"/>
    </authorization>
  </system.web>
</configuration>

 

roles는 특정 Group에 대한 접근이나 거부를 설정하고자 할때 사용합니다. Form인증의 경우 역활을, Windows인증의 경우 생성된 그룹명을 여기에 지정할 수 있습니다.

 

<?xml version="1.0"?>
<configuration>
  <system.web>
    <authorization>
      <deny verbs="GET"/>
    </authorization>
  </system.web>
</configuration>

 

verbs는 HTTP요청에 대한 접근제어를 설정하는 것입니다. 위 예제처럼 하면 HTTP의 GET요청은 거부될 것입니다.

 

<?xml version="1.0"?>
<configuration>
  <location path="WebForm.aspx">
    <system.web>
      <authorization>
        <deny users="?"/>
      </authorization>
    </system.web>
  </location>
</configuration>

 

익명 사용자가 WebForm.aspx에 접근을 시도하면 HTTP 404에러가 표시될 것입니다. 특정 사용자에 대한 거부라면

 

<?xml version="1.0"?>
<configuration>
  <location path="WebForm.aspx">
    <system.web>
      <authorization>
        <deny users="username"/>
      </authorization>
    </system.web>
  </location>
</configuration>

 

처럼 사용자명을 지정해 주면 됩니다. 윈도우인증인 경우 '도메인/사용자명'형식으로 지정합니다.

 

접근거부에 대한 결과인데 이를 좀더 자연스럽게 처리하려면 login페이지를 따로 만들고 프로젝트의 web.config <form>요소에 loginUrl속성으로 지정합니다.

 

<authentication mode="Forms">
  <forms loginUrl="login.aspx"></forms>
</authentication>

 

그러면 익명사용자가 인증이 필요한 페이지에 접근할때 기존 에러페이지를 표시하는대신 login.aspx로 이동하게될 것입니다. forms에는 name속성도 지정할 수 있는데 일반적으로 사용자를 식별하기 위한 쿠키이름을 지정합니다. 이름을 지정하지 않으면 .ASPXAUTH라는 이름이 사용됩니다.

 

 3. 로그인

 

익명사용자를 인증사용자로 전환하기 위해서는 로그인과정을 거쳐야 하는데 이를 위해 다음과 같이 Login컨트롤을 페이지에 배치합니다.

 

<form id="form1" runat="server">
<div>
    <asp:Login ID="Login1" runat="server"></asp:Login>
</div>
</form>

 

이걸로 로그인을 위한 준비는 끝났습니다. 하지만 사용자가 존재해야 해당 사용자가 로그인을 할텐데 사용자 생성에 관해서는 아래 글을 참고해 주시기 바랍니다.

 

2016/03/21 - [Programming/ASP.NET] - [ASP.NET] CreateUserWizard와 관련API


이 글은 위 글의 연장선에 있으며 이미 생성된 사용자(anchor37)가 있다고 가정합니다.

 

로그인 컨트롤은 기본적으로 Remember me next time. 체크 박스를 표시하는데 RememberMeText 속성을 원하는 내용으로 설정하면 Remember me next time.를 설정내용으로 바꿀 수 있으며 DisplayRememberMe속성을 false로 하면 아예 이 체크박스가 표시되지 않습니다.


또한 RememberMeSet 속성을 true로 하면 로그인할때 로그인정보를 클라이언트의 쿠키에 담도록 하며 이때 DisplayRememberMe속성을 true로 하면 자동으로 체크박스가 선택된 상태로 표시되지만 false로 하면 사용자가 체크여부를 선택할 수 없으므로 무조건 로그인정보가 쿠키로 저장됩니다.


따라서 별도의 로그아웃을 거지치 않으면 해당 사용자의 로그인은 계속 유지되므로 주의가 필요합니다.

 

사용자가 로그인을 시도할때 계정이 없는 경우 계정을 만들도록 유도하기 위해서는 CreateUserText와 CreateUserUrl속성을 사용합니다.

<asp:Login ID="Login1" runat="server" CreateUserText="회원가입" CreateUserUrl="~/Default.aspx"></asp:Login>

 

마찬가지로 암호를 찾기위한 경우는 PasswordRecoveryText와 PasswordRecoveryUrl속성을, 도움말 표시를 위해서는 HelpPageText, HelpPageUrl 속성을 사용합니다.

 

로그인 컨트롤을 사용하지 않는 경우나 직접 로그인처리를 해야하는 경우라면 FormsAuthentication클래스의 RedirectFromLoginPage메소드를 사용합니다.

 

FormsAuthentication.RedirectFromLoginPage("anchor37", false);

 

이 메소드의 첫번째 인수는 사용자 ID이며 두번째 인수는 해당 사용자의 쿠키를 영구생성할지를 지정합니다. 하지만 이 경우에도 사용자에 대한 정보를 확인하고 해당 사용자가 맞는지에 대한 인증을 거칠 필요가 있는데 이때는 Membership클래스의 ValidateUser메소드를 사용하면 됩니다.

 

if (Membership.ValidateUser("anchor37", "12356"))

                 FormsAuthentication.RedirectFromLoginPage("anchor37", false);

 

ValidateUser메소드는 사용자의 아이디와 비밀번호를 파라메터로 받고 결과를 bool값으로 반환합니다. 만약 Web.config에서 credentials요소를 통해 사용자를 특정한 상태라면 해당 사용자에 대한 유효여부는 Authenticate메소드로 처리할 수 있습니다.

 

if (FormsAuthentication.Authenticate("username", "password"))
                FormsAuthentication.RedirectFromLoginPage("anchor37", false);

 

위 예제에서 처럼 ASP.NET 에서 Form인증과 관련된 대부분의 API처리는 FormsAuthentiation 클래스를 사용하고 있습니다. 예제에서 사용된 메소드나 속성이외에도 FormsAuthentiation 클래스는 다음과 같은 유용한 메소드/속성을 가지고 있습니다.

 

 FormsCookieName

 쿠키이름을 반환합니다.

 FormsCookiePath

 쿠키경로를 반환합니다.

 Initialize

 Web.config 구성을 읽고 FormsAuthentication 클래스를 초기화 합니다.

 SignOut

 로그아웃 처리를 수행합니다.

 Decrypt

 암호화된 쿠키를 복호화합니다.

 Encrypt

 암호화된 쿠키를 생성합니다.

 

어느 웹서비스든 뻘짓하는 사용자가 존재하기 마련인데 특정 아이디에 대한 비밀번호를 반복적으로 입력해 정공법으로 해당 사용자의 계정을 취득하려는 경우가 대표적입니다. ASP.NET에서는 기본적으로 10분동안 로그인 시도횟수를 5번으로 제한하고 있는데 이러한 정책을 수정하려면 Membership공급자를 재정의해야 합니다.

 

<membership>

    <providers>

        <clear/>

        <add name="AspNetSqlMembershipProvider" 

type="System.Web.Security.SqlMembershipProvider, System.Web, Version=4.0.0.0, Culture=neutral, 

PublicKeyToken=b03f5f7f11d50a3a" connectionStringName="sqlprovider" enablePasswordRetrieval="false" 

enablePasswordReset="true" requiresQuestionAndAnswer="true" applicationName="/" 

requiresUniqueEmail="false" passwordFormat="Hashed" maxInvalidPasswordAttempts="5" 

minRequiredPasswordLength="7" minRequiredNonalphanumericCharacters="1" 

passwordAttemptWindow="10" passwordStrengthRegularExpression=""/>

     </providers>

</membership>


우선 공급자의 설정내용을 살펴보면 maxlnvalidPasswordAttempts가 5로 되어 있는 것을 볼 수 있는데 이는 5번의 시도를 의미합니다. passwordAttemptWindow의 값이 10이므로 제한시간은 10분이 됩니다.

 

실제 사용자가 잘못된 비밀번호를 입력하는 경우 개인화 DB의 aspnet_Membership 테이블에 그 기록이 남게 됩니다.

 

테이블의 FailedPasswordAttemptCount는 실패횟수를 FailedPasswordAttemptWindowStart는 실패시간을 의미합니다.

 

사용자가 아이디와 비밀번호를 입력하고 로그인을 시도했는데 위 설정 정책에 따라 10분동안 5번로그인에 실패하면 aspnet_Membership 의 IsLockedOut 컬럼에 true값이 입력되고 계정은 잠기게 됩니다.

 

계정 잠금에 관해서는 MembershipUser객체를 생성해 필요한 내용을 확인하거나 조치를 취하면 됩니다.

 

MembershipUser mu = Membership.GetUser("anchor37");

 

if (mu.IsLockedOut) { //잠긴계정 확인

    Response.Write("귀하의 계정음 잠겼습니다.");

 

    if (mu.UnlockUser()) //계정잠금 풀기

        Response.Write("귀하의 계정이 풀렸습니다.");

}

 

Login 컨트롤을 통해서 직업 사용자명과 비밀번호를 확인하고자 한다면 컨트롤의 OnAuthenticate 이벤트를 활용하면 됩니다.

 

<asp:login runat="server" ID="login1" OnAuthenticate="login1_Authenticate"></asp:login>

protected void login1_Authenticate(object sender, AuthenticateEventArgs e)
{
    if (login1.UserName == "username" && login1.Password == "password") {
    }
}

 

참고로 Remember me next time 설정값은 RememberMeSet 속성으로 확인할 수 있습니다.

'Programming > .NET' 카테고리의 다른 글

[C#] null 조건  (0) 2019.04.16
[ASP.NET] 인증및 접근제어와 로그인  (0) 2019.04.11
[C#] yield  (0) 2019.04.02
[C#] params  (0) 2019.03.19
[C#] HttpWebRequest / HttpWebResponse / WebClient  (0) 2019.03.12
[C#] 시프트(Shift) 연산자  (0) 2019.03.05
0 0