运用WPF和ADO.Net实现限制登录错误次数的简单登录界面_.NET_编程开发_程序员俱乐部

中国优秀的程序员网站程序员频道CXYCLUB技术地图
热搜:
更多>>
 
您所在的位置: 程序员俱乐部 > 编程开发 > .NET > 运用WPF和ADO.Net实现限制登录错误次数的简单登录界面

运用WPF和ADO.Net实现限制登录错误次数的简单登录界面

 2014/9/17 15:38:29  小碎石  程序员俱乐部  我要评论(0)
  • 摘要:最近看了一下传智播客的免费公开课视频,有一个登录界面的小练习。其中涉及到登录时间的限定功能,并未实现。所以我就自己动手写了一个,大家可以看看。首先编写SqlHelper类,通过SqlHelper类实现SQL单语句操作数据库。代码如下:1usingSystem;2usingSystem.Collections.Generic;3usingSystem.Linq;4usingSystem.Text;5usingSystem.Data.SqlClient;6usingSystem.Data
  • 标签:.net 实现 net 运用 限制 错误

  最近看了一下传智播客的免费公开课视频,有一个登录界面的小练习。其中涉及到登录时间的限定功能,并未实现。所以我就自己动手写了一个,大家可以看看。

首先编写SqlHelper类,通过SqlHelper类实现SQL单语句操作数据库。代码如下:

class="code_img_closed" src="/Upload/Images/2014091715/0015B68B3C38AA5B.gif" alt="" />logs_code_hide('65063697-8480-41f8-b20e-28f36cef98bb',event)" src="/Upload/Images/2014091715/2B1B950FA3DF188F.gif" alt="" />
 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 using System.Data.SqlClient;
 6 using System.Data;
 7 
 8 namespace 登录界面
 9 {
10     class SqlHelper
11     {
12         //此处没有设置为App.Config文件里的配置,只是想简单实现本项目。
13         private static string connectStr = @"Data Source=.\SQLEXPRESS;Initial Catalog=JJLogin;Integrated Security=True;";
14 
15         public static void ExecuteNonQuery(string sql, params SqlParameter[] parameters)
16         {
17             using (SqlConnection conn = new SqlConnection(connectStr))
18             {
19                 conn.Open();
20                 using (SqlCommand cmd = conn.CreateCommand())
21                 {
22                     cmd.CommandText = sql;
23                     cmd.Parameters.AddRange(parameters);
24                     cmd.ExecuteNonQuery();
25                 }
26             }
27         }
28 
29         public static object ExecuteScalar(string sql, params SqlParameter[] parameters)
30         {
31             using (SqlConnection conn = new SqlConnection(connectStr))
32             {
33                 conn.Open();
34                 using (SqlCommand cmd = conn.CreateCommand())
35                 {
36                     cmd.CommandText = sql;
37                     cmd.Parameters.AddRange(parameters);
38                     object obj = cmd.ExecuteScalar();
39                     return obj;
40                 }
41             }
42         }
43 
44         public static DataTable ExecuteDataTable(string sql, params SqlParameter[] parameters)
45         {
46             using (SqlConnection conn = new SqlConnection(connectStr))
47             {
48                 conn.Open();
49                 using (SqlCommand cmd =conn.CreateCommand())
50                 {
51                     cmd.CommandText = sql;
52                     cmd.Parameters.AddRange(parameters);
53                     SqlDataAdapter adapter = new SqlDataAdapter(cmd);
54                     DataTable ds = new DataTable();
55                     adapter.Fill(ds);
56                     return ds;
57                 }
58             }
59         }
60     }
61 }
View Code

  因最近半个月都在学习WPF技术,所以本示例采用的是WPF显示层技术。XAML代码如下:

 1 <Window x:Class="登录界面.MainWindow"
 2         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 3         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 4         Title="微博登录" Height="200" Width="250" ResizeMode="NoResize">
 5     <Grid>
 6         <Grid.RowDefinitions>
 7             <RowDefinition Height="Auto"></RowDefinition>
 8             <RowDefinition Height="Auto"></RowDefinition>
 9             <RowDefinition Height="Auto"></RowDefinition>
10             <RowDefinition Height="*"></RowDefinition>
11         </Grid.RowDefinitions>
12         <Grid.ColumnDefinitions>
13             <ColumnDefinition Width="Auto"></ColumnDefinition>
14             <ColumnDefinition Width="*"></ColumnDefinition>
15             <ColumnDefinition Width="Auto"></ColumnDefinition>
16         </Grid.ColumnDefinitions>
17         <TextBlock Grid.Row="0" Grid.Column="0" Text="用户名"></TextBlock>
18         <TextBlock Grid.Row="1" Grid.Column="0" Text="密码"></TextBlock>
19         <TextBox x:Name="txt_UserName" Grid.Row="0" Grid.Column="1" Margin="3"></TextBox>
20         <PasswordBox x:Name="txt_PassWord" Grid.Row="1" Grid.Column="1" Margin="3"></PasswordBox>
21         <DockPanel x:Name="btndock_login" Grid.Row="2" Grid.Column="1" Margin="3" Button.Click="btndock_login_Click">
22             <Button x:Name="btn_loginIn" Content="登录" HorizontalAlignment="Left" Margin="3"></Button>
23             <Button x:Name="btn_loginOut" Content="取消" HorizontalAlignment="Right" Margin="3"></Button>
24         </DockPanel>
25         <TextBlock x:Name="tbk_LoginMessage" Grid.Row="3" Grid.Column="1" VerticalAlignment="Top" HorizontalAlignment="Stretch" TextWrapping="Wrap"></TextBlock>
26     </Grid>
27 </Window>
View Code

  逻辑层代码如下:

  1 using System;
  2 using System.Collections.Generic;
  3 using System.Linq;
  4 using System.Text;
  5 using System.Windows;
  6 using System.Windows.Controls;
  7 using System.Windows.Data;
  8 using System.Windows.Documents;
  9 using System.Windows.Input;
 10 using System.Windows.Media;
 11 using System.Windows.Media.Imaging;
 12 using System.Windows.Navigation;
 13 using System.Windows.Shapes;
 14 using System.Data.SqlClient;
 15 using System.Data;
 16 using System.ComponentModel;
 17 
 18 namespace 登录界面
 19 {
 20     /// <summary>
 21     /// MainWindow.xaml 的交互逻辑
 22     /// </summary>
 23     public partial class MainWindow : Window
 24     {
 25         private Message message;
 26         public MainWindow()
 27         {
 28             InitializeComponent();
 29 
 30             message = new Message();
 31             tbk_LoginMessage.SetBinding(TextBlock.TextProperty, new Binding("LoginInfo") { Source = message });
 32         }
 33 
 34         private void btndock_login_Click(object sender, RoutedEventArgs e)
 35         {
 36             if (e.OriginalSource is Button)
 37             {
 38                 switch (((Button)e.OriginalSource).Name)
 39                 {
 40                     case "btn_loginIn":
 41                         {
 42                             LoginIn(txt_UserName.Text, txt_PassWord.Password);
 43                         } break;
 44                     case "btn_loginOut":
 45                         {
 46                             txt_UserName.Text = string.Empty;
 47                             txt_PassWord.Password = string.Empty;
 48                         }
 49                         break;
 50                     default: break;
 51                 }
 52             }
 53             else
 54             {
 55                 throw new Exception("请点击登录或取消按钮");
 56             }
 57         }
 58 
 59         private void LoginIn(string userName, string password)
 60         {
 61             //查询SQLServer默认情况下不区分大小写,因此对于用户名需要采取区分大小写的查询方式,此程序有待升级
 62             string sqlSelect = "select * from T_User where UserName=@UserName";
 63             DataTable table = SqlHelper.ExecuteDataTable(sqlSelect, new SqlParameter("@UserName", txt_UserName.Text));
 64             int count = table.Rows.Count;
 65             if (count <= 0)
 66             {
 67                 message.LoginInfo = "用户不存在";
 68                 return;
 69             }
 70             else if (count > 1)
 71             {
 72                 message.LoginInfo = "不好啦,用户名重复啦";
 73                 return;
 74             }
 75             DataRow row = table.Rows[0];
 76             long id = (long)row["ID"];
 77             string dbPassword = (string)row["PassWord"];
 78             int frequency = (int)row["Frequency"];
 79             DateTime dbTime = (DateTime)row["ErrorTime"];
 80             if (frequency >= 3)
 81             {
 82                 //如果frequency>=4就会比较dbTime与DateTime.Now之间的时间间隔是否大于15s
 83                 if (frequency >= 4)
 84                 {
 85                     TimeSpan timespan = DateTime.Now - dbTime;
 86                     double d = timespan.TotalSeconds;
 87                     if (d < 15.0)
 88                     {
 89                         message.LoginInfo = "请15s后再来登陆";
 90                         return;
 91                     }
 92                     //只要超过15s间隔再登陆就应该设置错误次数=0
 93                     frequency = 0;
 94                     goto passwordValidate;
 95                 }
 96 
 97                 string sqlUpdateErrorTime = "Update T_User set ErrorTime=@ErrorTime,Frequency=@Frequency+1";
 98                 SqlHelper.ExecuteNonQuery(sqlUpdateErrorTime, new SqlParameter("@ErrorTime", DateTime.Now), new SqlParameter("@Frequency", frequency));
 99                 message.LoginInfo = "输入错误次数太多,请耐心等待15s后再登陆";
100                 return;
101             }
102 
103         passwordValidate:
104             if (dbPassword != password)
105             {
106                 string sqlUpdateFrequency = "Update T_User set Frequency=@Frequency+1";
107                 SqlHelper.ExecuteNonQuery(sqlUpdateFrequency, new SqlParameter("@Frequency", frequency));
108                 message.LoginInfo = "密码输入错误"+(frequency+1)+"";
109                 return;
110             }
111             else
112             {
113                 frequency = 0;
114                 string sqlUpdateFrequency = "Update T_User set Frequency=@Frequency";
115                 SqlHelper.ExecuteNonQuery(sqlUpdateFrequency, new SqlParameter("@Frequency", frequency));
116                 message.LoginInfo = "登陆成功";
117             }
118         }
119     }
120 
121     public class Message : INotifyPropertyChanged
122     {
123         private string loginInfo;
124         public string LoginInfo
125         {
126             get { return loginInfo; }
127             set
128             {
129                 loginInfo = value;
130                 if (PropertyChanged != null)
131                 {
132                     PropertyChanged(this, new PropertyChangedEventArgs("LoginInfo"));
133                 }
134             }
135         }
136 
137         public event PropertyChangedEventHandler PropertyChanged;
138     }
139 }
View Code

  数据库设计

1 //ID                    bigint
2 //UserName       nvchar(20)   
3 //PassWord       nvchar(20)    
4 //Frequency       int
5 //ErrorTime        datetime
View Code

  关于登录时间的处理,本示例的思路是:如果连续三次登录错误,就会将当前系统时间存进数据库,但是输入错误次数(frequency)不清零。当你再次尝试登录时,会从数据库中读出本用户上次错误登录时的时间,将该值与现在的系统时间进行比较,如果小于规定的时间间隔,则提示用户耐心等待。如果时间间隔(timespan)大于规定的时间间隔,则将错误登录次数清零,接着进行经常的密码验证流程。

  本示例是一个简单版本,当然会有很多考虑不周到的地方。目前的不足:

  1.数据库查询如何进行大小写敏感设置,目前我还不会如何设置,所以数据库中的用户名输入大小写都能登录成功,这个肯定要改。

  2.因为是用WPF做的界面,所以关于登录信息提示的TextBlock,其文本属性应该绑定到Message消息中,所以可设置一个Message类,将提示信息文本保存在Message类的LoginInfo属性中。但是用户名和密码等输入文本框也应该以Mode=OneWayToSource绑定到User类的UserName与Password属性中。并对输入的数据进行Validation,通过自定义UserNameValidationRule和PasswordValidationRule。这些细节目前还没完全实现,正在编码中。在接下来的WPF学习中会继续研究

  最后,大家如有好的意见可以留言。

上一篇: [WCF编程]10.操作:单向操作 下一篇: 没有下一篇了!
发表评论
用户名: 匿名