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-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>BASIC</auth-method> <realm-name>Members Only</realm-name> </login-config> </web-app>
|
部署描述符web.xml中最重要的元素是login-config
元素。它有两个子元素:auth-method
和realm-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
算法创建一个组合用户名、域名和密码的哈希值,并发送到服务器。摘要访问身份验证是为了取代基本的访问认证,因为它提供了更安全的环境。
servlet
和JSP
容器没有义务支持摘要访问认证但大多数都有支持。
配置应用程序使用摘要访问认证的方式类似于使用基本访问认证。唯一的区别是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-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
,浏览器显示效果如下: