`
ihuashao
  • 浏览: 4552078 次
  • 性别: Icon_minigender_1
  • 来自: 济南
社区版块
存档分类
最新评论

如何保护Web应用程序

阅读更多
虽然安全性是所有应用程序都需关心的方面,但是它对于Web应用程序组件尤为重要。不安全的Web应用程序使Web站点易受多种攻击,而且有些攻击仅仅需要一个Internet浏览器和少量相关知识即可。

  Java 2 Enterprise Edition(J2EE)提供许多安全功能。了解何时以及如何使用这些功能是一件复杂的工作,而且易于出错。此外,J2EE的安全性无法满足许多Web应用程序开发人员的需要。 BEA WebLogic Server实现了所有J2EE Web应用程序的安全功能,并扩展它们以帮助完成一些单独使用J2EE API所不可能完成的任务。

Web应用程序安全性
  J2EE提供两个用于保护Web应用程序的基本机制:

  • 加密:有一个机制用于指定访问特定的URL时,是否必须使用SSL(安全套接字层,secure sockets layer)。使用SSL时,它可以确保中间人不能查看和修改用户浏览器和服务器之间的通信。SLL还允许用户核实,他们是将(可能是机密的)消息发送给 预定的目的地,而不是发送给冒名顶替者。
  • 基于角色的安全性:角色是授予用户的权限集合,它支持站点允许特定的用户访问站点的不同部分。可以使用声明性的方法,即把特定的URL限制给属于某个角色组的用户,也可以使用编程接口来确定当前用户是否属于某个特定角色。

Web应用程序示例
  本文开发了一个示例应用程序。该应用程序的骨架可以在www.sys-con.com/weblogic/sourcec.cfm上找到。这个骨架包含了该应用程序的所有Web页面和部署描述符,但是省略了所有与安全性没有直接关系的内容。
  该应用程序已经在BEA WebLogic Server 8.1上进行了测试。除了部署Web应用程序之外,还必须完成两件事情才能使该Web应用程序运行起来:

  • 您必须创建一个“Customers”组。这可以在控制台中的Security >Realms >myrealm> Groups选项卡下完成。无需填充该组,只需创建它即可。应用程序会在需要的时候填充它。
  • 您必须创建一个名为“weblogic”的用户,然后将其放入“Administrators”组。这可以在控制台中的Security >Realm>myrealm >Users选项卡下完成。

  当上述操作出现时,就会随即说明需要它们的原因。

加密(SSL)
  为了保证与用户交互时的机密性,站点通常使用SSL来执行对敏感页面的加密。在浏览器中,SSL使用以“https”,而不是“http”开头的URL表示。
  不幸的是,和许多安全技术一样,使用加密反过来会影响性能。因此,SSL通常只用于敏感页面。敏感页面就是包含机密数据的任意页面,不论是通过表单从服务器出站的还是从用户浏览器入站的。这项规则有一些例外。
  通常,应该对在其他安全会话中间的非敏感页面(比如,购买交易中间的广告)进行加密。除了方便开发人员之外,当浏览器从加密会话变为明文会话时,许多浏览器还使用提示来通知用户。为了避免可能出现的混乱提示,请对这些不安全的页面使用加密。
  此外,如果用户要填入的数据包含敏感信息,应该对包含表单的页面进行加密。例如,考虑一个需要您填入姓名和信用卡号的表单。提交表单时,它必须使用加 密来保护机密信息,但是也应该对表单本身进行加密,即便它没有包含机密信息也是如此。这是必需的,因为当一个页面已经被加密时,浏览器通常会在它们的底部 边缘处显示一个锁定记号。一些用户如果没有看见这个锁定记号,他们就不会将安全数据输入到表单中。注意,这个锁定记号与表单数据无关,用户实际上想要保护 的信息将被加密。这个锁定记号仅仅表示表单已经被加密。所以,尽管该锁定记号通常是没有关系的,还是应该使用加密让用户放宽心。您可以请求加密一个页面, 具体方法是指定传输保证(transport guarantee)为“INTEGRAL”或“CONFIDENTIAL”(请参见详细信息)。
  为了给出一个具体的例子,请考虑一个非常简单的应用程序,它支持在线购物。它包含以下文件:

  • catalog.jsp:允许浏览和搜索目录。可以从目录中将物品加入到购物车中。
  • shoppingcart.jsp:显示内容,并允许操纵购物车。用户可以购买车中的物品,也可以继续购物。
  • billinginfo.jsp:搜集发货地址和帐单信息,并把它们发送给orderstatus.jsp。
  • orderstatus.jsp:执行订单。如果成功,它将显示一条成功消息;如果失败,它将返回billinginfo,以便显示错误并允许用户纠正它。

  图1显示了这个站点的流程以及需要使用加密的情况。只有orderstatus.jsp页面需要使用加密,因为 发送来自billinginfo.jsp的表单中包含敏感数据。但是,建议也对billinginfo.jsp进行加密,以便用户能够看见浏览器工具栏上 的锁定记号。清单1显示了web.xml文件的一个片断,该文件将用于满足这些加密要求。


图1:需要加密的站点流程

  当您指定需要加密的<transport-guarantee>时,BEA WebLogic Server不会允许出现非SSL的连接。如果试图进行非SSL的连接,WebLogic Server将发送重定向给浏览器,以使其通过SSL访问页面。这将为转换为SSL提供一种便捷的方法。也就是说,shoppingcart.jsp无需 指定应该对shoppingcart.jsp使用SSL。应用服务器将自动确保这一点。例如,在我们的示例Web应用程序中,shoppingcart. jsp中指向billinginfo.jsp的链接是:

<a href="billinginfo.jsp"> Checkout </a>

  它没有指定HTTPS。WebLogic Server将确保使用HTTPS。从这种行为中衍生出两个问题:

  1. 您决不应该依赖于这种从SSL到安全表单数据的自动转换。一旦数据以未加密的方式发往服务器,它现在是否已加密都不要紧。正如示 例Web应用程序所做的那样,通过加密表单页面,它确保了这个问题不会出现。对表单的请求可能发送两次,第一次不加密,而第二次加密,但是只能以加密的方 式发送表单数据中的安全信息。
  2. 没有办法自动返回到未加密的通信。如果您永不指定协议,一旦选中SSL,它将会用于其余的交互。 在我们的示例中,所有返回到目录的链接都显式地指定了HTTP。由于其频繁使用和大量数据(尤其是图片),对目录进行加密将对性能来说是个恶梦。在我们的 示例Web应用程序中,无论何时链接到目录,我们都显式地指定HTTP,如下所示:

    <a
    href="http://<%=request.getServerName()%>:
    <%=request.getServerPort()%><%=request.getContextPath()%>
    /catalog.jsp"> Continue Shopping </a>

基于角色的安全性
  尽管加密确保了通过网络传输的数据不会被中间人读取或篡改,它这是针对全体用户而言的。另一方面,基于角色的安全性用于根据用户的既定权限对他们进行分类,然后基于这些分类授权访问Web页面。
  基于角色的安全性应该用在以下两种情况之一。第一种情况,当您想要把站点的某些部分限制给所有用户的一部分访问。在我们的示例中,我们将说明如何把站 点的一部分限制给“Customer”角色,但是其他角色也是可以的。例如,您可以想像给站点添加更多功能(比如搜索订单的能力),以给客户和雇员提供支 持。
第二种情况,当您需要了解用户的身份时,应该使用基于角色的安全性。复杂的任务,比如维护有关一个用户访问了哪些页面的统计信息,和简单的任务,比如显示一条包含用户名称的欢迎消息,都需要用到用户名。
可以通过调用下面的方法来获得用户名:

request.getRemoteUser()

  该方法只会在用户已经登录之后返回用户名。在登录之前,用户处于匿名状态,并且getRemoteUser()返回空。强制用户进行登录的最简单方式 是让他们访问受保护的页面。这会强制容器执行登录过程,在这之后,getRemoteUser()将返回一个有效的用户名。
  在我们的示例中,shoppingcart.jsp需要登录,以便我们使用客户的用户名在数据库中查找他们的购物车。虽然我们的例子实际上没有访问数据库,但是它在标题中打印出了用户名。
  为了给上述示例添加基于角色的安全性,我们将增加维护客户的购物车和购买行为的永久性记录能力。为了实现这种能力,Web应用程序必须确保只有通过了 身份验证的用户才允许访问购物车。用户通过身份验证之后,购物车和订单信息可以被保存在与用户相关的数据库中。图2说明了新的Web应用程序和其中基于角 色的安全性的使用。清单2是用于配置这种安全性的web.xml文件的一个片断。有一个特点要引起注意,即无需在catalog.jsp中添加到 login.jsp页面的显式链接。只要链接到shoppingcart.jsp即可,然后根据<security- constraint> 和<login-config>标签,servlet容器将会把login.jsp页面表示在您的面前。正好,它会在任何引用了 shoppingcart.jsp(就此处而论,或任何受到保护的页面),而当前用户尚未登录的地方放置login.jsp页面。此外,如果当前用户的身 份不是Customer,那么他们将收到一个访问被拒绝的错误页面(即HTTP error code 403)。


图2:使用了基于角色的安全性的新Web 应用程序

声明性和编程性安全
  以此种方式在部署描述符中指定安全机制被称为“声明性安全(declarative security)”。这是与“编程性安全(programmatic security)”相对应的。使用编程性安全时,安全机制嵌入在您的代码中。声明性安全优于编程性安全的主要方面有:

  • 简单性:安全性代码往往极难编写,而且易于出错。声明性安全允许您不编写安全性代码,而只要“声明”您的安全要求即可,servlet容器将为您完成余下的工作。
  • 易维护性:当安全机制嵌入在您的程序中时(即编程性安全),安全性的变化意味着必须重写代码。使用声明性安全时,往往只需修改部署描述符。例如,在我们的示例中,如果业务要求出现变化,只有已注册客户才能访问目录,此时惟一需要做的改动便是修改部署描述符中的标签。
  • 责 任分离:编程的工作通常是由工程师完成的。安全性则通常是由工程师、业务分析员、应用程序开发人员和其他人共同实现的。如果应用程序的安全机制嵌入在代码 中,那么只有工程师才能修改它。如果把安全机制嵌入在部署描述符中,那么可以在开发之后修改安全机制,而无需工程师的参与。

在线用户注册
  为了进一步完善这个示例,我们可以添加允许新用户注册的页面。图3描述了该流程。login.jsp表单上有一个指向newuser.jsp页面的 “New User”链接。在这个页面上,用户可以输入一个用户名和相应的密码,然后把表单提交给userstatus.jsp。如果用户创建不成功, userstatus.jsp将进行重定向,返回到newuser.jsp页面,然后在页面的顶部显示一条相应的错误消息。如果用户创建成功, userstatus.jsp将会让该用户登录,打印一条成功的消息,然后为用户提供一个链接,以便让其继续到达原来的目的地。


图3:新用户注册

  当我们进一步扩展这个示例时,要切记一件事情,即尽管图3显示login.jsp(因此还有newuser.jsp)页面只会在 catalog.jsp和shoppingcart.jsp之间执行,它还是有可能出现在其他地方。每当未通过身份验证的用户访问受到保护的页面时, login.jsp页面就有可能出现。即使没有指向其他页面(比如billinginfo.jsp)的链接,用户可以在浏览器中键入URL,或者他们可以 把这些页面加入到收藏夹中。
  在着手处理一些参数之后,userstatus.jsp会创建一个用户。J2EE没有为用户创建提供标准的机制,但是BEA WebLogic Server却通过UserEditorMBean接口提供了该机制。获得UserEditorMBean之后,需要做的就是调用 userEditorMBean.createUser(username, password, "");
  (第三个参数是关于用户的描述性文本,这个例子中没有使用。)该操作是受到保护的,只对Admin角色中的用户可用。为了让userstatus.jsp正确执行,它需要有一个run-as标签,以便让它以Admin用户的身份运行。部署描述符的代码如下:

<servlet>
<servlet-name> userstatus </servlet-name>
<jsp-file> /userstatus.jsp </jsp-file>
<run-as>
<role-name> weblogic </role-name>
</run-as>
</servlet>

  记住,确保已经创建了“weblogic”用户,并按照先前所述,将它放在“Administrators”组中,以确保代码能够正常工作。
  创建好用户之后,servlet会让新用户登录。J2EE也不支持通过编程让用户登录,但是WebLogic Server通过以下代码支持这种做法:

SimpleCallbackHandler callbackHandler =
new SimpleCallbackHandler(username, password);
ServletAuthentication
.authenticate(callbackHandler, request);

  最后,userstatus.jsp将显示一条成功的消息,以及一个用于继续下去的链接。这里的困难之处在于,该链接的目的地可能是任何受保护的页 面,并没有限定是shoppingcart.jsp。这是因为只要有受保护的页面被访问,身份验证过程就会开始。尽管J2EE没有提供用于发现目的地 URL的机制,WebLogic Server可以通过以下调用来访问它:

ServletAuthentication.getTargetURLForFormAuthentication
(request.getSession())

  有一点要注意,即要想使上面的语句达到预期效果,新用户必须放入Customer角色。这是在一个两步骤过程中完成的。首先,Customer角色被 映射到Customers组(组是用户的集合,一定要按照如前所述进行创建)。该映射通过下面的代码行在weblogic.xml中完成:

<security-role-assignment>
<role-name>Customer</role-name>
<principal-name>Customers</principal-name>
</security-role-assignment>

  接下来,在创建用户之后,Web应用程序使用WebLogic扩展把新用户放入Customers组,方法是调用:

groupEditorMBean.addMemberToGroup("Customers", username);

编程性安全
  尽管J2EE支持编程性安全,但是使用它是有风险的。它往往导致代码变得缺乏灵活性,而且易于出现错误。但是,为了实现个性化而使用编程性安全API 却可以收到良好的效果。假定扩展我们上面的示例,使其包含一个离开目录页面的链接,而目录页面允许您通过updatentry.jsp更新目录项。这个链 接只适用于CatalogAdmin角色中的用户。catalog.jsp中的以下代码将引入一个通向updateentry.jsp的条件性链接。该链 接只对CatalogAdmin角色中的用户可见,就像”Logout“链接只对已登录的用户可见一样。

<% if (request.isUserInRole("CatalogAdmin")) { %>
<a href="updateentry.jsp?productid=<%=getProductID()%>">
Update Catalog Entry</a>
<% } %>

  这段代码假定updateentry.jsp带有一个productid参数,而且具有的getProductID()方法的作用是返回当前所示产品的ID。

完成
  图4说明了完成后的应用程序流程,它同时描述了加密和基于角色的安全性。尽管必须结合使用加密和基于角色的安全性,以确保Web应用程序中的安全性, 但它们用于不同的目的。加密用于确保网络上数据的安全性。基于角色的安全性用于对用户进行分类,并根据用户的类别授予权限。J2EE提供通过Web应用程 序的web.xml文件启用这些安全功能的机制。此外,J2EE还提供一些用于编程性安全的标准机制,比如访问用户的名称。


图4:完成后的应用程序流程

  BEA webLogic Server的安全性扩展,比如UserEditorMBean和GroupEditorMBean,可用于用户管理。J2EE标准中没有包含用户管理的 功能。在我们的示例中,我们使用这些用户管理功能来实现在线用户注册,这是一项在许多Web站点中很常见的功能。
  BEA WebLogic Server 还扩展了编程性安全,启用了登录到服务器的编程性机制。通过使用ServletAuthentication.authenticate()和ServletAuthentication. getTargetURLForFormAuthentication(),我们的示例演示了如何以编程的方式实现用户登录,以及将用户重定向到他们原来的目的地。
  设计这些WebLogic Server扩展的目的是与J2EE中可用于Web应用程序的安全性功能相吻合。它们填补了标准J2EE安全性功能中的空白,允许实现功能更加丰富、更加多样的Web应用程序。

原文出处
http://www.sys-con.com/story/?storyid=43021&DE=1

<!--文章其他信息-->
作者简介
Neil Smithline是架构和开发过许多企业应用程序,利用了各种技术,包括applet、EJB、JavaScript和Java Web应用程序。他当前是BEA核心安全架构师。通过这一工作,他接触到J2EE安全性的所有方面以及许多其他安全标准和技术。Neil还有一个重要任 务,即探索新的安全技术并且将它们与WebLogic Server进行集成。 Neil常常与大企业打交道,帮助他们构建安全解决方案来满足他们的独特需求。他是JSR-196委员会的成员,这个委员会正在为J2EE开发新的验证标 准。 Neil拥有SUNY Buffalo的计算机科学学士学位和罗切斯特大学的计算机科学硕士学位。
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics