深入tomcat驗證機制

背景

<<Head First Servlets & JSP>>安全一章介紹了tomcat內建的驗證機制.

 

首先介紹術語realm.

As far as theservlet

spec is concerned, arealm is a place where authentication information is stored. When you’retesting your application in Tomcat, you can use a file called“tomcat-users.xml” (located in

tomcat’sconf/directory, NOT within webapps). That one “tomcat-users.xml” file appliesto ALL

applicationsdeployed under web-apps. It’s commonly known as the memory realm because Tomcat reads this file into memory at startuptime. While it’s great for testing, it’s not recommended for production. Forone thing you can’t modify its contents without restarting Tomcat.

 

The tomcat-users.xml file

用戶名,密碼以及角色存儲於/conf/tomcat-users.xml文件.這裏不詳細介紹.

<rolerolename="Admin"/>

<rolerolename="Member"/>

<rolerolename="Guest"/>

<userusername="Annie" password="admin"roles="Admin,Member,Guest" />

<userusername="Diane" password="coder"roles="Member,Guest" />

<userusername="Ted" password="newbie" roles="Guest"/>

 

Tomcat廠商指定角色映射

<security-role><role-name>Admin</role-name></security-role>

<security-role><role-name>Member</role-name></security-role>

<security-role><role-name>Guest</role-name></security-role>

 

Enabling authentication

web.xml文件

<login-config>

<auth-method>BASIC</auth-method>

</login-config>

注意:驗證方法包括BASIC,DIGEST,CLIENT-CERT以及FORM.表單驗證時,action填寫j_security_check,用戶名name填寫j_username,密碼name填寫j_password,即能自動使用tomcat-users文件中的數據驗證.

 

Defining resource/method constraints

<security-constraint>element in the DD.

 

<security-constraint>

<web-resource-collection>

<web-resource-name>newconference</web-resource-name>

<url-pattern>/createConference</url-pattern>

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

<http-method>GET</http-method>

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

</web-resource-collection>

<web-resource-collection>

<web-resource-name>newschedule</web-resource-name>

<url-pattern>/newSchedule</url-pattern>                        

<http-method>GET</http-method>

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

</web-resource-collection>

<web-resource-collection>

<web-resource-name>accountmanagement</web-resource-name>

<url-pattern>/editPassword</url-pattern>

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

<http-method>GET</http-method>

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

</web-resource-collection>

<auth-constraint>

<role-name>Admin</role-name>                        

</auth-constraint>

<!-- 

<user-data-constraint>

<transport-guarantee>CONFIDENTIAL</transport-guarantee>

</user-data-constraint>

-->

</security-constraint>

當你訪問安全約束中指定的頁面時,就會彈出或跳轉至登錄頁面,用戶登錄之後並滿足指定角色才能訪問頁面.使用很簡單,那麼tomcat驗證機制是如何實現的呢?tomcat驗證機制能滿足我們實際所需嗎?參考Apache Tomcat文檔以及Apache Tomcat源代碼.

 

tomcat驗證機制如何實現

 

Configuration a Realm

參考Apache Tomcat 官方文檔Realm Configuration HOW-TO.

In general, you willbe adding an XML element to your conf/server.xml configuration file, that lookssomething like this:

     

      <!-- ThisRealm uses the UserDatabase configured in the global JNDI

           resources under the key"UserDatabase".  Any edits

           that are performed against thisUserDatabase are immediately

           available for use by the Realm.  -->

      <RealmclassName="org.apache.catalina.realm.UserDatabaseRealm"

            resourceName="UserDatabase"/>

這兒配置UserDatabaseRealm.接下來看看UserDatabase資源配置

 

  <!-- Global JNDI resources

       Documentation at/docs/jndi-resources-howto.html

  -->

  <GlobalNamingResources>

    <!-- Editable user database that canalso be used by

         UserDatabaseRealm to authenticateusers

    -->

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

             type="org.apache.catalina.UserDatabase"

              description="User databasethat can be updated and saved"

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

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

  </GlobalNamingResources>

 

配置中涉及到org.apache.catalina.realm.UserDatabaseRealm,org.apache.catalina.UserDatabase,org.apache.catalina.users.MemoryUserDatabaseFactory這三個類,應該是用於實現tomcat驗證機制.

 

查閱JavaDoc相關類.

UserDatabaseRealm有個成員

     /**

     * The<code>UserDatabase</code> we will use to authenticate users

     * and identify associated roles.

     */

UserDatabase database;

 

MemoryUserDatabaseFactory

Createand return a new MemoryUserDatabase instancethat has been configured according to the properties of the specified Reference. If you instance can be created, return nullinstead.

 

MemoryUserDatabase

Concreteimplementation of UserDatabase that loads all defined users, groups, and rolesinto an in-memory data structure, and uses a specified XML file for itspersistent storage. 

 

至於相關的各種驗證方法見包org.apache.catalina.authenticator,比如表單驗證方法即FormAuthenticator.

 

public booleanauthenticate(Request request,

                                Responseresponse,

                                LoginConfigconfig)

 

代碼塊

      Realm realm =context.getRealm();

        if (characterEncoding != null) {

           request.setCharacterEncoding(characterEncoding);

        }

        String username =request.getParameter(Constants.FORM_USERNAME);

        String password =request.getParameter(Constants.FORM_PASSWORD);

        if (log.isDebugEnabled())

            log.debug("Authenticatingusername '" + username + "'");

        principal =realm.authenticate(username, password);

        if (principal == null) {

//用戶名或密碼錯誤

            forwardToErrorPage(request,response, config);

            return (false);

        }

 

 

RealmBase

 

    /**

     * Return the Principal associated with thespecified username and

     * credentials, if there is one; otherwisereturn <code>null</code>.

     *

     * @param username Username of thePrincipal to look up

     * @param credentials Password or othercredentials to use in

     * authenticating this username

     */

    public Principal authenticate(Stringusername, String credentials) {

 

        String serverCredentials =getPassword(username);

 

        boolean validated ;

        if ( serverCredentials == null ) {

            validated = false;

        } else if(hasMessageDigest()) {

            validated =serverCredentials.equalsIgnoreCase(digest(credentials));

        } else {

            validated =serverCredentials.equals(credentials);

        }

        if(! validated ) {

            if (containerLog.isTraceEnabled()){

               containerLog.trace(sm.getString("realmBase.authenticateFailure",

                                               username));

            }

            return null;

        }

        if (containerLog.isTraceEnabled()) {

           containerLog.trace(sm.getString("realmBase.authenticateSuccess",

                                           username));

        }

 

        return getPrincipal(username);

    }

 

tomcat驗證機制能滿足實際所需嗎

 

使用數據庫

mysql爲例.

 

To set up Tomcat touse JDBCRealm, you will need to follow these steps:

 

  1. If you have not yet done so, create tables and columns in your database that conform to the requirements described above.
  1. Configure a database username and password for use by Tomcat, that has at least read only access to the tables described above. (Tomcat will never attempt to write to these tables.)
  1. Place a copy of the JDBC driver you will be using inside the $CATALINA_HOME/lib directory. Note that only JAR files are recognized!
  1. Set up a <Realm> element, as described below, in your $CATALINA_BASE/conf/server.xml file.
  2. Restart Tomcat if it is already running.

 

realm配置使用JDBCRealm.

<Resourcename="jdbc/conference" auth="Container"

type="javax.sql.DataSource" username="root"password="root"

driverClassName="com.mysql.jdbc.Driver"url="jdbc:mysql://127.0.0.1:3306/conference?useUnicode=true&amp;characterEncoding=utf8"

maxTotal="8"maxIdle="4" />

<RealmclassName="org.apache.catalina.realm.JDBCRealm"

driverName="org.gjt.mm.mysql.Driver"

connectionURL="jdbc:mysql://127.0.0.1:3306/conference?user=root&amp;password=root"

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

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

 

mysql數據庫中建表

create table users (

  user_name         varchar(15) not null primary key,

  user_pass         varchar(15) not null

);

 

create tableuser_roles (

  user_name         varchar(15) not null,

  role_name         varchar(15) not null,

  primary key (user_name, role_name)

);

 

jdbc driver for mysql放入tomcatlib目錄下

比如當前最新的文件mysql-connector-java-5.1.34-bin.jar.

 

 

A typical use of this resource reference might looklike this:

參考Apache tomcat文檔JNDI Resources HOW-TO: JDBC DataSources.

Context initCtx =new InitialContext();

Context envCtx =(Context) initCtx.lookup("java:comp/env");

DataSource ds =(DataSource)

  envCtx.lookup("jdbc/conference");

 

Connection conn =ds.getConnection();

... use thisconnection to access the database ...

conn.close();

 

獲取驗證用戶角色以及用戶名

HttpServletRequest

  • getUserPrincipal
  • getRemoteUser
  • isUserInRole

 

以獲取用戶名爲例

Principal principal= request.getUserPrincipal();

System.out.println(principal.getName());

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章