昨天和Tomcat奋战了整整8个钟头,23:30才搞定它。
目的:
使用Servlet2.3规定的Realm功能实现WEB程序的登录,将role控制在web.xml中申明。
方法:
1、在mysql中创建用户数据库
2、按照tomcat4.1.30的《JNDI DataSource HOW-TO》说明配置DBCP
3、按照tomcat4.1.30的《Realm HOW-TO》说明配置Realm
4、在web.xml中申明security-constraint
项目Context文件如下:
<!--
Context configuration file for the TEST Web App
-->
<Context path="/tps"
docBase="D:/projects/work/test/workspace"
debug="0"
privileged="true">
<Resource name="jdbc/myds"
auth="Container"
type="javax.sql.DataSource" />
<ResourceParams name="jdbc/myds">
<parameter>
<name>factory</name>
<value>org.apache.commons.dbcp.BasicDataSourceFactory</value>
</parameter>
<!-- Maximum number of dB connections in pool. Make sure you
configure your mysqld max_connections large enough to handle
all of your db connections. Set to 0 for no limit.
-->
<parameter>
<name>maxActive</name>
<value>100</value>
</parameter>
<!-- Maximum number of idle dB connections to retain in pool.
Set to 0 for no limit.
-->
<parameter>
<name>maxIdle</name>
<value>30</value>
</parameter>
<!-- Maximum time to wait for a dB connection to become available
in ms, in this example 10 seconds. An Exception is thrown if
this timeout is exceeded. Set to -1 to wait indefinitely.
-->
<parameter>
<name>maxWait</name>
<value>10000</value>
</parameter>
<parameter>
<name>driverClassName</name>
<value>com.mysql.jdbc.Driver</value>
</parameter>
<parameter>
<name>url</name>
<value>jdbc:mysql://localhost/tps?autoReconnect=true</value>
</parameter>
<parameter>
<name>username</name>
<value>test</value>
</parameter>
<parameter>
<name>password</name>
<value>test</value>
</parameter>
</ResourceParams>
<Realm className="org.apache.catalina.realm.DataSourceRealm"
debug="99"
dataSourceName="java:/comp/env/jdbc/myds"
userTable="realms"
userNameCol="username"
userCredCol="password"
userRoleTable="realms"
roleNameCol="role" />
</Context>
web.xml如下:
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">
<!--
- Web app deployment descriptor that loads both a root application context
- and an "test" DispatcherServlet with a specific context.
-
- Any number of additional DispatcherServlets can be added.
-
- Depends on the following libraries in WEB-INF/lib:
- * spring.jar
- * commons-logging.jar
- * log4j-1.2.x.jar
-->
<web-app>
<!--
- Key of the system property that should specify the root directory of this
- web app. Applied by WebAppRootListener or Log4jConfigListener.
-->
<context-param>
<param-name>webAppRootKey</param-name>
<param-value>test.webapp.root</param-value>
</context-param>
<!--
- Location of the Log4J config file, for initialization and refresh checks.
- Applied by Log4jConfigListener.
-->
<context-param>
<param-name>log4jConfigLocation</param-name>
<param-value>/WEB-INF/classes/log4j.properties</param-value>
</context-param>
<!--
- Location of the XML file that defines the root application context
- Applied by ContextLoaderListener.
-->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext-hibernate.xml</param-value>
</context-param>
<!--
- Configures Log4J for this web app.
- As this context specifies a context-param "log4jConfigLocation", its file path
- is used to load the Log4J configuration, including periodic refresh checks.
-
- Would fall back to default Log4J initialization (non-refreshing) if no special
- context-params are given.
-
- Exports a "web app root key", i.e. a system property that specifies the root
- directory of this web app, for usage in log file paths.
- This web app specifies "test.webapp.root" (see log4j.properties file).
-->
<listener>
<listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
</listener>
<!--
- Loads the root application context of this web app at startup,
- by default from "/WEB-INF/applicationContext.xml".
- Use WebApplicationContextUtils.getWebApplicationContext(servletContext)
- to access it anywhere in the web application, outside of the framework.
-
- The root context is the parent of all servlet-specific contexts.
- This means that its beans are automatically available in these child contexts,
- both for getBean(name) calls and (external) bean references.
-->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!--
- Servlet that dispatches request to registered handlers (Controller implementations).
- Has its own application context, by default defined in "{servlet-name}-servlet.xml",
- i.e. "example-servlet.xml".
-
- A web app can contain any number of such servlets.
- Note that this web app has a shared root application context, serving as parent
- of all DispatcherServlet contexts.
-->
<servlet>
<servlet-name>test</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<!--
- Maps the example dispatcher to /example/*. All handler mappings in
- example-servlet.xml will by default be applied to this subpath.
- If a mapping isn't a /* subpath, the handler mappings are considered
- relative to the web app root.
-
- A single dispatcher could get mapped to multiple paths, like any servlet.
-->
<servlet-mapping>
<servlet-name>test</servlet-name>
<url-pattern>/test/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>test</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
<security-constraint>
<web-resource-collection>
<web-resource-name>Operator Area</web-resource-name>
<url-pattern>*.jsp</url-pattern>
<url-pattern>*.do</url-pattern>
<url-pattern>*.html</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>operator</role-name>
</auth-constraint>
</security-constraint>
<!-- Login configuration uses form-based authentication -->
<login-config>
<auth-method>FORM</auth-method>
<realm-name>Tomcat Server Configuration Form-Based Authentication Area</realm-name>
<form-login-config>
<form-login-page>/auth/login.do</form-login-page>
<form-error-page>/auth/error.do</form-error-page>
</form-login-config>
</login-config>
<!-- Security roles referenced by this web application -->
<security-role>
<role-name>admin</role-name>
</security-role>
<security-role>
<role-name>operator</role-name>
</security-role>
</web-app>
然后将test.xml拷贝到tomcat4.1.30_home/webapps下,启动tomcat4.1.30开始测试
问题:
登录总是失败,检查tomcat4.1.30_home/logs发现发生异常javax.naming.NameNotFoundException: Name java: is not bound in this Context
解决方法:
经过漫长的各种尝试,和在google上的搜索,发现tomcat5.0的《Realm HOW-TO》在DataSourceRealn中增加了一个参数localDataSource,说置成true才可以支持在context中申明的DataSource。经过试验后成功。看来tomcat4.1.30无法支持在context元素中申明的Datasource。
附上在tomcat5.0.25上配置成功的context文件,web.xml没有变化。context文件不在拷贝到webapps中而是拷贝到jakarta-tomcat-5.0.25\conf\Catalina\localhost上。Realm中申明的dataSourceName必须是相对于java:/comp/env的
<!--
Context configuration file for the TPS Web App
-->
<Context path="/tps"
docBase="D:/projects/work/wapgw/tps/workspace/tps2"
debug="0"
privileged="true">
<Resource name="jdbc/myds"
auth="Container"
type="javax.sql.DataSource" />
<ResourceParams name="jdbc/myds">
<parameter>
<name>factory</name>
<value>org.apache.commons.dbcp.BasicDataSourceFactory</value>
</parameter>
<!-- Maximum number of dB connections in pool. Make sure you
configure your mysqld max_connections large enough to handle
all of your db connections. Set to 0 for no limit.
-->
<parameter>
<name>maxActive</name>
<value>100</value>
</parameter>
<!-- Maximum number of idle dB connections to retain in pool.
Set to 0 for no limit.
-->
<parameter>
<name>maxIdle</name>
<value>30</value>
</parameter>
<!-- Maximum time to wait for a dB connection to become available
in ms, in this example 10 seconds. An Exception is thrown if
this timeout is exceeded. Set to -1 to wait indefinitely.
-->
<parameter>
<name>maxWait</name>
<value>10000</value>
</parameter>
<parameter>
<name>driverClassName</name>
<value>com.mysql.jdbc.Driver</value>
</parameter>
<parameter>
<name>url</name>
<value>jdbc:mysql://localhost/tps?autoReconnect=true</value>
</parameter>
<parameter>
<name>username</name>
<value>tps</value>
</parameter>
<parameter>
<name>password</name>
<value>tps</value>
</parameter>
</ResourceParams>
<Realm className="org.apache.catalina.realm.DataSourceRealm"
debug="99"
dataSourceName="jdbc/myds"
localDataSource="true"
userTable="realms"
userNameCol="username"
userCredCol="password"
userRoleTable="realms"
roleNameCol="role" />
</Context>