12.2 身份验证方法

12.2 身份验证方法

现在你应该知道如何对资源集合实施安全约束,你也应该学会如何验证访问资源的用户信息。由于以声明的方式获得的资源,在部署描述符中使用的是安全约束元素,因此身份验证可以使用HTTP 1.1提供的解决方案:基本访问认证和摘要访问身份验证。此外,还可以使用基于表单的访问认证HTTP身份验证是在RFC2617中定义的。你可以在这里下载规范:
http://www.ietf.org/rfc/rfc2617.txt

基本访问身份验证

基本访问身份验证,或简称基本认证,是一个接受用户名和密码的HTTP身份验证。访问受保护的资源的用户将被服务器拒绝,服务器会返回一个401(未经授权)响应。该响应包含一个WWW-Authenticate头,包含至少一个适用于所请求资源的认证域。这里有一个响应内容的例子:

1
2
3
4
HTTP/1.1 401 Authorization Required
Server: Apache-Coyote/1.1
Date: Wed, 21 Dec 2011 11:32:09 GMT
WWW-Authenticate: Basic realm="Members Only"

浏览器会显示用户输入用户名和密码的登录对话框。当用户单击“登录”按钮时,用户名将被加上一个冒号并与密码连接起来形成一个字符串。该字符串在被发送到服务器之前将用Base64算法编码。成功登录后,服务器将发送所请求的资源。Base64是一个非常弱的算法,因此很容易解密Base64的信息。考虑使用摘要访问认证来替代。

实例

app12b应用程序展示了如何使用基本访问认证

项目结构

app12b应用程序的项目结构如下图所示
这里有一张图片

app12b的部署描述符web.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
<?xml version="1.0" encoding="utf-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
<!-- 限制资源访问配置 -->
<security-constraint>
<!-- 访问受限的资源集合 -->
<web-resource-collection>
<web-resource-name>JSP pages</web-resource-name>
<!-- 访问受限的资源集合的URL的正则表达式 -->
<url-pattern>*.jsp</url-pattern>
</web-resource-collection>
<!-- 运行访问该资源集合的角色列表 -->
<auth-constraint />
</security-constraint>
<security-constraint>
<web-resource-collection>
<web-resource-name>Servlet1</web-resource-name>
<!-- 受保护的资源集合的URL正则表达式 -->
<url-pattern>/servlet1</url-pattern>
</web-resource-collection>
<!-- 允许访问该资源集合的角色列表 -->
<auth-constraint>
<role-name>member</role-name>
<role-name>manager</role-name>
</auth-constraint>
</security-constraint>
<!-- 认证设置 -->
<login-config>
<!-- 认证方法为:基本访问身份验证 -->
<auth-method>BASIC</auth-method>
<!-- 提示信息,将会显示在浏览器上 -->
<realm-name>Members Only</realm-name>
</login-config>
</web-app>

部署描述符web.xml中最重要的元素是login-config元素。它有两个子元素:auth-methodrealm-name。要使用
基本访问身份验证 Basic access authentication,您必须将auth-method元素的值设为BASIC(所有字母大写)。在浏览器登录对话框中显示的realm-name元素必须赋值。

Servlet1.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
package servlet;
import java.io.IOException;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.HttpConstraint;
import javax.servlet.annotation.ServletSecurity;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet(
urlPatterns =
{"/servlet1"}
)
@ServletSecurity(
@HttpConstraint(
rolesAllowed = "manager"
)
)
public class Servlet1 extends HttpServlet
{
private static final long serialVersionUID = 119L;
public void doGet(HttpServletRequest request,
HttpServletResponse response)
throws ServletException,IOException
{
RequestDispatcher dispatcher = request
.getRequestDispatcher("/jsp/1.jsp");
dispatcher.forward(request, response);
}
}

1.jsp

1
2
3
4
5
6
7
8
9
<!DOCTYPE HTML>
<html>
<head>
<title>Welcome</title>
</head>
<body>
<h2>Hello World</h2>
</body>
</html>

运行效果

要测试app12b例子的基本访问身份验证,可使用以下URL来访问例子中的受限资源。
http://localhost:8080/app12b/servlet1
此时,浏览器中不会显示Servlet1的输出,而是要求输入用户名(tom)和密码(tom),如下图所示:
这里有一张图片
用户名和密码需要在Tomcat安装目录下的conf目录下的tomcat-users.xml中配置,详情请看:12.1 身份验证和授权小节中.
现在输入tomcat-user.xml中配置过的用户名tom,密码tom,就可以访问这个Servlet1了,显示效果如下图所示:
这里有一张图片
认证过后,再次点击上述链接则可以直接访问Servlet1,不再需要重复认证.

摘要访问接入认证

摘要访问接入认证,或简称摘要认证,也是一个HTTP认证,类似基本认证。但不使用弱加密的base64算法,而使用MD5算法创建一个组合用户名、域名和密码的哈希值,并发送到服务器。摘要访问身份验证是为了取代基本的访问认证,因为它提供了更安全的环境。
servletJSP容器没有义务支持摘要访问认证但大多数都有支持。

配置应用程序使用摘要访问认证的方式类似于使用基本访问认证。唯一的区别是login-config元素内的auth-method元素的值。**对于摘要访问认证,login-config元素内的auth-method元素值必须是DIGEST**(大写)。

实例

作为一个例子,该app12c演示应用的摘要访问认证Digest accessauthentication的使用。

项目结构

项目结构如下图所示:

web.xml

此应用程序的部署描述符如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
<!-- 设置受保护的资源 -->
<security-constraint>
<!-- 设置受保护的资源集合 -->
<web-resource-collection>
<web-resource-name>JSP pages</web-resource-name>
<!-- URL满足以下正则表达式的资源将被保护 -->
<url-pattern>*.jsp</url-pattern>
</web-resource-collection>
<!-- 设置允许访问该资源集合的角色列表 -->
<!-- 角色列表为空表示拒绝任何角色直接访问 -->
<auth-constraint />
</security-constraint>
<security-constraint>
<web-resource-collection>
<web-resource-name>Servlet1</web-resource-name>
<url-pattern>/servlet1</url-pattern>
</web-resource-collection>
<auth-constraint>
<!-- 允许以下角色访问该资源集合 -->
<role-name>member</role-name>
<role-name>manager</role-name>
</auth-constraint>
</security-constraint>
<!-- 认证配置 -->
<login-config>
<!-- 使用摘要接入认证方法 -->
<auth-method>DIGEST</auth-method>
<!-- 提示信息 -->
<realm-name>Digest authentication</realm-name>
</login-config>
</web-app>

Servlet1.java

与上述代码一样,这里不再列举。

1.jsp

与上面的1.jsp代码一样,这里不再列举.

运行效果

我们在浏览器里输入这个地址来测试一下:
http://localhost:8080/app12c/servlet1
输入正确的用户名tom,密码tom:
这里有一张图片
然后才可以访问Servlet1,浏览器显示效果如下:
这里有一张图片