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

srverlet Container或web應用程序自己均可以提供控制web應用程序資源的安全防禦html

前者稱爲容器管理的安全防禦,或者稱爲應用程序管理安全防禦java

經過內嵌機制,tomcat提供一些安全防禦方法,這是一種「容器管理」的安全防禦。另外一方面若是有一系列具備本身的登陸機制的servlet和JSP,則視爲應用程序管理的安全防禦。web

無論是哪一種安全防禦類型,都是用稱之爲領域(realm)的組來管理用戶和密碼。算法

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

1、領域的配置數據庫

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

  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"/>tomcat

後面的realm配置能夠覆蓋前面安全

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

一、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/>元素中,則只有對應的應用程序能被訪問

 

 二、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/>元素中,則只有對應的應用程序能被訪問

 

 三、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表達式,則會忽略此屬性

 

 四、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 不進去。

 

五、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>

 

六、MemoryRealm

 

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

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

 

七、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"/> 

 

八、LockOutRealm 

它繼承於CombinedRealm,和CombinedRealm同樣,與它一塊兒工做的Realm須要嵌套在LockOutRealm中,並且也是隻須要知足任何一個Realm便可。若是在必定的時間內屢次嘗試受權失敗,它將會鎖定這個用戶。使用它時,不須要修改它下面的Realm配置,由於它是經過記錄全部失敗的登陸(包括不存在的用戶)來實現的。

 

 

 2、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(證書認證)
一、BASIC(基礎認證):須要提供base64編碼文本的用戶口令,這種驗證方法,全部的密碼都會以base64編碼文本在網絡上傳遞
示例以下:

 


二、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文件中做爲某個用戶的密碼

示例以下:

 

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

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

示例:

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

四、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、角色聲明

必需明出全部用到的角色

相關文章
相關標籤/搜索