了解了如何对一个资源集合强加安全约束后(上一个博客),还应该知道如何对访问的用户进行验证。对于声明式保护的资源,可以在部署描述符中使用security-constraint元素,通过HTTP1.1提供的解决方案实现验证:基本访问验证和摘要访问验证。另外,也可以使用基于表单的访问验证。
基本访问验证
基本验证是一种接受用户名和密码的HTTP验证。在基本访问验证中,如果访问收到保护的资源,将会被服务器拒绝,并返回一个401(未授权)响应。该响应包含一个HTTP-Authenticate标头,其中至少包含一个适用于被请求资源的角色,然后,浏览器屏幕上会显示一个登陆对话框,用于输入用户名和密码。这里使用Base64算法(弱算法,很容易被破解)编码,将用户名和密码结合起来的字符串发送到服务器。登陆成功后,服务器就会发出请求的资源。
<servlet>
<servlet-name>Servlet1</servlet-name>
<servlet-class>security.Servlet1</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Servlet1</servlet-name>
<url-pattern>/Servlet1</url-pattern>
</servlet-mapping>
<security-constraint>
<web-resource-collection>
<web-resource-name>JSP page</web-resource-name>
<url-pattern>*.jsp</url-pattern>
</web-resource-collection>
<!-- 必须有auth-constraint元素,否则这个资源将得不到保护 -->
<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>
该部署描述符中最重要的额就是login-config元素。它的两个子元素:auth-method ,使用基本访问验证时,它的值必须是BASIC并全部大写;realm-name,只要一个名称,用于显示在浏览器的登陆对话中。
Servlet1类:
public class Servlet1 extends HttpServlet{
private static final long serialVersionUID = 123456L;
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
RequestDispatcher dispatcher = request.getRequestDispatcher("jsp/image.jsp");
dispatcher.forward(request, response);
}
}
现在访问Servlet1来访问它里面的受限制资源
由于映射到Servlet1的auth-contraint元素指定了manager和member两个角色(conf/tomcat-users.xml里声明)。所以现在通过在conf/tomcat-users.xml里定义的用户都能登陆。
摘要访问验证
摘要验证也是一种HTTP验证。它使用MD5算法创建一个散列(hash),其中结合了用户名,realm,密码,将这个散列发生到服务器。该验证方式旨在取代基本验证,因为它提供了更安全的环境。
部署:
<login-config>
<auth-method>DIGEST</auth-method>
<realm-name>Digest authentication</realm-name>
</login-config>
访问验证:
基于表单的验证
前两个验证都不允许使用定制的登陆表单。我们可以使用基于表单的验证方法使用定制的表单。由于它传输的值没有进行加密,因此这个应该和SSL结合起来使用。
使用这个验证方法时,我们创建一个login页面也一个error界面。部署描述符中的auth-method元素值必须设为FORM,另外login-config元素还应该有一个form-login-config元素,带有两个子元素:form-login-page;form-error-page。
部署描述符:
显示界面必须以’/’开头
<login-config>
<auth-method>FORM</auth-method>
<form-login-config>
<form-login-page>/login.html</form-login-page>
<form-error-page>/error.html</form-error-page>
</form-login-config>
</login-config>
login.html和error.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Login</title>
</head>
<body>
<h1>Login Form</h1>
<form action="j_security_check" method="post">
<div>
User Name:<input name="j_username"/>
</div>
<div>
Password:<input type="password" name="j_password">
</div>
<div>
<input type="submit" value="Login">
</div>
</form>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Login Error</title>
</head>
<body>
Login failed
</body>
</html>
客户端证书验证
客户端证书验证是在HTTPS(用SSL加密过的HTTP)上进行的。它要求每一个客户端都要有一个客户端证书 ,这是一个非诚健壮的验证机制,但是不适用于在互联网上部署的应用程序,因为不可能要求每一个互联网都拥有一个数字验证,然而,这种验证方式可以用来访问公司内部网的应用程序。