深入tomcat验证机制

来源:互联网 发布:mac中文官网 编辑:程序博客网 时间:2024/05/19 12:11

背景

<<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 thememory 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.

     */

UserDatabasedatabase;

 

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());

1 0
原创粉丝点击