(8) tomcat中管理領域、角色及用戶


srverlet Container或web應用程序本身都可以提供控制web應用程序資源的安全防護

前者稱為容器管理的安全防護,或者稱為應用程序管理安全防護

通過內嵌機制,tomcat提供一些安全防護方法,這是一種“容器管理”的安全防護。另一方面如果有一系列具有自己的登錄機制的servlet和JSP,則視為應用程序管理的安全防護。

不管是哪種安全防護類型,都是用稱之為領域(realm)的組來管理用戶和密碼。

下面將介紹conf/server.conf中領域的配置(定義了如何存儲用戶與角色信息),以及web應用程序的WEB_INF/web.xml中的<security-constraint>(如何對webapp的用戶進行授權)

一、領域的配置

Tomcat含有可插入式的領域架構,且具備多種有用的領域實現:

  1. UserDatabaseReal
  2. JDBCRealm
  3. JNDIRealm
  4. JAASRealm
  5. DataSourceRealm
  6. MemoryRealm
  7. CombinedRealm
  8. LockOutRealm

Java開發者可創建額外的領域實現,以便作為與其用戶和密碼的接口。如欲指定使用何種領域,在server.conf配置文件中插入Realm元素,以className屬性設定要使用的領域,然后通過 該實現的自定義屬性以提供此領域相關的配置信息:

<Realm className="SOME.REALM.IMPLEMENTATION.CLASSNAME"
CUSTOMATRRIBUTION1="SOME CUSTOM VALUE"
CUSTOMATTRIBUTION2="SOME OTHER CUSTOM VALUE"/>

后面的realm配置可以覆蓋前面

每種不同的Realm 采用了不同的用戶名和密碼存儲和使用方式,tomcat默認使用的是UserDatabaseRealm

1、UserDatabaseRealm

UserDatabaseRealm是從靜態文件加載到內存中,且直到tomcat停止后才從內存中清除。事實上,tomcat所用的用戶、密碼及角色只存在於內存中。換句話說,權限文件只會在啟動時,讀入一次,在UserDatabaseRealm中分配權限的默認文件為$CATALINA_HOME/conf/tomcat-user.xml(如果更改了tomcat-user.xml文件但沒有重啟tomcat,則除非重啟tomcat,否則tomcat不會重啟讀入該文件)

tomcat-user.xml文件是使用該領域的關鍵。它包含一份可訪問web應用程序的用戶清單。該文件是一個簡單的xml文件,根元素是tomcat-users,且只能使用role和user元素。
每個role元素只有一個屬性:rolename。
而每個user元素則有3個屬性:username、password及roles

role元素:定義rolename,即角色名稱,可以定義多個

user元素:定義username用戶名、password密碼、roles使用上述的哪個角色多個角色名稱之間使用逗號分隔),可以定義多個

 

 

UserDatabaseRealm是基於MemoryRealm擴展出來的,默認是讀取tomcat-users.xml(可通過Resource中的pathname屬性配置為其它文件)里面配置的用戶角色信息。

server.xml中的默認配置如下:

 

不過他是通過應用jndi的方式實現的,從設計上支持多種實現方式,默認采用了類似MemoryRealm的實現方式,但是又對其進行了擴展,主要是增加了用戶組”的概念,即用戶除了有所屬角色外,還可以有所屬用戶組”,用戶組可以關聯其它多個角色,例如它可以使用下面的tomcat-users.xml配置:

  <role rolename="tomcat"/>

  <role rolename="admin"/>

  <user username="tomcat" password="tomcat" roles="tomcat"/>

  <group groupname="one"  roles="tomcat"/>

  <user username="admin" password="admin" roles="admin" groups="one"/>

 

admin用戶由於關聯了“one”這個用戶組,“one”用戶組包含角色“tomcat”,所以admin用戶就擁有了“tomcat”角色。

這個安全域的配置:
1. sever.xml的GlobalNamingResources節點下添加:

<Resource  name="UserDatabase"  auth="Container"

              type="org.apache.catalina.UserDatabase"

              description="User database that can be updated and saved"

              factory="org.apache.catalina.users.MemoryUserDatabaseFactory"

              pathname="conf/tomcat-users.xml" />

 

2.在Engine中啟用該安全域的配置:

 

<Realm className="org.apache.catalina.realm.UserDatabaseRealm"

               resourceName="UserDatabase"/>

 <Realm/>元素可以:
放在<Engine/>元素中,這時該Realm會被所有應用共享。
放在<Host/>元素中,會被該Host下的應用程序共享。
放在<Context/>元素中,則只有對應的應用程序能被訪問

 

 2、JDBCRealm  

相對於UserDataBaseRealm而言,JDBCRealm具有更大潛在的靈活性,並能動態訪問數據,基本上是使用關系型數據庫的領域。這個Realm是基於數據庫的,數據庫中保存了用戶名/密碼和用戶的角色,通過建立數據庫的通信來維持用戶角色信息
1. 所需要的數據庫腳本

create table users (

  user_name        varchar(15) not null primary key,

  user_pass         varchar(15) not null

);

 

create table user_roles (

  user_name         varchar(15) not null,

  role_name         varchar(15) not null,

  primary key (user_name, role_name)

);

 

insert into  users( user_name , user_pass )  values ( 'admin','admin')

insert into  users( user_name , user_pass )  values ( 'tomcat','admin')

insert into  user_roles(user_name,role_name)  values ( 'admin','admin')

insert into  user_roles(user_name,role_name)  values ( 'tomcat','tomcat')

 

2.修改tomcat中server.xml添加安全域配置(必須做,設置JDBC的連接參數設成領域的屬性,也可以在webapp的context配置文件中配置):

<Realm className="org.apache.catalina.realm.JDBCRealm"

   connectionName="sa"

   connectionPassword=""

   connectionURL="jdbc:h2:tcp://localhost//home/conquer/mine/work_space/h2-dbpath/tomcat"

   driverName="org.h2.Driver"

   userTable="users"   userNameCol="user_name"   userCredCol="user_pass"

   userRoleTable="user_roles"   roleNameCol="role_name"/>

</Realm>

領域屬性詳解:

className             此Realm實現的java類名,對JDBC而言,必須是org.apache.catalina.realm.JDBCRealm

connectionName            用來建立JDBC連接數據的用戶名

connectionPassword       用來建立JDBC連接的數據庫密碼

connectionURL             用來建立JDBC連接的數據庫URL

digest                           摘要算法(SHA、MD2或只有MD5),默認值是cleartext

driverName                  JDBC驅動程序的java類名

roleNameCol                含有角色名(指定給用戶)的角色表中的字段名

userNameCol                在用戶與角色數據表中,列出用戶名的字段名

userCredCol                  在用戶數據表中,列出用戶密碼的字段名

userRoleTable               將角色映射至用戶的數據表名

userTable                      列出用戶與密碼的數據表名

注意事項:

在配置Tomcat的JDBCRealm的時候,有幾個應該注意的地方
1). 數據庫JDBC驅動應該放在${tomcat.home}/server/lib目錄下,而不能放在webapps的lib目錄下,二者的class loader不同
2). tomcat在啟動時只會自動裝載后綴為.jar的jar包,因此如果使用oracle9i的驅動,應把class12.zip改名為class12.jar
3). 最好將JDBCRealm的配置信息放在webapp的context配置文件中,而不要放在server.xml

4)<Realm/>元素可以放在<Engine/>元素中,這時該Realm會被所有應用共享。
放在<Host/>元素中,會被該Host下的應用程序共享。
放在<Context/>元素中,則只有對應的應用程序能被訪問

 

 3、JNDIRealm

 

如果讓tomcat從LDAP目錄中獲取用戶名稱、密碼及角色,可使用JNDIRealm。

JNDIRealm是非常有彈性的Realm實現,可以依據用戶名、密碼及角色的LDAP目錄來驗證用戶的身份,同時還允許該數據用於許多不同的模式布局。

JNDIRealm可遞歸地搜索LDAP層次目錄,直到找到所需要的信息為止,

或者可以設定在目錄服務器的特定位置中查找
可以將密碼存儲為明碼形式,並使用基本驗證,或存儲層摘要編碼形式,而使用摘要驗證法

 

其它示例:

 

 

領域屬性詳解:

className                     此領域實現的Java類名,對於JNDIRealm,必須是org.apache.catalina.realm.JNDIRealm

connectionName           用來驗證只讀的LDAP連接的用戶名,如果未設定則會建立匿名連接

connectionPassword    用來建立只讀的LDAP連接密碼

connectionURL              用來建立LDAP連接的目錄URL

conetextFactory             用於此連接的JNDI程序廠商的完全限定的java類名,如果未設定則使用默認的JNDI LDAP提供商類

digest                              摘要算法(SHA、MD2或MD5),默認值是cleartext

 

roleBase                         查詢角色信息的LDAP基本目錄條目,如果未指定,默認使用目錄范圍中的頂層元素

roleName                        搜尋包含角色名的領域屬性名,此屬性可與userRoleName合並使用,若未指定,則只會從用戶的目錄中取得角色

userRoleName               用戶目錄中包含關聯用戶角色名的屬性名,含有此用戶角色名稱的用戶目錄中的屬性名稱。
                                        此屬性可與roleName合並使用。如果未設定,則用戶的所有角色都來自角色搜索

roleSubtree                    如果想要用戶相關的角色的roleBase中以遞歸方式檢索設定的元素的子樹,則需要設為true。
                                        如果未設定,則導致默認值false只會搜尋最上層(非遞歸方式的搜尋)

 

userPattern                    用戶目錄識別名(DN,distinguished name)的樣式,遵從java.text.MessageFormat的語法,用{0}標記插入的實際用戶名

userPassword               屬性名,用戶目錄中包含的用戶口令。

如果設定此值,則JNDIRealm會用connectionName與connectionPassword屬性的指定值綁定至目錄,並從目錄服務器中獲取對應的口令屬性,以便與正在被驗證的用戶指定的屬性值比對。如果設定了digest屬性,則在比對用戶提供的密碼與獲取自目錄服務器的屬性值之前,會先對改密碼應用摘要算法;如果未設定則JNDIRealm會以用戶目錄的DN以及用戶指定的密碼嘗試單純第綁定至目錄

userBase                       設定以userSearch表達式搜尋用戶的基本元素。如果未設定,則會使用目錄范圍中的頂層元素;如果使用userPattern表達式,則會忽略此屬性

userSearch                    當搜索用戶目錄時,所有的LDAP過濾表達式,以{0}標記實際插入用戶名的位置,
                                        使用此屬性(以及userBase和userSubtree屬性)代替userPattern屬性,從目錄中檢索用戶目錄

userSubtree                   如果想遞歸檢索用戶目錄的userBase屬性指定的元素子樹,則需要設置該值為true
                                         默認為false,導致僅檢索元素子樹的頂層(非遞歸檢索)。如果使用userPattern表達式,則會忽略此屬性

 

 4、JAAS Realm

 

這個是基於java的jaas認證和授權服務而設計的,主要就是用到了jaas的“認證”部分,不涉及“授權”,通過向javax.security.auth.Subject#getPrincipals()里面添加用戶和角色來完成用戶和角色的認證

注意這里的技巧在於,tomcat要在server.xml的該安全域里配置哪些java類型的Principal表示用戶,哪些java類型的Principal表示角色,因為jaas的登錄模塊在驗證成功后只能將用戶和角色信息都放入到javax.security.auth.Subject#getPrincipals(),通過事先的類型約定來讓tomcat識別用戶和角色信息。

JAAS實現了標准的“可插入式驗證模塊”(PAM)架構,此架構可讓應用程序獨立於驗證實現之外,可不經修改應用程序應用程序本身而只需稍微修改應用程序配置設定,在應用程序中插入全新或更新的驗證實現(此時為Tomcat),如依據unix的用戶/密碼/組 數據庫,可使用配置好的JAASRealm,驗證用戶身份,然后更改配置設定,而不需要更改整個領域實現即可重新設定成依據Kerberos來驗證。

除此之外,JAAS還支持堆棧式的驗證模塊,從而在一個驗證堆棧中,兩個或三個驗證模塊可以彼此協同使用。對插入式模塊進行堆棧處理,允許實現tomcat尚未實現的自定義驗證邏輯


這個安全域的配置如下:

<Realm  className="org.apache.catalina.realm.JAASRealm"

                appName="Sample"

                userClassNames="jaas.SamplePrincipal"

                 roleClassNames="jaas.SampleRolePrincipal"/>

可以看到,上面的配置中指定了jaas.SamplePrincipal表示用戶,而jaas.SampleRolePrincipal表示角色
可通過confiFile屬性來配置jaas需要的認證配置文件,或使用java默認-Djava.security.auth.login.config=xx/jaas.config參數來指定領域屬性詳解:

className                             此領域實現的java類名,對於JAASRealm必須是org.apache.catalina.realm.JAASRealm

appName                                傳給JAAS LoginContext構造函數(並基於JAAS配置挑選適當的登錄方法)的應用程序名稱。
                                                默認是Tomcat,不過只要在JAAS .java.login.config文件中更改對應名,即可設定成任何所要的值

userClassNames                    代表個別用戶的javax.security.Principal類清單,以逗號分隔。對於UnixLoginModule設定值,應當包括UnixPrincipal類類

roleClassNames                     代表安全角色的javax.security.Principal類清單,以逗號分隔。對於UnixLoginModule,設定值應該包括UnixNumericGroupPrincipal類

userContextClassLoader      告知JAASRealm,或從前后類加載器中加載類,或從Tomcat自身的類加載器加載類,默認值為true

 

 

關於jaas的登錄模塊的實現,請看:

Java認證和授權服務 JAAS 之 認證http://blog.csdn.net/conquer0715/article/details/78204889
Java認證和授權服務JAAS之授權http://blog.csdn.net/conquer0715/article/details/78205755

注意:如果要使用Java認證和授權服務JAAS之認證中的例子,需要進行如下更改:
1. MyLoginModule 文件:

package jaas;

 

import javax.security.auth.Subject;

import javax.security.auth.callback.*;

import javax.security.auth.login.FailedLoginException;

import javax.security.auth.login.LoginException;

import javax.security.auth.spi.LoginModule;

import java.security.Principal;

import java.util.Map;

 

public class MyLoginModule implements LoginModule {

 

    // username and password

    private String username;

    private char[] password;

 

    // the authentication status

    private boolean userPwdSucceeded = false;

    private boolean commitSucceeded = false;

 

    // user's Principal

    private Principal userPrincipal;

 

 

    // initial state

    private Subject subject;

    private CallbackHandler callbackHandler;

 

 

    /**

     * Initialize this <code>LoginModule</code>.

     */

    public void initialize(Subject subject,

                           CallbackHandler callbackHandler,

                           Map<java.lang.String, ?> sharedState,

                           Map<java.lang.String, ?> options) {

 

        this.subject = subject;

        this.callbackHandler = callbackHandler;

    }

 

    /**

     * Authenticate the user by prompting for a user name and password.

     */

    public boolean login() throws LoginException {

        // prompt for a user name and password

        if (callbackHandler == null)

            throw new LoginException("Error: no CallbackHandler available " +

                    "to garner authentication information from the user");

 

        Callback[] callbacks = new Callback[2];

        callbacks[0] = new NameCallback("user name");

        callbacks[1] = new PasswordCallback("password", false);

//        callbacks[2] = new TextOutputCallback(TextOutputCallback.INFORMATION, "hello, just a msg!");

//        callbacks[3] = new TextOutputCallback(TextOutputCallback.WARNING, "just warn you!");

 

        try {

            callbackHandler.handle(callbacks);

            NameCallback nameCallback = (NameCallback) callbacks[0];

            PasswordCallback passwordCallback = (PasswordCallback) callbacks[1];

 

            username = nameCallback.getName();

 

            char[] tmpPassword = passwordCallback.getPassword();

            passwordCallback.clearPassword();// clean password in memory space

            if (tmpPassword == null) {

                tmpPassword = new char[0];// treat a NULL password as an empty password

            }

            password = new char[tmpPassword.length];

            System.arraycopy(tmpPassword, 0, password, 0, tmpPassword.length);

        } catch (Exception e) {

            e.printStackTrace();

        }

 

 

        // verify the username/password

//        boolean usernameCorrect = false;

//        if (username.equals("user")) usernameCorrect = true;

//

//        if (usernameCorrect &&

//                password.length == 3 &&

//                password[0] == 'p' &&

//                password[1] == 'w' &&

//                password[2] == 'd') {

//

//            userPwdSucceeded = true;

//        } else {

//            userPwdSucceeded = false;

//            cleanUserAndPwdData();

//            if (!usernameCorrect) {

//                throw new FailedLoginException("User Name Incorrect");

//            } else {

//                throw new FailedLoginException("Password Incorrect");

//            }

//        }

//        return userPwdSucceeded;

        userPwdSucceeded=true;

        return true;

    }

 

    public boolean commit() throws LoginException {

        if (!userPwdSucceeded) return false;

 

        // add a Principal (authenticated identity) to the Subject

        userPrincipal = new SamplePrincipal(username);

        subject.getPrincipals().add(userPrincipal);

        // for tomcat jaas realm

        if (username.equals("admin")) {

            subject.getPrincipals().add(new SampleRolePrincipal("admin"));

        } else if (username.equals("tomcat")) {

            subject.getPrincipals().add(new SampleRolePrincipal("tomcat"));

        }

 

        // in any case, clean out state

        cleanUserAndPwdData();

 

        return commitSucceeded = true;

    }

 

    public boolean abort() throws LoginException {

        if (!userPwdSucceeded) return false;

 

        if (commitSucceeded) {

            logout();

        } else {

            cleanState();

        }

 

        return true;

    }

 

    public boolean logout() throws LoginException {

        subject.getPrincipals().remove(userPrincipal);

        cleanState();

        userPwdSucceeded = commitSucceeded;

        return true;

    }

 

    private void cleanState() {

        userPwdSucceeded = false;

        cleanUserAndPwdData();

        userPrincipal = null;

    }

 

    private void cleanUserAndPwdData() {

        username = null;

        if (password != null) {

            for (int i = 0; i < password.length; i++)

                password[i] = ' ';

            password = null;

        }

    }

}

 

 SamplePrincipal 文件:

package jaas;

 

import  java.security.Principal;

 

public class SamplePrincipal implements Principal {

    private String name;

 

    public SamplePrincipal(String name) {

        this.name = name;

    }

 

    public String getName() {

        return name;

    }

 

}

 

 

SampleRolePrincipal文件:

package jaas;

 

public class SampleRolePrincipal extends SamplePrincipal {

    public SampleRolePrincipal(String name) {

        super(name);

    }

}

 

說明:
另外注意 userClassNames="jaas.SamplePrincipal" 和 roleClassNames="jaas.SampleRolePrincipal" 兩個實現類的 equals 和 hascode 方法,如果覆蓋不好最好不要覆蓋,否則容易 subject.getPrincipals().add 不進去。

 

5、DataSourceRealm

這個安全域和上面的JDBCRealm實現基本一致,只不過不是創建數據庫連接,而是從JNDI上下文獲取數據源,它所需要的數據庫腳本和JDBCRealm一致。
修改tomcatserver.xml 添加安全域配置:
1. 
GlobalNamingResources 節點下添加:


<Resource

  name="jdbc/h2"

  type="javax.sql.DataSource"

  username="sa"

  password=""

  driverClassName="org.h2.Driver"

  url="jdbc:h2:tcp://localhost//home/conquer/mine/work_space/h2-dbpath/tomcat"/>

 2. 繼續添加安全域配置(這里會使用jndi引用上面注冊的數據源資源):

<Realm className="org.apache.catalina.realm.DataSourceRealm"

   dataSourceName="jdbc/h2"

   userTable="users"   userNameCol="user_name"   userCredCol="user_pass"

   userRoleTable="user_roles"   roleNameCol="role_name"/>

 

</Realm>

 

6、MemoryRealm

 

這個是最簡單的配置,默認是讀取tomcat-users.xml可通過pathname屬性配置為其它文件)里面配置的用戶角色信息。
修改server.xml 添加配置:

<Realm  className="org.apache.catalina.realm.MemoryRealm"/>

 

7、CombinedRealm

這是一個特殊的Realm,顧名思義,它可以使用多個子的Realm(Realm可以嵌套)來對用戶進行授權。也許你有多個“數據源”,也許你希望當有一個Realm停止工作的時候系統仍然不會崩潰,不管是什么需求需要同時使用多個Realm,這個CombinedRealm就能滿足這個需求。授權將會按照子Realm的聲明順序依次進行,只要滿足任何一個子Realm,都可以通過校驗。


resourceName="UserDatabase"/> 
dataSourceName="jdbc/authority" 
userTable="users" 
userNameCol="user_name" 
userCredCol="user_pass" 
userRoleTable="user_roles" 
roleNameCol="role_name"/> 

 

8、LockOutRealm 

它繼承於CombinedRealm,和CombinedRealm一樣,與它一起工作的Realm需要嵌套在LockOutRealm中,而且也是只需要滿足任何一個Realm即可。如果在一定的時間內多次嘗試授權失敗,它將會鎖定這個用戶。使用它時,不需要修改它下面的Realm配置,因為它是通過記錄所有失敗的登錄(包括不存在的用戶)來實現的。

 

 

 二、web.xml的配置

 web.xml安全配置

Servlet規范支持安全地訪問web資源,只需要通過web.xml簡單配置即可,其功能由服務器提供商實現,

web.xml文件內容如下:

<!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>
 <--!配置 <security-constraint/> 元素,指定角色可訪問的資源集和可使用的 HTTP 方法-->

    <security-constraint>

        <web-resource-collection>        #定義資源集

            <web-resource-name>some name</web-resource-name>    #指定資源名稱

 
            <url-pattern>*.jsp</url-pattern>              #匹配資源

            <url-pattern>*.do</url-pattern>

 
            <http-method>GET</http-method>                #可使用的HTTP方法

            <http-method>PUT</http-method>

            <http-method>HEAD</http-method>

            <http-method>TRACE</http-method>

            <http-method>POST</http-method>

            <http-method>DELETE</http-method>

            <http-method>OPTIONS</http-method>

        </web-resource-collection>
 

        <auth-constraint>                      #定義認證用戶

            <role-name>tomcat</role-name>

            <role-name>admin</role-name>

        </auth-constraint> tomcat或admin兩個角色都可以使用GET|PUT|HEAD|TRACE|POST|DELETE|OPTIONS方法訪問*.jsp *.do資源 <user-data-constraint>

            <transport-guarantee>NONE</transport-guarantee>

            <!--

                這個可選的元素指出在訪問相關資源時使用哪種傳輸層保護。

                它必須包含一個transport-guarantee子元素(合法值為NONE | INTEGRAL | CONFIDENTIAL),

                transport-guarantee為NONE值將對所用的通訊協議不加限制。

                INTEGRAL值表示數據必須以一種防止截取它的人閱讀它的方式傳送。

                雖然原理上(並且在未來的HTTP版本中),在INTEGRAL和CONFIDENTIAL之間可能會有差別,但在當前實踐中,他們都只是簡單地要求用SSL。

            -->

        </user-data-constraint>


    </security-constraint>              #對一個完整資源的安全的定義結束

 

    <security-constraint>               #對另一個資源安全的定義開始

        <web-resource-collection>           #定義資源集

            <web-resource-name>admin page</web-resource-name>      #定義資源名稱
  
            <url-pattern>/admin.jsp</url-pattern>              #資源匹配

        </web-resource-collection>

        <auth-constraint>                            #定義認證用戶

            <role-name>admin</role-name>

        </auth-constraint>

    </security-constraint>                        #該資源集安全定義結束,admin.jsp資源只能由admin角色訪問
<security-constraint>                #第三個資源安全定義開始 <web-resource-collection>            #定義資源集 <web-resource-name>tomcat page</web-resource-name>    #定義資源名稱 <url-pattern>/tomcat.jsp</url-pattern> #匹配資源 </web-resource-collection> <auth-constraint>                      #定義認證用戶 <role-name>tomcat</role-name> </auth-constraint> </security-constraint> #該資源安全定義結束 ,tomcat.jsp資源只能由tomcat角色訪問
配置
<login-config/>元素,指定認證方式,並指定安全域 <login-config> <!--<auth-method>BASIC</auth-method>--> <auth-method>FORM</auth-method> 目前認證方式有4種:BASIC(基礎認證)|DIGEST(摘要認證)|FROM(表單認證)|CLIENT-CERT(證書認證)
1、BASIC(基礎認證):需要提供base64編碼文本的用戶口令,這種驗證方法,所有的密碼都會以base64編碼文本在網絡上傳遞
示例如下:

 


2、DIGEST(摘要認證):需要提供摘要編碼字符串的用戶口令,若使用摘要認證,除了在此web.xml文件中設置外,還需要在server.xml文件中修改Realm設定,將digest屬性添加到Realm元素中
並給與該屬性MD5值,digest屬性值可使用SHA/MD2/MD5,推薦僅使用MD5,在tomcat的密碼庫(codebase)中對該選項的支持更好
除了告訴tomcat存儲密碼的方式(MD5)外,還需要以指定格式手動加密每個用戶密碼,對於每個用戶均需執行如下兩個步驟:
            步驟1:
                $CATALINA_HOME/bin/digest.sh -a MD5 123456          #123456是明文密碼,執行后返回加密密碼

                      步驟2:將上述冒號后的加密后的密碼復制添加到tomcat-user.xml文件中作為某個用戶的密碼

示例如下:

 

3、FROM(表單認證):在網頁的表單上要求提供用戶密碼

當用戶請求web應用程序受保護的資源時,表單驗證會顯示登錄表單的網頁畫面,在web應用程序中,為實現表單驗證,需要登錄表單的網頁與驗證失敗的錯誤信息網頁

示例:

/login.html,form-login-page元素表示當tomcat發現未登錄的用戶企圖訪問受到security-constraint保護保護的資源時,需要顯示給用戶的網頁
/error.html,form-error-page元素表示當
用戶登錄失敗時,tomcat要顯示給用戶的網頁 

4、CLIENT-CERT(證書認證):以客戶端數字證書來確認用戶的身份

只有當在SSL(即HTTPS)上提供網頁內容時,才能使用CLIENT_CERT的驗證方(在web.xml文件的auth-method元素中的CLIENT_CERT),它允許客戶端認證不用口令,而是瀏覽器提供客戶端X.509數值認證證書作為登錄認證

    

<!-- 使用的Realm名字,注意這里不能有空格 --> <realm-name>MyConstraints</realm-name>
   <form-login-config>                            #只有表單驗證(FROM),才需要這里的登錄表單網頁和驗證失敗錯誤信息網頁 相對於Web應用程序的根目錄的2個文件 
<form-login-page>/login.html</form-login-page> #該元素表示當tomcat發現未登錄的用戶企圖訪問受到security-constraint保護保護的資源時,需要顯示給用戶的網頁
<form-error-page>/error.html</form-error-page> #用戶登錄失敗時,form-error-page元素展示了tomcat要顯示給用戶的網頁
</form-login-config>
</login-config> 配置<security-role/>元素來定義角色(角色是在tomcat-user.xml文件中事先定義好的)

<security-role>
<role-name>tomcat</role-name>
</security-role>
<security-role>
<role-name>admin</role-name>
</security-role> </web-app>

 

上述的web.xml文件內容表示:

1、安全規則
admin.jsp 只能由 admin 角色訪問,
tomcat.jsp
只能由 tomcat 角色訪問,
其它任意 *.jsp  *.do 可由 admin tomcat 角色訪問。

2、認證方式
BASIC
是基礎認證方式,由瀏覽器廠商實現的用戶名和密碼接收界面;
FORM
是應用定制的用戶名和密碼接收頁面;

3、角色聲明

必需明出所有用到的角色


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM