公司用WSS3.0做内部协同,但是由于很多分公司在外地,所以协同网站必须在公网上,为了提高安全性和更好的分区域管理,所以要给WSS增加一个用户于IP绑定的功能,这个任务光荣地落到我的头上,结果查遍Google,Baidu无果,只好自力更生。想到的第一个方法是做一个WebPart,在WebPart检测登录的用户名,然后与数据库里的绑定表作对比。不过转念一想WebPart需要部署且要加了的页面才能起作用,整个网站集几十个站点,累也能累死。最后决定自己写一个HttpModule加上去,然后在AuthorizeRequest 事件里来验证。至于验证的过程到是很简单,只需要在数据库里比对一下就行了。
由于采用的Form认证,所以在aspnetdb数据库里增加一个绑定表,就两个列,UserAccount和IpAddr,因为不存在范围之类的所以直接用字符串的形式存储IP。
HttpModule很好写,为了避免每次都读取数据库,在第一次验证成功就生成Cookie,之后检测到Cookie就不再验证了。之前想过用Cache,不过Cache和Application一个级别的,用Session又太麻烦,于是用Cookie,最后代码如下:
<!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>-->
1
public
class
UserProvider:IHttpModule
2
{
3
4
private
HttpApplication ctx;
5
private
String User;
6
#region
IHttpModule 成员
7
8
public
void
Dispose()
9
{
10
ctx
=
null
;
11
//
throw new Exception("The method or operation is not implemented.");
12
}
13
14
public
void
Init(HttpApplication context)
15
{
16
ctx
=
context;
17
context.AuthorizeRequest
+=
new
EventHandler(context_AuthorizeRequest);
18
19
}
20
21
void
context_AuthorizeRequest(
object
sender, EventArgs e)
22
{
23
try
24
{
25
User
=
ctx.User.Identity.Name.ToLower();
26
if
(User
!=
null
&&
User.Length
>
1
)
27
{
28
if
(ctx.Context.Request.Cookies[
"
AuthIP
"
]
==
null
)
29
{
30
SqlConnection conn
=
new
SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings[
"
LocalSqlServer
"
].ConnectionString);
31
string
IP
=
"
0.0.0.0
"
;
32
string
UIP
=
""
;
33
using
(conn)
34
{
35
conn.Open();
36
SqlCommand cmd
=
new
SqlCommand(
"
SELECT [UserAccount],[IPAddr] FROM [aspnetdb].[dbo].[IPLock] WHERE [UserAccount] = @P
"
, conn);
37
cmd.Parameters.Add(
"
@P
"
, SqlDbType.VarChar,
50
).Value
=
User;
38
SqlDataReader sd
=
cmd.ExecuteReader();
39
if
(sd.Read())
40
{
41
IP
=
sd[
"
IpAddr
"
].ToString();
42
}
43
conn.Close();
44
45
UIP
=
ctx.Request.UserHostAddress;
46
if
(
!
IP.Equals(
"
0.0.0.0
"
))
47
{
48
if
(
!
IP.Equals(UIP))
49
{
50
throw
new
Exception(
"
IP地址被禁止
"
+
User
+
"
:
"
+
IP);
51
}
52
}
53
ctx.Response.Cookies.Add(
new
HttpCookie(
"
AuthIP
"
));
54
ctx.Response.Cookies[
"
AuthIP
"
].Value
=
"
OK
"
;
55
ctx.Response.Cookies[
"
AuthIP
"
].Expires
=
DateTime.Now.AddDays(
1
);
56
}
57
}
58
}
59
}
60
catch
(Exception ex)
61
{
62
throw
ex;
63
}
64
65
}
66
67
#endregion
68
}
不过在Web.Config里加载上这个模块后直接报错了。显示 SqlClientPermission 的权限有问题,看来在这里访问数据库还是有问题,WSS应该对代码的安全性做了限制,查了查Web.Config.看到:
<!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>-->
1
<
securityPolicy
>
2
<
trustLevel name
=
"
WSS_Medium
"
policyFile
=
"
C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\12\config\wss_mediumtrust.config
"
/>
3
<
trustLevel name
=
"
WSS_Minimal
"
policyFile
=
"
C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\12\config\wss_minimaltrust.config
"
/>
4
<
trustLevel name
=
"
WSS_Custom
"
policyFile
=
"
C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\12\config\wss_custom_wss_minimaltrust.config
"
/>
5
</
securityPolicy
>
看来是在这里设置的了。找到<trust level="WSS_Custom" originUrl="" /> 发现当前WSS使用的WSS_Custom这个配置,于是就到C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\12\config\ 找到Wss_Custom_wss_minimaltrust.config文件
看了下发现里面确实没有关于Sqlclient的配置,本来想就地添加,不过转念一想自己动手怕将来要修改的地方太多太杂,于是继续看了下另外两个config文件,最后在wss_mediumtrust.config 里找到了SqlClint相关的配置,于是最后将trust节点改成<trust level="WSS_Medium" originUrl="" />
打开页面看看,OK,搞定收工。
[本代码乃Demo,与公司内部使用的代码与逻辑均不相同,特此声明]