另外即使只是做做试验也是不错的尝试。
本文并没有对各种登陆算法进行对比探讨。而是仅仅给出了一个比较安全、高效也经历了实际的考验的算法供大家参考。
本文中给出一个实例的节选,希望能给各位启示。
该算法的特点为:
1、安全、仅仅使用用户名(考生号)来访问数据库,这样需要控制的项就比较少了.即使进行安全检查系统压力也小。
2、高效、一般情况下用户操作仅需一次数据访问,所需的数据就全部返回了。而且单键访问数据执行效率也高。
3、比较完整的简单的分层设计,可以供入门程序员参考(作为教学人员,我的注释写的很详细,具有一定的可读性)
一、建立数据模型:数据集如下图:存放在app_code目录中,命名为kaoshengs.xsd
1、考生表的结构。依次为考生号、考生姓名、录取结果、密码(口令,默认是空值。)、查分密码(该系统中每个考生有自己的随机查分密码覆膜印在准考证上,第一次需要使用该密码来登录系统并修改密码)、报名点代码、县区代码、地市代码(后边3个代码是为了管理使用)。
2、适配器。增加了几个访问数据的方法,有名称和参数可以很容易的看出,不再解释了。
二、对该考生对象的操作的类库。存放在app_code目录中,命名为kaosheng.cs
需要注意的是,该系统在登陆时需要的操作比较多
1、有用户名和密码能够登录
2、有录取结果,显示录取结果,并不再允许继续操作
3、密码为空,则为第一次登录允许使用查分密码来修改口令
4、修改已有的口令
1
using System;
2
using System.Data;
3
using System.Configuration;
4
using System.Web;
5
using System.Web.Security;
6
using System.Web.UI;
7
using System.Web.UI.WebControls;
8
using System.Web.UI.WebControls.WebParts;
9
using System.Web.UI.HtmlControls;
10
using System.Collections;
11
12
/// <summary>
13
/// kaosheng 的摘要说明
14
/// edit by lww @2007-04-21
15
/// 考生对象的相关操作
16
/// </summary>
17
public class kaosheng
18
{
19
public kaosheng()
20
{
21
//
22
// TODO: 在此处添加构造函数逻辑
23
//
24
}
25
26
/// <summary>
27
/// 验证用户
28
/// </summary>
29
/// <param name="ksh"></param>
30
/// <param name="code"></param>
31
/// <returns>
32
/// 根据返回进行跳转
33
/// 返回值为arrylist 其中
34
/// retal[0]存放int形式的返回值
35
/// 其中
36
/// 0:系统出错、数据库连接?
37
/// 1:已被录取
38
/// 2:登录正确
39
/// 3:首次登录需导向修改页面
40
/// 4:登录密码不对(已有但是不正确)
41
/// 5:未更改过密码,并且查分码不对
42
/// 6:错误的考生号
43
/// retal[1]之后存放string附加值
44
/// 标号 0 1 2 3 4 5 6
45
/// 包括: 返回类型 考生号、考生姓名、县区、 地市
46
47
/// </returns>
48
public static ArrayList yanzheng(string ksh,string code)
49
{
50
///根据输入的考生号和密码进行判断
51
///由于这里需要判断的项比较多,所以采用将考生相关信息返回的方式
52
///根据输入的考生号,得到返回值。包括:考生姓名、密码、查分密码、录取信息
53
ArrayList ksinfo= getks(ksh);
54
ArrayList retal = new ArrayList();
55
if (ksinfo[0].ToString().Trim() == "0")
56
{//错误考生号
57
retal.Add("6");
58
return retal;
59
}
60
///1、首先判断是否被录取,如果被录取则提示,不再继续进行下面的操作
61
if ((ksinfo[4].ToString().Trim() != string.Empty) && (ksinfo[4].ToString().Trim() != null))
62
{//已经被录取
63
retal.Add("1");
64
retal.Add(ksinfo[4].ToString());
65
return retal;
66
}
67
else
68
{//本来下边的处理其他情况的代码包含在else中,但是为了程序的可读性,我们在前边增加了 return retal;跳出,
69
//这样后边就可以从if else中剥离出来了.这里为了方便叙述保留了else段
70
}
71
///ksinfo格式
72
/// 根据考生号取得考生信息
73
/// 标号 0 1 2 3 4 5 6 7
74
/// 包括:考生号、考生姓名、密码、查分密码、录取信息 县区 地市 报名点
75
76
///3、如果返回值密码项不为空,判断是否和新输入的密码的md5一致,一致则允许登录,不一致,则导向提示页面,提示考生联系管理员
77
if ((ksinfo[2].ToString().Trim() != string.Empty) && (ksinfo[2].ToString().Trim() != null))
78
{
79
if (ksinfo[2].ToString().Trim() == MD5s.genmd5(code))
80
{//正确登录
81
retal.Add("2");
82
}
83
else
84
{
85
retal.Add("4");
86
}
87
}
88
else
89
{
90
///4、如果为空,判断查分密码是否正确,正确则导向修改密码页面,
91
if (ksinfo[3].ToString().Trim() == code)
92
{
93
retal.Add("3");
94
}
95
else
96
{
97
retal.Add( "5");
98
}
99
}
100
//返回结果:附加
101
retal.Add(ksinfo[0].ToString());//考生号
102
retal.Add(ksinfo[1].ToString());//考生姓名
103
retal.Add(ksinfo[3].ToString());//考生登录号
104
retal.Add(ksinfo[5].ToString());//考生县区名称
105
retal.Add(ksinfo[6].ToString());//考生地市名称
106
retal.Add(ksinfo[7].ToString());//报名点名称
107
retal.Add(ksinfo[8].ToString());//报名点代码
108
/// 返回结果
109
/// 标号 0 1 2 3 4 5 6
110
/// 包括: 代码 考生号、考生姓名、查分密码、 县区 地市 报名点
111
return retal;
112
}
113
/// <summary>
114
/// 修改密码:重载1、考生使用
115
/// </summary>
116
/// <param name="ksh"></param>
117
/// <param name="code"></param>
118
/// <returns></returns>
119
public static bool passchange(string ksh, string code,string newcode)
120
{
121
///根据考生号进行密码重置,
122
///首先判断查分密码是否正确,然后判断更改密码
123
///如果密码为空,根据查分密码判断
124
ArrayList ksinfo = getks(ksh);
125
if (ksinfo[2].ToString().Trim() == string.Empty)
126
{
127
if ((ksinfo[0].ToString() == ksh) && (ksinfo[3].ToString() == code))
128
{
129
return passchange(ksh, newcode);
130
}
131
}
132
else
133
{
134
if ((ksinfo[0].ToString() == ksh) && (ksinfo[2].ToString().Trim() == MD5s.genmd5(code)))
135
{
136
return passchange(ksh, newcode);
137
}
138
}
139
return false;
140
}
141
/// <summary>
142
/// 重置密码:重载2、管理员使用,将考生密码初始化为指定值
143
/// </summary>
144
/// <param name="ksh"></param>
145
/// <returns></returns>
146
public static bool passchange(string ksh, string newcode)
147
{
148
///根据考生号进行密码重置
149
kaoshengsTableAdapters.tksTableAdapter ksapt = new kaoshengsTableAdapters.tksTableAdapter();
150
string newpass = "";
151
//逻辑,置空密码传入的时候需要处理,不需要md5
152
if(newcode.Trim()==string.Empty)
153
{
154
newpass = "";
155
}
156
else
157
{
158
newpass = MD5s.genmd5(newcode);
159
}
160
try
161
{
162
ksapt.passchange(newpass, ksh);
163
return true;
164
}
165
catch { return false; }
166
}
167
168
/// <summary>
169
/// 登录日志
170
/// </summary>
171
/// <param name="ksh"></param>
172
/// <param name="code"></param>
173
/// <returns></returns>
174
public static string loginlog(string ksh, string ip,string code)
175
{
176
///写日志
177
rizhiTableAdapters.rzTableAdapter rz = new rizhiTableAdapters.rzTableAdapter();
178
rz.rizhi(ksh, ip, code);
179
return "ok";
180
}
181
182
/// <summary>
183
/// 根据考生号取得考生信息
184
/// 请注意,该命令仅仅使用ksh作为参数而没有使用用户名,
185
/// 原因为
186
/// 1、安全:ksh已经在网页中限制为仅能为数字
187
/// 2、高效:数字的主键访问速度快
188
/// 返回信息为: ///
189
/// 标号 0 1 2 3 4 5 6 7 8
190
/// 包括:考生号、考生姓名、密码、查分密码、录取信息 县区 地市 报名点 报名点代码
191
/// </summary>
192
/// <param name="ksh"></param>
193
public static ArrayList getks(string ksh)
194
{
195
///从数据库中根据考生号填充数据然后将arraylist填充
196
kaoshengsTableAdapters.tksTableAdapter ksapt = new kaoshengsTableAdapters.tksTableAdapter();
197
kaoshengs.tksDataTable tks=new kaoshengs.tksDataTable();
198
ksapt.getksinfo(tks, ksh);
199
kaoshengs.tksRow r = tks.FindByksh(ksh);
200
ArrayList al = new ArrayList();
201
if (r==null)
202
{//未发现记录,返回第一个为"0"标记为错误
203
al.Add("0");
204
return al;
205
}
206
else
207
{
208
al.Add(r.ksh.ToString().Trim());//考生考生号
209
al.Add(r.ksxm.ToString().Trim());//考生姓名
210
al.Add(r.mima.ToString().Trim());//考生当前密码
211
al.Add(r.kscf.ToString().Trim());//考生查分密码
212
al.Add(r.kslq.ToString().Trim());//考生是否被录取
213
///在这里返回的区域代码需要翻译为含义
214
string xqdm = r.bmddm.Substring(0, 4).Trim();
215
string dsdm = r.bmddm.Substring(0, 2).Trim();
216
string bmddm = r.bmddm.Substring(0,6).Trim();
217
string xqmc = cache.transxqdm(xqdm);
218
string dsmc = cache.transdsdm(dsdm);
219
string bmdmc = cache.transbmddm(bmddm);
220
al.Add(xqmc);//县区名称
221
al.Add(dsmc);//地市名称
222
al.Add(bmdmc);//报名点名称
223
al.Add(r.bmddm.Substring(0, 6).Trim());//报名点代码
224
return al;
225
}
226
}
227
228
//下边的代码为管理员使用的部分
229
230
/// <summary>
231
/// 通过考生号加载数据
232
/// </summary>
233
/// <param name="ksh"></param>
234
/// <returns></returns>
235
public static kaoshengs.tksDataTable getbyksh(string ksh)
236
{
237
//首先取出当前的权限
238
ArrayList alqx = quanxian.yanzheng();
239
kaoshengs.tksDataTable tb = new kaoshengs.tksDataTable();
240
kaoshengsTableAdapters.tksTableAdapter ksapt = new kaoshengsTableAdapters.tksTableAdapter();
241
tb = ksapt.GetDataByksh(ksh, alqx[3].ToString(), alqx[4].ToString());
242
return tb;
243
}
244
/// <summary>
245
/// 通过考生姓名加载数据,模糊查询
246
/// </summary>
247
/// <param name="ksxm"></param>
248
/// <returns></returns>
249
public static kaoshengs.tksDataTable getbyxm(string ksxm)
250
{
251
//首先取出当前的权限
252
ArrayList alqx = quanxian.yanzheng();
253
kaoshengs.tksDataTable tb = new kaoshengs.tksDataTable();
254
kaoshengsTableAdapters.tksTableAdapter ksapt = new kaoshengsTableAdapters.tksTableAdapter();
255
tb = ksapt.GetDataByxm(ksxm, alqx[3].ToString(), alqx[4].ToString());
256
return tb;
257
}
258
259
/// <summary>
260
/// 通过考生号范围加载数据
261
/// </summary>
262
/// <param name="kshmin"></param>
263
/// <param name="kshmax"></param>
264
/// <returns></returns>
265
public static kaoshengs.tksDataTable getbyfw(string kshmin,string kshmax)
266
{
267
//首先取出当前的权限
268
//ArrayList alqx = quanxian.yanzheng();
269
////将用户输入的范围置入当前权限允许的范围内
270
string min=kshmin,max=kshmax;
271
ArrayList alqx = quanxian.yanzheng();
272
if (Convert.ToInt64(kshmin) < Convert.ToInt64(alqx[3].ToString()))
273
{ min = alqx[3].ToString(); }
274
if (Convert.ToInt64(kshmax) > Convert.ToInt64(alqx[4].ToString()))
275
{ max = alqx[4].ToString(); }
276
kaoshengs.tksDataTable tb = new kaoshengs.tksDataTable();
277
kaoshengsTableAdapters.tksTableAdapter ksapt = new kaoshengsTableAdapters.tksTableAdapter();
278
tb = ksapt.GetDataByfw(min, max);
279
return tb;
280
}
281
282
283
}
284
三、登录页面。页面如下,其中考生号有ajax效果控制不能输入除数字以外的信息
2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202

203

204

205

206

207

208

209

210

211

212

213

214

215

216

217

218

219

220

221

222

223

224

225

226

227

228

229

230

231

232

233

234

235

236

237

238

239

240

241

242

243

244

245

246

247

248

249

250

251

252

253

254

255

256

257

258

259

260

261

262

263

264

265

266

267

268

269

270

271

272

273

274

275

276

277

278

279

280

281

282

283

284

下边的该页的后台代码,为节省篇幅,仅给出进入系统按纽的代码如下:
需要注意的是因为引入了ajax所以输出提示信息的方式和以前不一样了.
1
protected void btlogin_Click(object sender, EventArgs e)
2
{
3
///取值
4
string ksh = this.tbksh.Text.Trim();
5
string code = this.tbcode.Text.Trim();
6
string yanzheng = this.tbyanzheng.Text.Trim();
7
///判断验证码
8
//提示弹出对话框需要注册客户端脚本
9
ClientScriptManager csm = this.ClientScript;
10
11
if (tbyanzheng.Text.ToLower() == quanxian.yanzhengcode())
12
{
13
///判断用户
14
ArrayList retal = kaosheng.yanzheng(ksh, code);
15
///根据返回进行跳转
16
///返回值为arrylist 其中
17
/// retal[0]存放int形式的返回值
18
/// 其中
19
/// 0:系统出错、数据库连接?
20
/// 1:已被录取
21
/// 2:登录正确
22
/// 3:首次登录需导向修改页面
23
/// 4:登录密码不对(已有但是不正确)
24
/// 5:未更改过密码,并且查分码不对
25
int backcode = Convert.ToInt16(retal[0].ToString().Trim());
26
if (backcode == 3 || backcode == 2)
27
{
28
string strip = Request.UserHostAddress;
29
kaosheng.loginlog(ksh, strip, backcode.ToString());
30
31
}
32
if (backcode == 0)
33
{
34
csm.RegisterStartupScript(this.GetType(), "Hello", "<script>alert('服务器忙,或数据连接错,请联系管理员!')</script>");
35
}
36
if (backcode == 1)
37
{
38
csm.RegisterStartupScript(this.GetType(), "Hello", "<script>alert('你已经被《" + retal[1].ToString() + "》录取,不能再填报其他志愿!')</script>");
39
}
40
if (backcode == 2)
41
{
42
//登录正确,首先准备参数数组,然后传递
43
retal[0] = "0";//标记为0代表为考生信息
44
///此时retal中存放
45
/// 标号 0 1 2 3 4 5 6 7
46
/// 包括: 0 考生号、考生姓名、 登录号 县区 地市 报名点 报名点代码
47
quanxian.buildsession(retal);
48
Response.Redirect("kszy.aspx");
49
50
}
51
if (backcode == 3)
52
{
53
//首先准备,参数,包括 ksh,name、查分、县区、地市
54
///此时retal中存放
55
/// 标号 0 1 2 3 4 5。。。
56
/// 包括: 3 考生号、考生姓名、 登录号 县区 地市。。。
57
58
//调用静态方法将数据放入session中。
59
if(quanxian.buildsession(retal)) Response.Redirect("passchange.aspx");
60
}
61
if (backcode == 4)
62
{
63
csm.RegisterStartupScript(this.GetType(), "Hello", "<script>alert('密码不正确,请联系管理员!')</script>");
64
}
65
if (backcode == 5)
66
{
67
csm.RegisterStartupScript(this.GetType(), "Hello", "<script>alert('查分密码不正确,请联系管理员!')</script>");
68
}
69
if (backcode == 6)
70
{
71
csm.RegisterStartupScript(this.GetType(), "Hello", "<script>alert('考生号输入不正确,本次操作已经被记录,请认真核对!')</script>");
72
}
73
///1、导向修改密码
74
///2、导向填报页面
75
76
}
77
else
78
{
79
//不相同则提示错误信息
80
csm.RegisterStartupScript(this.GetType(), "Hello", "<script>alert('必须输入正确的验证码!')</script>");
81
}
82
}

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

登录程序到这里就完成了.