控制客户端(一般为浏览器)访问服务器资源的方法
(方法1)如果只有少量的页面需要控制,可以通过jsp标签完成访问检查。
<% taglib uri="/WEB-INF/corej2eelib.tld" prefix="corePatterns" %>
<corePatterns:guard/>
<html>
..........
</html>
在这个标签中,如果用户没有权限,可以直接forward到诸如"你没有权限"之类的页面
(方法2)以上的访问控制还可以针对页面中的部分代码,这样页面可能就变成下面这个样子
<% taglib uri="/WEB-INF/corej2eelib.tld" prefix="corePatterns" %>
不要保护的代码
<corePatterns:guard>
要保护的代码
</corePatterns:guard>
不要保护的代码
这种情况可以有很多种变化,比如根据用户的角色来决定是否需要保护,或者根据系统的某个状态来显示不同的内容,这些都可以通过传入参数变量给标签来完成。
以上两种控制方法都是通过jsp的标签来实现的,具体关于标签的设置可以参考sun的j2ee教程14 15章,网址如下:
http://java.sun.com/j2ee/1.4/docs/tutorial/doc/index.html,还可以通过看tomcat里自带的一些标签的例子来学习。
(方法3)通过一个简单、通用的配置实现资源保护
如果你想限制客户端访问某些资源,比如jsp页面,你可以把它放到web应用的/WEB-INF/目录下即可,这样,一个servlet控制器仍然能够把请求转发给该资源,而通过浏览器直接访问URL就无法访问到了。
(方法4)通过标准安全限制(或者web容器内置安全技术)来实现对资源的保护
servlet技术规定,对于URL的映射访问,我们可以设定必须通过容器的安全角色控制,这里我们以tomcat 5.0.28为例:我们看tomcat的manager应用程序中(tomcat目录/server/webapps/)中关于web.xml的配置
<security-constraint>
<web-resource-collection>
<web-resource-name>HTMLManger and Manager command</web-resource-name>
<url-pattern>/jmxproxy/*</url-pattern>
<url-pattern>/html/*</url-pattern>
<url-pattern>/list</url-pattern>
<url-pattern>/sessions</url-pattern>
<url-pattern>/start</url-pattern>
<url-pattern>/stop</url-pattern>
<url-pattern>/install</url-pattern>
<url-pattern>/remove</url-pattern>
<url-pattern>/deploy</url-pattern>
<url-pattern>/undeploy</url-pattern>
<url-pattern>/reload</url-pattern>
<url-pattern>/save</url-pattern>
<url-pattern>/serverinfo</url-pattern>
<url-pattern>/status/*</url-pattern>
<url-pattern>/roles</url-pattern>
<url-pattern>/resources</url-pattern>
</web-resource-collection>
<auth-constraint>
<!-- NOTE: This role is not present in the default users file -->
<role-name>manager</role-name>
</auth-constraint>
</security-constraint>
<web-resource-collection>
<web-resource-name>HTMLManger and Manager command</web-resource-name>
<url-pattern>/jmxproxy/*</url-pattern>
<url-pattern>/html/*</url-pattern>
<url-pattern>/list</url-pattern>
<url-pattern>/sessions</url-pattern>
<url-pattern>/start</url-pattern>
<url-pattern>/stop</url-pattern>
<url-pattern>/install</url-pattern>
<url-pattern>/remove</url-pattern>
<url-pattern>/deploy</url-pattern>
<url-pattern>/undeploy</url-pattern>
<url-pattern>/reload</url-pattern>
<url-pattern>/save</url-pattern>
<url-pattern>/serverinfo</url-pattern>
<url-pattern>/status/*</url-pattern>
<url-pattern>/roles</url-pattern>
<url-pattern>/resources</url-pattern>
</web-resource-collection>
<auth-constraint>
<!-- NOTE: This role is not present in the default users file -->
<role-name>manager</role-name>
</auth-constraint>
</security-constraint>
<!-- Define the Login Configuration for this Application -->
<login-config>
<auth-method>BASIC</auth-method>
<realm-name>Tomcat Manager Application</realm-name>
</login-config>
<login-config>
<auth-method>BASIC</auth-method>
<realm-name>Tomcat Manager Application</realm-name>
</login-config>
上面的配置把对manager这个应用程序中需要保护的资源加上了角色控制,只有获取该角色才可以访问这些URL,在manager.xml中,我们可以看到
<ResourceLink name="users" global="UserDatabase"
type="org.apache.catalina.UserDatabase"/>
type="org.apache.catalina.UserDatabase"/>
这样的一段配置,就表示manager这个应用程序引用了全局资源UserDatabase,在tomcat目录/conf/server.xml的配置里可以找到这样的一段资源
<Resource name="UserDatabase" auth="Container"
type="org.apache.catalina.UserDatabase"
description="User database that can be updated and saved">
</Resource>
<ResourceParams name="UserDatabase">
<parameter>
<name>factory</name>
<value>org.apache.catalina.users.MemoryUserDatabaseFactory</value>
</parameter>
<parameter>
<name>pathname</name>
<value>conf/tomcat-users.xml</value>
</parameter>
type="org.apache.catalina.UserDatabase"
description="User database that can be updated and saved">
</Resource>
<ResourceParams name="UserDatabase">
<parameter>
<name>factory</name>
<value>org.apache.catalina.users.MemoryUserDatabaseFactory</value>
</parameter>
<parameter>
<name>pathname</name>
<value>conf/tomcat-users.xml</value>
</parameter>
</ResourceParams>
现在清楚了,其实就是manager应用程序要用到tomcat目录/conf/tomcat-users.xml里的用户,只有具备manager角色的用户才可以访问限制资源的,tomcat-users.xml默认是没有这样的用户的,我们加上两行
<role rolename="manager"/>
<user username="manager" password="manager" roles="manager"/>
这样重启tomcat,我们就可以使用manager这个用户访问manager应用程序了。
除了以上讲到的4种方法以外,控制客户端访问还要防止重复的表单提交(用户通过刷新或回退重复,要防止这种情况)。
防止的原理是这样的:在用户进入表单页面的时候生成一个随机的数字,并赋值给一个session,并写入一个隐藏控件在处理提交数据的页面判断传入的隐藏控件的值是否等于session的值。
相等表明允许提交,否则不允许提交,其中最重要的一步是处理提交的数据成功后清空session,这样他反复提交过来的页面,隐藏控件的值是存在的,而session为空,就不允许提交了。
相等表明允许提交,否则不允许提交,其中最重要的一步是处理提交的数据成功后清空session,这样他反复提交过来的页面,隐藏控件的值是存在的,而session为空,就不允许提交了。
一般的web框架都会有处理重复提交的机制,比如struts,Struts中该方法的基本原理是:服务器端在处理到达的request之前,会将request中的Token值与保存在当前用户session中的令牌值进行比较,看是否匹配。在处理完该 request后,且在response发送给客户端之前,将会产生一个新的 Token,该Token除传给客户端以外,也会将用户session中保存的旧的Token进行替换。这样,如果用户会退到刚才的提交页面并再次提交的话,客户端传过来的Token值和服务器端的不一致,从而有效地防止了重复提交的发生。