DIGEST 消息摘要验证也是 Tomcat 的自带验证方式,与 BASIC 认证的设置基本一致。先在 conf/server.xml 中添加Realm 领域数据源,然后在 web.xml 中添加 <security-constraint> 和 <login-config> 元素。
两者的唯一区别是 web.xml 配置时,<auth-method> 元素指定的认证方法,基本认证设置 <auth-method> 为 BASIC,而摘要认证设置 <auth-method> 为 DIGEST。
可以使用 IDEA、Eclipse 等工具创建一个 Web 项目(当然也可以手动创建),项目的的结构如下图:
其中,index.jsp 页面为 Web 应用的主页面,需要用户登录授权后才能访问。而 web.xml 是 Web 应用的配置文件。
index.jsp 页面内容如下:
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <meta charset="UTF-8"> <title>DEMO</title> </head> <body> <h1>DIGEST 摘要验证</h1> </body> </html>
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> <display-name>Archetype Created Web Application</display-name> <security-constraint> <display-name>default</display-name> <!-- 需要限制访问的资源子集 --> <web-resource-collection> <web-resource-name>all files</web-resource-name> <url-pattern>/*</url-pattern> </web-resource-collection> <!-- 指定可以访问该资源集合的用户角色,这里指定为 JAAS 中的角色 --> <auth-constraint> <role-name>manager-gui</role-name> </auth-constraint> <!-- 用来显示怎样保护在客户端和Web容器之间传递的数据 --> <!-- NONE 不需要传输保证 --> <!-- INTEGRAL 服务器和客户端之间的数据必须以某种方式发送,而且在传送中不能改变 --> <!-- CONFIDENTIAL 传输的数据必须是加密的数据 --> <user-data-constraint> <transport-guarantee>NONE</transport-guarantee> </user-data-constraint> </security-constraint> <!-- 配置登录方式为 digest 摘要验证方式 --> <login-config> <!-- 指定验证方式 --> <auth-method>DIGEST</auth-method> <!-- 指定领域名称,必须和生成摘要密码中的领域名称一致 --> <realm-name>myRealm</realm-name> </login-config> <security-role> <role-name>manager-gui</role-name> </security-role> </web-app>
接下来,需要生成 Tomcat 可识别的 MD5 摘要密码。生成密码有两种方式,正如官网描述:
To calculate the digested value of a cleartext password, two convenience techniques are supported:
为了计算明文密码的摘要值,支持两种便捷技术:
(1)If you are writing an application that needs to calculate digested passwords dynamically, call the static Digest() method of the org.apache.catalina.realm.RealmBase class, passing the cleartext password and the digest algorithm name as arguments. This method will return the digested password.
如果您正在编写一个需要动态计算摘要密码的应用程序,请调用 org.apache.catalina.realm.RealmBase 类的静态 Digest() 方法,将明文密码和摘要算法名称作为参数传递,此方法将返回摘要密码。例如:
import org.apache.catalina.realm.RealmBase; /** * Tomcat MD5 摘要密码生成器 * @author hxstrive.com 2022/6/16 */ public class DigestPwdGenerator { public static void main(String[] args) { String digest = RealmBase.Digest( "tomcat:myRealm:aaaaaa", "MD5", "UTF-8"); System.out.println(digest); } }
注意,上面 DEMO 需要添加 %CATALINA_HOME%/lib/*.jar 和 %CATALINA_HOME%/bin/tomcat-juli.jar 依赖。运行 DEMO 输出加密后的摘要如下:
000edf117940faf92f394f14c15752b6
(2)If you want to execute a command line utility to calculate the digested password, simply execute
如果要执行命令行实用程序来计算摘要密码,只需执行
CATALINA_HOME/bin/digest.[bat|sh] -a {algorithm} {cleartext-password}
and the digested version of this cleartext password will be returned to standard output.
并且此明文密码的摘要版本将返回到标准输出。在 Windows 下,示例如下:
D:apache-tomcat-7.0.64-2in> digest.bat -a MD5 tomcat:myRealm:aaaaaa
tomcat:myRealm:aaaaaa:000edf117940faf92f394f14c15752b6
cleartext-password 的格式?
官方是这样描述的:
If using digested passwords with DIGEST authentication, the cleartext used to generate the digest is different and the digest must use the MD5 algorithm. In the examples above {cleartext-password}must be replaced with {username}:{realm}:{cleartext-password} . For example, in a development environment this might take the form testUser:Authentication required:testPassword . The value for {realm} is taken from the <realm-name> element of the web application’s <login-config> . If not specified in web.xml, the default value of Authentication required is used.
如果将摘要密码与摘要身份验证一起使用,则用于生成摘要的明文不同,摘要必须使用 MD5 算法。在上面的示例中,必须用 {用户名}:{领域}:{清除文本-密码} 替换 {clartext-password}。例如,在开发环境中,这可能采用以下形式:tomcat:myRealm:aaaaaa
从 Web 应用程序的 <LOGIN-CONFIG> 的 <Realm-Name> 元素中获取 {领域} 的值。如果未在 web.xml 中指定,则使用缺省值所需的身份验证。
打开 tomcat 的 tomcat-users.xml 配置文件,将用户的明文密码替换成上面生成的摘要密码。如下:
<?xml version='1.0' encoding='utf-8'?> <tomcat-users> <role rolename="manager-gui"/> <role rolename="manager-script"/> <role rolename="manager-jmx"/> <role rolename="manager-status"/> <role rolename="admin-gui"/> <user username="tomcat" password="000edf117940faf92f394f14c15752b6" roles="manager-gui,manager-script,manager-jmx,manager-status,admin-gui"/> </tomcat-users>
将该 Web 应用打包成 war 包的方式去部署运行 Web 应用,或者直接通过 IDEA 内置 Tomcat 功能运行该 Web 应用。
运行成功后,使用浏览器访问项目 index.jsp 页面。如下图:
输入用户名和密码点击“登录”按钮进行登录,如果密码验证通过,则跳转到主页。如下图:
通过浏览器调试工具,可以看到 Authorization 请求头字段信息如下:
Authorization: Digest username="tomcat", realm="myRealm", nonce="1655442073849:9d39b54c1ecf010670262e92aeed1705", uri="/tomcat_auth_digest/", response="0128f8cedaabe9c1ec85fed4efb45b5d", opaque="D4766067E4D56D43888D83EDAB07A0BE", qop=auth, nc=00000002, cnonce="753daa8372c48293"