本章要点

1. 理解 验证、授权、数据完整性 和 机密性的概念

2. 理解 角色的概念

3. 了解Servlet 规范中定义的4 种验证机制

4. 掌握声明式安全的配置方式

5. 掌握基本验证和表单验证的实现

6. 掌握程序式安全的实现方式

7. 学会如何避免SQL 注入攻击

随着Internet 的日益普及,越来越多的企业以Internet 为媒介,发布产品信息,进行在线交易;越来越多的人通过Internet 购买商品、在线汇款。在Internet上,每天都有大量的交易发生,无数的敏感信息在网上传输,而所有的这一切,都需要有一个强健的安全机制来保障。
本章主要介绍如何让我们开发的Web应用程序更加安全。

18.1 概述

大多数网络资源都是免费的,可以被所有的用户所访问。然而,有些资源是需要特定的用户才能访问。例如,我们开发了一个论坛系统,所有的访客都可以浏览帖子,但不可以发表帖子,注册用户可以发表帖子,只有管理员可以访问论坛的后台管理系统。要让不同身份的用户访问不同的资源,就需要我们采用某些安全的机制来保护Web应用程序中的资源,避免关键信息被未授权的用户所访问。
Servlet 规范定义了一些在Web应用程序中实现安全性的方法,Servlet容器在其底层架构中对安全的安全的实现提供了支持。Web应用程序的安全涉及多个方面,在介绍Servlet规范提供的安全特性的实现细节之前,我们先来了解一些概念。

1、验证 (Authentication)

验证是确定一个用户是谁的过程。例如,身份证是我们每个人的表示,你说你是张三,那好看看你的身份证就知道了。生活中,验证随时在发生,当驾驶员在路上违反交规的时候,交警总是说,“请拿出你的驾照”,对其身份进行验证。在互联网上,验证一个用户通常是使用用户名和密码。

2、 授权(Authorization)

一旦 用户被验证,他必须被授权。授权是决定一个用户是否允许访问他所请求的特定资源的过程。例如,虽然大家都是银行的储户,但是你没有被授权访问其他储户的账户。虽然驾驶员都有驾照,但有些驾驶员被授权可以开卡车,而有些驾驶员只能开小轿车。
授权通常是通过访问控制列表(Access Control List ,ACL)来实现的,这个列表指定了用户和他们所能访问的资源类型。需要注意的是,授权和验证往往是结合在一起应用的,例如,现在很多公司都有门禁系统,你去公司上班,进入办公室之前,要在门口刷一下你的胸卡,这个过程就包含了验证和授权。核对胸卡上面的信息以确定你是否是本公司的职员,这是验证。判断你是否被允许进入这个办公室(例如,财务室只能让公司的财务人员进入),这是授权。

3、数据完整性(Data Integrity)

数据完整性是 确保数据在传输过程中没有被篡改。例如,你通过网络支付购买商品的费用200元,那么接收方得到的数据应该也是200元,而不能是其他的数字。通常,我们要对传输的数据进行单向散列算法,得到一个散列值(哈希值),或者对传输的数据进行数字签名,然后将这个散列值或者数字签名和数据一起传输,接收方通过校验数据和散列值来确保数据是完整的。

4、机密性 或者 数据保密(Confidentiality or Data Privacy )

机密性是确保只有指定的用户可以访问敏感信息的过程。例如,你登录某个网站的时候,输入了用户名和密码,而这些信息是以明文的方式在网上传输的,某个黑客就可以通过监测HTTP 数据包的手段而得到这些信息。在这种情况下,数据就不是机密的。要实现数据的保密,可以对数据进行加密,只要指定的用户才可以解密,这样,即使黑客得到了数据,无法解密数据,也就无法使用它了。目前,大多数网站都是使用Https协议来传输加密的信息。授权和机密性的区别是对信息保护的方式不同,授权是防止信息不能到达非授权的用户,而机密性是确保信息即使被窃取也无法使用。

5、角色(Role)

在安全系统设计中,权限被分配给某个角色,而不是实际的用户,用户所获得的权限是通过他所扮演的角色来获取的。例如,公司的财务人员可以访问员工的工资信息,而财务人员是谁并没有关系,财务人员可以随着时间而改变,张三 今天分配到财务部(扮演财务人员的角色),那么他就可以访问员工的工资信息,明天他调离财务部,也就不能访问工资信息了。角色的使用,对于权限的设置提供了更多的灵活性。一个用户可以扮演多个角色, 例如, 李四既是财务部主管,又负责销售部,那么他就扮演了两个角色,可以同时访问工资信息和销售数据。在实际的安全系统设计中,往往还有用户组,用户属于用户组,角色可以分配给用户组,也可以分配给单独的用户,作为一个用户组的成员,自然就具有这个用户组的角色。通过 用户、用户组、角色的多重关系,可以设计出强大而又非常灵活的权限系统。
了解了以上这些关于安全的基本概念,下面看啊可能如何在Web应用程序中实现验证。

18.2 理解验证 机制

在 Servlet规范中, 定义了四种 验证用户的机制 。

18.2.1 HTTP Basic Authentication

HTTP 基本验证是在HTTP1.0 规范中定义的、基于用户名和密码的验证机制。 当Web 客户端(浏览器)请求受保护的资源时,Web服务器会请求客户端验证用户,此时,客户端会弹出一个对话框,让用户输入用户名和密码。Web客户端从用户处得到用户名和密码,传输给Web服务器。如果用户名和密码正确,服务器将发送用户所请求的资源。图18-1 是采用HTTP基本验证时,浏览器弹出对话框让用户输入用户名和密码。
image.png
当 Web应用程序采用基本验证时,浏览器和服务器端交互的详细过程如下。
(1)浏览器请求受保护的资源。此时,浏览器并不知道请求的资源是受保护的,它按照通常的方式发送HTTP 请求,例如:

  1. GET /ch18/ HTTP/1.1
  1. (2) 服务器发现客户端请求的资源是受保护的,于是向客户端发送401(未授权的)响应消息。在响应消息中,包含了WWW-Authenticate 响应报头,用于告诉浏览器访问的这个资源需要基本验证。服务器发送的响应消息形式如下:
  1. HTTP/1.1 401 Unauthorized
  2. ...
  3. www-Authenticate: Basic realm="Basic Auth Test"
  4. Content-Type:text/html;charset=utf-8
  5. Content-Length:952
  6. ...
  1. WWW-Authenticate 响应报头中,包含了一个Realm(领域)字符串,Realm值定义了保护区域。通过使用Realm,可以将服务器上的受保护资源分隔为不同的保护区域,这些区域有各自的验证方案或授权数据库。Realm值是一个字符串,由服务器来分配。请读者注意图18-1 中圆角矩形框的部分。当浏览器向服务器传输用户名和密码后,服务器在指定的Realm(领域)内验证用户。<br />(3)当接收到服务器发送的401 响应后,浏览器弹出一个对话框,让用户输入用户名和密码,如图18-1所示。<br />(4)用户输入了用户名和密码后,浏览器发送Authorization请求报头,将用户名和密码一起发送出去。用户名和密码的发送形式为“用户名:密码”,将这个字符串以Base64编码作为Authorization报头的值。
  1. GET /ch18/ HTTP/1.1
  2. ...
  3. Authorization:Basic YWRTAW46TIzNDU2NZG=
  1. 5 当服务器接收到包含了Authorization报头的请求,于是就验证用户名和密码。如果用户名和密码正确,就发送用户请求的资源。否则,发送403(被禁止的)响应消息。服务器通常会给出不提供服务的原因,例如,“对请求资源的访问被拒绝”。<br /> (6) 浏览器显示请求的资源(验证通过),或者显示服务器发送的错误页面(验证失败)。

要注意的是,基本验证虽然配置的简单,但它不是一个安全的验证协议。因为在传输过程中,用户密码并没有被加密(Base64 编码不是一种加密的方式)。如果确定客户端与服务器的连接本身是安全的,可以使用基本验证。

18.2.2 HTTP Digest Authentication

与HTTP 基本验证类似,HTTP 摘要验证也是基于用户名和密码来验证用户的,不同的是,使用摘要验证,用户密码是以加密的形式(对密码采用MD5摘要算法)传输的,这个比采用Base 64 编码要安全得多。虽然摘要验证比基本验证更加安全,但目前并没有得到广泛得使用,Servlet规范也没有要求所有的Servlet容器必须实现摘要验证(Tomcat 服务器支持摘要验证)。

18.2.3 HTTPS Client Authentication

HTTPS(Secure HTTP) 是在 SSL(secure Socket Layer, 安全套接字)之上得HTTP 协议。SSL 是 1995年由Netscape 公司提出得一种安全协议,用于在两个套接字(Web浏览器和Web服务器通过套接字建立连接)之间建立一个安全的连接。SSL 由两个子协议组成,一个用于建立安全的连接,另一个使用安全的连接。当建立了安全连接后,通信双方使用同一个“会话密钥”对传输的信息进行加密和解密。
使用HTTPS 的客户端验证是强壮的验证机制。这种机制需要客户端拥有一个公钥证书(Public Key Certificate ,PKC)。 HTTPS 客户端验证主要在电子商务应用程序中使用。 几乎所有的浏览器和主流的Servlet容器都支持HTTPS 协议,HTTPS 客户端验证是四种验证机制中最安全的,不过实现的代价也是最高的。

18.2.4 Form Based Authentication

基于表单的验证类似与基本验证。不同之处是,基于表单的验证使用定制的HTML表单让用户输入用户名和密码,而不是使用浏览器的弹出对话框。
使用基于表单的验证,开发者可以定制表单的显示外观,不过就

元素的action 属性必须指定为j_security_check, 输入用户名的文本域的名字必须是 j_username, 输入密码的口令域的名字必须是 j_password ,如下所示:

  1. <form method="POST" action="j_security_check">
  2. <input type="text" name="j_username">
  3. <input type="password" name="j_password">
  4. </form>

当浏览器请求一个资源的时候,服务器将保存原始的请求参数,然后发送验证表单给浏览器。用户在表单中输入用户名和密码,然后提交给服务器,服务器验证通过后,重定向客户端到请求的资源。
基于表单的验证实现简单,同时可以定制用户登陆页面的外观,不过,与基本验证一样,基于表单的验证同样是不安全的,用户名和密码是以明文(没有任何的加密或编码)的方式传输的。另外,基于表单的验证只能在使用Cookie 或者 SSL 会话跟踪Session的情况下使用,如果是采用URL 重写的机制跟踪Session,则不能使用基于表单的验证。

18.3 声明式安全

声明式安全是在web.xml 文件中指定Web应用程序的安全处理机制,这使得一个Web应用程序无须修改任何代码就可以获得安全性。默认请情况下web应用程序的所有资源对每个都是可以访问的,通过在web.xml 文件中配置 元素来限制对资源的访问。

18.3.1 元素

image.png

image.png

image.png

image.png

image.png

image.png

image.png

image.png
image.png

image.png
image.png