2017-11-02 22 views
0

今日のご挨拶! 私はフォーム認証を使用しています。登録はOKですが、ログインしている間は間違っています。反対にやっています。 登録時に、パスワード123を入力したとします。これでフォーム認証を使用してパスワードを変換し、DBに保存します。ログイン中に、ユーザーが123を入力すると変更され、DBに保存されます。 私のケースでは、両方のパスワードが一致すると、それは反対の動作をしています。カスタムエラーメッセージが表示されます。アカウントがロックされていない場合は、カウンター変数を増やします。ASP.netのフォーム認証

私のコードを調べて助けてください... 。

データベース: -

CREATE TABLE [dbo].[tblUsers](
    [ID] [int] IDENTITY(1,1) NOT NULL, 
    [UserName] [nvarchar](15) NULL, 
    [Password] [nvarchar](15) NULL, 
    [Email] [nvarchar](200) NULL, 
    [RetryAttempts] [int] NULL, 
    [IsLocked] [bit] NULL, 
    [LockedDateTime] [datetime] NULL, 
PRIMARY KEY CLUSTERED 
(
    [ID] ASC 
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
) ON [PRIMARY] 



CREATE proc [dbo].[sp_RegisterUser] 
@UserName nvarchar(15), 
@Password nvarchar(15), 
@Email nvarchar(200) 
As 
Begin 
Declare @Count int 
Declare @ReturnCode int 

Select @Count= COUNT(UserName) from tblUsers where [email protected] 
if(@Count=1) 

Begin 
Set @ReturnCode=-1 
End 

else 
Begin 
Set @ReturnCode=1 
insert into tblUsers(UserName,Password,Email) values(@UserName,@Password,@Email) 
End 
Select @ReturnCode as ReturnValue 
End 


CREATE proc [dbo].[SP_AuthenticateUser] 
@UserName nvarchar(15), 
@Password nvarchar(15) 
As 
Begin 
    Declare @Count int 
    Declare @RetryCount int 
    Declare @AccountLocked bit 

    Select @AccountLocked= ISNULL(IsLocked,0) from tblUsers where [email protected] 

    If(@AccountLocked=1) 
    Begin 
     Select 1 as AccountLocked,0 as Authenticate,0 as RetryAttempts 
    End 

    Else 
    Begin 
    Select @Count= COUNT(UserName) from tblUsers where [email protected] and [email protected] 
    If(@Count=1) 
    Begin 
     Select 0 as AccountLocked,1 as Authenticate,0 as RetryAttempts 
    End 

    Else 
    Begin 
     Select @RetryCount=ISNULL(RetryAttempts,0) from tblUsers where [email protected] 
     Set @[email protected]+1 
    If(@RetryCount<=3) 
    Begin 
     Update tblUsers set [email protected] where [email protected] 
     Select 0 as AccountLocked,0 as Authenticate,@RetryCount as RetryAttempts 
    End 
    Else 
    Begin 
     Update tblUsers set IsLocked=1,LockedDateTime=GETDATE() where [email protected] 
     Select 1 as AccountLocked,0 as Authenticate,0 as RetryAttempts 
    End 
    End 
    End 
End 

デザイン: -

Registration_Page-

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Registration.aspx.cs" Inherits="Registration" %> 

<!DOCTYPE html> 

<html xmlns="http://www.w3.org/1999/xhtml"> 
<head runat="server"> 
    <title></title> 
</head> 
<body> 
    <form id="form1" runat="server"> 
    <div style="font-family:Arial"> 
<table style="border: 1px solid black"> 
    <tr> 
     <td colspan="2"> 
      <b>User Registration</b> 
     </td> 
    </tr> 
    <tr> 
     <td> 
      User Name 
     </td>  
     <td> 
      :<asp:TextBox ID="txtUserName" runat="server"> 
      </asp:TextBox> 
      <asp:RequiredFieldValidator ID="RequiredFieldValidatorusername" 
      runat="server" ErrorMessage="User Name required" Text="*" 
      ControlToValidate="txtUserName" ForeColor="Red"> 
      </asp:RequiredFieldValidator> 
     </td>  
    </tr> 
    <tr> 
     <td> 
      Password 
     </td>  
     <td> 
      :<asp:TextBox ID="txtPassword" TextMode="Password" runat="server"> 
      </asp:TextBox> 
      <asp:RequiredFieldValidator ID="RequiredFieldValidatorPassword" 
      runat="server" ErrorMessage="Password required" Text="*" 
      ControlToValidate="txtPassword" ForeColor="Red"> 
      </asp:RequiredFieldValidator> 
     </td>  
    </tr> 
    <tr> 
     <td> 
      Confirm Password 
     </td>  
     <td> 
      :<asp:TextBox ID="txtConfirmPassword" TextMode="Password" runat="server"> 
      </asp:TextBox> 
      <asp:RequiredFieldValidator ID="RequiredFieldValidatorConfirmPassword" 
      runat="server" ErrorMessage="Confirm Password required" Text="*" 
      ControlToValidate="txtConfirmPassword" ForeColor="Red" 
      Display="Dynamic"></asp:RequiredFieldValidator> 
      <asp:CompareValidator ID="CompareValidatorPassword" runat="server" 
      ErrorMessage="Password and Confirm Password must match" 
      ControlToValidate="txtConfirmPassword" ForeColor="Red" 
      ControlToCompare="txtPassword" Display="Dynamic" 
      Type="String" Operator="Equal" Text="*"> 
      </asp:CompareValidator> 
     </td>  
    </tr> 
    <tr> 
     <td> 
      Email 
     </td>  
     <td> 
      :<asp:TextBox ID="txtEmail" runat="server"> 
      </asp:TextBox> 
      <asp:RequiredFieldValidator ID="RequiredFieldValidatorEmail" 
      runat="server" ErrorMessage="Email required" Text="*" 
      ControlToValidate="txtEmail" ForeColor="Red" 
      Display="Dynamic"></asp:RequiredFieldValidator> 
      <asp:RegularExpressionValidator ID="RegularExpressionValidatorEmail" 
      runat="server" ErrorMessage="Invalid Email" ControlToValidate="txtEmail" 
      ForeColor="Red" Display="Dynamic" Text="*" 
      ValidationExpression="\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*"> 
      </asp:RegularExpressionValidator> 
     </td>  
    </tr> 
    <tr> 
     <td> 

     </td>  
     <td> 
      <asp:Button ID="btnRegister" runat="server" Text="Register" 
      onclick="btnRegister_Click"/> 
     </td>  
    </tr> 
    <tr> 
     <td colspan="2"> 
      <asp:Label ID="lblMessage" runat="server" ForeColor="Red"> 
      </asp:Label> 
     </td>  
    </tr> 
    <tr> 
     <td colspan="2"> 
      <asp:ValidationSummary ID="ValidationSummary1" ForeColor="Red" runat="server" /> 
     </td>  
    </tr> 
</table> 
</div> 
    </form> 
</body> 
</html> 

ログインページ:_

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Login.aspx.cs" Inherits="_Default" %> 

<!DOCTYPE html> 

<html xmlns="http://www.w3.org/1999/xhtml"> 
<head runat="server"> 
    <title></title> 
</head> 
<body> 
    <form id="form1" runat="server"> 
    <div style="font-family:Arial"> 
<table style="border: 1px solid black"> 
    <tr> 
     <td colspan="2"> 
      <b>Login</b> 
     </td> 
    </tr> 
    <tr> 
     <td> 
      User Name 
     </td>  
     <td> 
      :<asp:TextBox ID="txtUserName" runat="server"> 
      </asp:TextBox> 
     </td>  
    </tr> 
    <tr> 
     <td> 
      Password 
     </td>  
     <td> 
      :<asp:TextBox ID="txtPassword" TextMode="Password" runat="server"> 
      </asp:TextBox> 
     </td>  
    </tr> 
    <tr> 
     <td> 
      <asp:CheckBox ID="chk_boxRememberMe" runat="server" Text="Remember Me" />   
     </td>  
     <td> 
      <asp:Button ID="btnLogin" runat="server" Text="Login" OnClick="btnLogin_Click" /> 
     </td>  
    </tr> 
    <tr> 
     <td> 
      <asp:Label ID="lblMessage" runat="server" ForeColor="Red"></asp:Label> 
     </td> 
    </tr> 
</table> 
<br /> 
<a href="Registration/Registration.aspx">Click here to register</a> 
if you do not have a user name and password. 
</div> 

    </form> 
</body> 
</html> 

背後にあるコード: -

登録ページ: -

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Web; 
using System.Web.UI; 
using System.Web.UI.WebControls; 
using System.Data; 
using System.Data.SqlClient; 
using System.Configuration; 
using System.Web.Security; 
public partial class Registration : System.Web.UI.Page 
{ 
    protected void Page_Load(object sender, EventArgs e) 
    { 

    } 

    protected void btnRegister_Click(object sender, EventArgs e) 

    { 
     if (Page.IsValid) 
     { 
      string CS = ConfigurationManager.ConnectionStrings["con"].ConnectionString; 

      using (SqlConnection Conn=new SqlConnection(CS)) 
      { 
       SqlCommand cmd = new SqlCommand("sp_RegisterUser",Conn); 
       cmd.CommandType = CommandType.StoredProcedure; 

       SqlParameter UserName = new SqlParameter("@UserName",txtUserName.Text); 
       string EncryptPassword = FormsAuthentication.HashPasswordForStoringInConfigFile(txtPassword.Text, "SHA1"); 
       SqlParameter Password = new SqlParameter("@Password", EncryptPassword); 

       SqlParameter Email = new SqlParameter("@Email", txtEmail.Text); 

       cmd.Parameters.Add(UserName); 
       cmd.Parameters.Add(Password); 
       cmd.Parameters.Add(Email); 

       Conn.Open(); 

       int ReturnCode=(int) cmd.ExecuteScalar(); 

       if (ReturnCode==-1) 
       { 
        lblMessage.Text = "User Name alredy exists"; 
       } 
       else 
       { 
        Response.Redirect("~/Login.aspx"); 
       } 
      } 
     } 
    } 
} 

ログインページ: -

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Web; 
using System.Web.UI; 
using System.Web.UI.WebControls; 
using System.Data; 
using System.Data.SqlClient; 
using System.Configuration; 
using System.Web.Security; 


public partial class _Default : System.Web.UI.Page 
{ 
    protected void Page_Load(object sender, EventArgs e) 
    { 

    } 

    protected void btnLogin_Click(object sender, EventArgs e) 
    { 
     //Login_WebConfig(); 
     // Login_DataBase(); 

     if (AuthenticateUser(txtUserName.Text, txtPassword.Text)) 
     { 
      FormsAuthentication.RedirectFromLoginPage(txtUserName.Text, chk_boxRememberMe.Checked); 
     } 
     else 
     { 
      lblMessage.Text = "Invalid username/password"; 
     } 
    } 

    //protected void Login_WebConfig() 
    //{ 
    // if (FormsAuthentication.Authenticate(txtUserName.Text, txtPassword.Text)) 
    // { 
    //  FormsAuthentication.RedirectFromLoginPage(txtUserName.Text, chk_boxRememberMe.Checked); 
    // } 
    // else 
    // { 
    //  lblMessage.Text = "Invalid user name/password"; 
    // } 
    //} 

    protected void Login_DataBase() 
    { 

    } 

    private bool AuthenticateUser(string username, string password) 
    { 
     string CS = ConfigurationManager.ConnectionStrings["con"].ConnectionString; 
     using (SqlConnection Conn = new SqlConnection(CS)) 
     { 
      SqlCommand cmd = new SqlCommand("SP_AuthenticateUser", Conn); 
      cmd.CommandType = CommandType.StoredProcedure; 

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

      SqlParameter paramUserName = new SqlParameter("@UserName", username); 
      SqlParameter paramPassword = new SqlParameter("@Password", EncryptPassword); 

      cmd.Parameters.Add(paramUserName); 
      cmd.Parameters.Add(paramPassword); 
      Conn.Open(); 

      int ReturnCode = (int)cmd.ExecuteScalar(); 
      return ReturnCode == 1; 


     } 
    } 
} 

のWeb設定: -

<?xml version="1.0"?> 

<!-- 
    For more information on how to configure your ASP.NET application, please visit 
    http://go.microsoft.com/fwlink/?LinkId=169433 
    --> 

<configuration> 

    <system.web> 
     <compilation debug="true" targetFramework="4.5" /> 
     <httpRuntime targetFramework="4.5" /> 
     <authentication mode="Forms"> 
     <forms loginUrl="Login.aspx" defaultUrl="Welcome.aspx" timeout="2" protection="All"> 
      <!--<credentials passwordFormat="Clear"> 
      <user name="rkbisht" password="1234"/> 
      </credentials>--> 
     </forms> 
     </authentication> 
     <authorization> 
     <deny users="?"/> 
     </authorization> 
    </system.web> 

    <appSettings> 
     <add key="ValidationSettings:UnobtrusiveValidationMode" value="None" /> 
    </appSettings> 

    <connectionStrings> 
    <add name="con" connectionString="Data Source=.;Initial Catalog=Security_Learning;Integrated Security=true"/> 
    </connectionStrings> 

</configuration> 
+0

なぜ独自の認証システムを構築していますか?あなたのサイトを侵害してもらいたいですか? ASP.NET IDを使用するか、できない場合は、その前身のメンバーシップを使用します。あなた自身の認証をロールバックしないでください。 – CodeCaster

答えて

0

基本的に、あなたは仕事のための適切なツールを使用していません。

あなたは確かにFormsAuthenticationを使用しておらず、設定ファイルにハッシュを保存していないので、FormsAuthentication.HashPasswordForStoringInConfigは使用するべきものではありません。

この権利を取得するには時間がかかることがあります。ここでの出発点は次のとおりです。

https://docs.microsoft.com/en-us/aspnet/core/security/data-protection/consumer-apis/password-hashing

注意、あなたはハッシュと塩を使用する必要があり、塩は、各ユーザに一意である必要があります。

個人的に私は次のように実装してMicrosoft.AspNetCore.Cryptography.KeyDerivation nugetパッケージを使用します。

ヘルパークラス

using Microsoft.AspNetCore.Cryptography.KeyDerivation; 
using Resources; 
using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Security.Cryptography; 
using System.Text; 
using System.Web; 

public static class SecurityHelper 
{ 
    public static int DefaultIterations = 10000 

    //KeyDerivation.Pbkdf2 
    /// <summary> 
    /// Generates a random salt 
    /// </summary> 
    /// <returns>A byte array containing a random salt</returns> 
    public static byte[] GetRandomSalt() 
    { 
     byte[] saltBytes = new byte[32]; 
     RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider(); 
     rng.GetNonZeroBytes(saltBytes);    
     return saltBytes; 
    } 

    public static string GeneratePasswordHash(string plainPassword, int iterations, out string generatedRandomSalt) 
    { 
     generatedRandomSalt = Convert.ToBase64String(GetRandomSalt()); 
     return Convert.ToBase64String(ComputeHash(plainPassword, generatedRandomSalt, iterations)); 
    } 

    public static string GetPasswordHash(string plainPassword, string existingSalt, int iterations) 
    { 
     return Convert.ToBase64String(ComputeHash(plainPassword, existingSalt, iterations)); 
    } 



    private static byte[] ComputeHash(string plainText, string salt, int iterations) 
    { 
     return KeyDerivation.Pbkdf2(
     password: plainText, 
      salt: Convert.FromBase64String(salt), 
      prf: KeyDerivationPrf.HMACSHA256, 
      iterationCount: iterations, 
      numBytesRequested: 32); 
    }  

} 

あなたのワークフローは今変更:

  • をあなたがパスワードを保存します、あなたも塩を保存する必要があります
  • ユーザーを認証するときは、データベースからUserNameでユーザーを取得し、保存されたsaltを使用して入力されたパスワードのハッシュを計算し、保存されたハッシュと結果を比較します。

大雑把

//Registration 
using (SqlConnection Conn=new SqlConnection(CS)) 
{ 
    SqlCommand cmd = new SqlCommand("sp_RegisterUser",Conn); 
    cmd.CommandType = CommandType.StoredProcedure; 

    SqlParameter UserName = new SqlParameter("@UserName",txtUserName.Text); 
    string Salt = string.Empty; 
    string Password = SecurityHelper.GeneratePasswordHash(txtPassword.Text, SecurityHelper.DefaultIterations, out salt); 
    ; 
    SqlParameter Password = new SqlParameter("@Password", Password); 
    SqlParameter Email = new SqlParameter("@Email", txtEmail.Text); 
    SqlParameter Salt = new SqlParameter("@Salt", Salt); 
    cmd.Parameters.Add(UserName); 
    cmd.Parameters.Add(Password); 
    cmd.Parameters.Add(Email); 

    Conn.Open(); 

    int ReturnCode=(int) cmd.ExecuteScalar(); 

    if (ReturnCode==-1) 
    { 
     lblMessage.Text = "User Name alredy exists"; 
    } 
    else 
    { 
     Response.Redirect("~/Login.aspx"); 
    } 
} 

//Log In 
private bool AuthenticateUser(string username, string password) 
{ 
    //Get the following from your database based on username 
    string savedHash = //fromDB; 
    string savedSalt = //fromDb; 

    return (SecurityHelper.GetPasswordHash(password, savedSalt, SecurityHelper.DefaultIterations) == tempUser.Password)     
} 

私は多少これを単純化してきました。また、デフォルトの反復を増やす必要がある場合に備えて、データベース内のユーザーに対して反復処理を保存します。

私の最終的なアドバイスは、「塩漬け」が良いことです。

+0

ロールベースのSeuciryでこれをどのように拡張しましたか? –

0

認証ストアドプロシージャ(SP_AuthenticateUser)は3列を返しますが、ExecuteScalarを使用して呼び出しています。データセットを取得し、2番目の列を確認する必要があります。

private bool AuthenticateUser(string username, string password) 
{ 
    string CS = ConfigurationManager.ConnectionStrings["con"].ConnectionString; 
    using (SqlConnection Conn = new SqlConnection(CS)) 
    { 
     SqlCommand cmd = new SqlCommand("SP_AuthenticateUser", Conn); 
     cmd.CommandType = CommandType.StoredProcedure; 

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

     SqlParameter paramUserName = new SqlParameter("@UserName", username); 
     SqlParameter paramPassword = new SqlParameter("@Password", EncryptPassword); 

     cmd.Parameters.Add(paramUserName); 
     cmd.Parameters.Add(paramPassword); 
     Conn.Open(); 

     var reader = cmd.ExecuteReader(); 
     reader.Read(); 
     return reader["Authenticate"] as bool; 
    } 
} 

また、認証が成功した場合は、再試行カウンタをリセットしてください。

Select @Count= COUNT(UserName) from tblUsers where [email protected] and [email protected] 
If(@Count=1) 
Begin 
    Update tblUsers set RetryAttempts = 0 where UserName = @UserName 
    Select 0 as AccountLocked,1 as Authenticate,0 as RetryAttempts 
End 

あなたのコードには他にもいくつか問題がありますが、その2つはあなたの質問に記載されている動作を引き起こしている可能性があります。

Here is a better way to hash your password

フォームの認証Cookieを設定しない限り、ユーザーはサインオンを続ける必要があります。 Click here for ideas on how

web.configには認証情報は必要ありません。 FormsAuthentication.Authenticateを使用する場合は、その場所に置くだけです。代わりにデータベースを使用しているようです。

関連する問題