TOMCAT的安全控制策略是根據Servlet 2.4規范來實現的。
1.在$CATALINA/conf/server.xml文件中配置:
<Realm className="org.apache.catalina.realm.UserDatabaseRealm" debug="0" resourceName="UserDatabase"/>
這里UserDatabase是一個jndi的名稱,也需要在server.xml中配置,對應于$CATALINA/conf/tomcat-users.xml文件
2.tomcat-users.xml文件里面定義了用戶和角色
<?xml version='1.0' encoding='utf-8'?>
<tomcat-users>
<role rolename="tomcat"/>
<role rolename="role1"/>
<role rolename="manager"/>
<role rolename="admin"/>
<user username="tomcat" password="tomcat" roles="tomcat"/>
<user username="both" password="tomcat" roles="tomcat,role1"/>
<user username="manager" password="tomcat" roles="manager"/>
<user username="admin" password="tomcat" roles="admin"/>
</tomcat-users>
3.在相應的應用的web.xml文件中加入<security-constraint><login-config> <security-role>標簽,如下所示:
<!-- Security is active on entire directory -->
<security-constraint>
<display-name>Tomcat Server Configuration Security Constraint</display-name>
<web-resource-collection>
<web-resource-name>Protected Area</web-resource-name>
<!-- Define the context-relative URL(s) to be protected -->
<url-pattern>/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<!-- Anyone with one of the listed roles may access this area -->
<role-name>admin</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>/login.jsp</form-login-page>
<form-error-page>/error.jsp</form-error-page>
</form-login-config>
</login-config>
<!-- Security roles referenced by this web application -->
<security-role>
<description>
The role that is required to log in to the Administration Application
</description>
<role-name>admin</role-name>
</security-role>
4.在 <login-config>標簽的<auth-method>FORM</auth-method>屬性中,可以看到這里的authentication method 設置為FORM,這是一種基于表單的用戶認證方式。基于form的用戶認證需要在<form-login-page>/login.jsp</form-login-page>定義的登陸頁面中提供一個包括用戶名和密碼的html表單,這個表單相對應于用戶名和密碼的元素必須是j_username和j_password,并且表單的ACTION必須為j_security_check。譬如:
<form method="POST" action="j_security_chack">
<input type="text" name="j_username">
<input type="password" name="j_password">
</form>
在驗證通過之后,login頁面會自動轉向該應用的默認頁面(index.html,index.jsp等等)。
除了FORM驗證方式之外,還有BASIC和CLIENT-CERT這兩種用戶認證方式,前者是基本的用戶認證方式,要求瀏覽器彈出一個對話框,錄入用戶名和密碼。后者是使用客戶數字證書來認證請求。
5.以上四步完成之后便可以通過在tomcat-users.xml文件中添加用戶和角色來實現訪問控制了。還是比較方面的。
Hibernate的主鍵生成策略有好幾種:
1) assigned
2) hilo
3) seqhilo
4) increment
5) identity
6) sequence
7) native
8) uuid.hex
9) uuid.string
10) foreign
一般而言,利用uuid.hex方式生成主鍵將提供最好的性能和數據庫平臺適
應性。另外由于常用的數據庫,如Oracle、DB2、SQLServer、MySql 等,都提
供了易用的主鍵生成機制(Auto-Increase 字段或者Sequence)。我們可以在數
據庫提供的主鍵生成機制上,采用generator-class=native的主鍵生成方式。
不過值得注意的是,一些數據庫提供的主鍵生成機制在效率上未必最佳,
大量并發insert數據時可能會引起表之間的互鎖。
數據庫提供的主鍵生成機制,往往是通過在一個內部表中保存當前主鍵狀
態(如對于自增型主鍵而言,此內部表中就維護著當前的最大值和遞增量),
之后每次插入數據會讀取這個最大值,然后加上遞增量作為新記錄的主鍵,之
后再把這個新的最大值更新回內部表中,這樣,一次Insert操作可能導致數據
庫內部多次表讀寫操作,同時伴隨的還有數據的加鎖解鎖操作,這對性能產生
了較大影響。
因此,對于并發Insert要求較高的系統,推薦采用uuid.hex 作為主鍵生成
機制。
另外我們可以擴展Hibernate的類來做自己的主鍵生成策略:
java 代碼這個類必須要擴展AbstractUUIDGenerator并實現Configurable接口,在generate方法中生成我們想要的主鍵。
- package com.gsta.eshore.framework.util.uid;
- import java.io.Serializable;
- import org.hibernate.engine.SessionImplementor;
- import org.hibernate.id.AbstractUUIDGenerator;
- import org.hibernate.id.Configurable;
- import org.hibernate.id.IdentifierGenerator;
- import java.util.Properties;
- import org.hibernate.Hibernate;
- import org.hibernate.dialect.Dialect;
- import org.hibernate.type.Type;
- import org.hibernate.util.PropertiesHelper;
- /**
- * <b>uuid</b><br>
- * @author hwq
- */
- public class UIDGenerator extends AbstractUUIDGenerator implements Configurable {
- private static long lastTime = System.currentTimeMillis();
- private static short lastCount = -32768;
- private static Object mutex = new Object();
- private static long ONE_SECOND = 1000L;
- private String sep = "";
- public Serializable generate(SessionImplementor session, Object obj) {
- long l = 0L;
- short word0 = 0;
- int i = 0;
- synchronized(mutex)
- {
- if(lastCount == 32767)
- {
- for(boolean flag = false; !flag;)
- {
- l = System.currentTimeMillis();
- if(l < lastTime + ONE_SECOND)
- {
- try
- {
- Thread.currentThread();
- Thread.sleep(ONE_SECOND);
- }
- catch(InterruptedException interruptedexception) { }
- } else
- {
- lastTime = l;
- lastCount = -32768;
- flag = true;
- }
- }
- } else
- {
- l = lastTime;
- }
- word0 = lastCount++;
- i = getHostUniqueNum();
- }
- String s = Integer.toString(i, 16) + sep + Long.toString(l, 16) + sep + Integer.toString(word0, 16);
- if(s.length() > 24)
- s = s.substring(s.length() - 24);
- return s;
- }
- public Serializable generate_old(SessionImplementor session, Object obj) {
- String name = obj.getClass().getName();
- return new StringBuffer(64)
- .append(name.substring(name.lastIndexOf('.')+1)).append(sep)
- .append((short)getIP()).append(sep)
- .append(Math.abs((short)getJVM())).append(sep)
- .append(getCount())
- .toString();
- }
- private static int getHostUniqueNum()
- {
- return (new Object()).hashCode();
- }
- public void configure(Type type, Properties params, Dialect d) {
- sep = PropertiesHelper.getString("separator", params, "");
- }
- public static void main( String[] args ) throws Exception {
- Properties props = new Properties();
- props.setProperty("separator", "");
- IdentifierGenerator gen = new UIDGenerator();
- ( (Configurable) gen ).configure(Hibernate.STRING, props, null);
- IdentifierGenerator gen2 = new UIDGenerator();
- ( (Configurable) gen2 ).configure(Hibernate.STRING, props, null);
- for ( int i=0; i<10; i++) {
- String id = (String) gen.generate(null, gen);
- System.out.println(id);
- String id2 = (String) gen2.generate(null, gen2);
- System.out.println(id2);
- }
- }
- }
在hibernate的配置文件中要做以下的配置:
xml 代碼Generator的類要引用UIDGenerator,并且可以帶參數生成主鍵,示例是根據時間,Ip等生成一個24位的字符串。這樣做的靈活性大大提高了,提供了最好的性能和數據庫平臺適應性。
- <id name="id" type="java.lang.String">
- <column name="id" length="24" />
- <generator class="com.gsta.eshore.framework.util.uid.UIDGenerator"><param name="separator">-</param></generator>
- </id>
但是有時候我們在保存一條記錄的時候是不能指定主鍵的,因為它的主鍵要來源于其他的表的主鍵,(hibernate推薦用代理主鍵,但是有時候設計的時候沒有用到)。這個時候的主鍵生成策略就要是assigned了。為了保持主鍵的連貫性,我總不能又用另外一種主鍵生成策略吧。
仿照上面的類,我們做一個生成24為隨機字符串的類。
java 代碼在save一個實體的時候調用entity.setId(UID.getUID())。
- package com.gsta.eshore.framework.util.uid;
- public class UID
- {
- private static long lastTime = System.currentTimeMillis();
- private static short lastCount = -32768;
- private static Object mutex = new Object();
- private static long ONE_SECOND = 1000L;
- public UID()
- {
- }
- public static String getUID()
- {
- long l = 0L;
- short word0 = 0;
- int i = 0;
- synchronized(mutex)
- {
- if(lastCount == 32767)
- {
- for(boolean flag = false; !flag;)
- {
- l = System.currentTimeMillis();
- if(l < lastTime + ONE_SECOND)
- {
- try
- {
- Thread.currentThread();
- Thread.sleep(ONE_SECOND);
- }
- catch(InterruptedException interruptedexception) { }
- } else
- {
- lastTime = l;
- lastCount = -32768;
- flag = true;
- }
- }
- } else
- {
- l = lastTime;
- }
- word0 = lastCount++;
- i = getHostUniqueNum();
- }
- String s = Integer.toString(i, 16) + "`" + Long.toString(l, 16) + "`" + Integer.toString(word0, 16);
- if(s.length() > 24)
- s = s.substring(s.length() - 24);
- return s;
- }
- private static int getHostUniqueNum()
- {
- return (new Object()).hashCode();
- }
- public static void main(String[] args) {
- for (int i = 0; i < 100; i++) {
- String uid=getUID();
- System.out.println(uid);
- }
- }
- }
呵呵,以后用hibernate就不用煩用什么主鍵生成策略了,自己做一個。