By Shing Wai Chan, 7/14/08 |
|
安全性对于企业环境非常重要。在 Java EE 5 / GlassFish 环境中,您可以通过以下几种方式实现安全性:
本文讨论身份验证和授权。参考资料 [1]、[2] 和 [3] 讨论了如何在客户端和服务器端为 Enterprise JavaBeans 和 Web 服务建立 SSL 环境。Web 服务的消息层安全性将在以后的文章中讨论。
身份验证服务一般通过要求用户输入用户名和密码来实现校验用户身份的目的。在 Java EE 环境中,身份验证是和域(realm)相关联的。域可以通过多种方式存储用户身份信息,包括文件、LDAP 目录、甚至是通过 JDBC 访问的数据库(请参阅 参考资料 [4])。它还可以与 Solaris 可拔插验证模块 (Pluggable Authentication Modules, PAM) 框架一起工作。
授权服务根据所运行的软件和运行该软件的用户的身份来执行访问控制授权操作。每次当用户登录时,应用程序都会为他/她赋予一组权限。
在 Java EE 5 之前,如果您希望在某个应用程序使用授权,则需要在应用程序部署描述符 ejb-jar.xml 或 web.xml 中指定授权信息。Java EE 5 的重要改进之一就是简化了 Java EE 应用程序的开发。从 Java EE 5 开始,开发人员可以在 Java 源文件中指定注释,而无需在部署描述符中加入元数据。注释简化了 Java EE 应用程序的开发,缩短了开发周期,并降低了总体拥有成本。
JSR 250(请参阅 参考资料 [5])定义了 Java 平台中的常用注释。本文将讨论 JSR 250 中定义的安全注释,并演示如何在应用程序中通过它们来实现身份验证和授权,以获得安全性。
- | 基本定义和示例 |
- | 注释的无效用法示例 |
- | 安全注释的继承 |
- | 使用部署描述符 |
- | 结束语 |
- | 参考资料 |
- | 致谢 |
注释 (Annotation) 是一种特殊的修饰符,可以与其他修饰符共同使用。注释由 @
符号、注释类型和包含在括号中的元素值对列表组成。
本节讨论 JSR 250 定义的常用安全注释。共有 5 种(请参阅 参考资料 [6]):
javax.annotation.security.PermitAll
javax.annotation.security.DenyAll
javax.annotation.security.RolesAllowed
javax.annotation.security.DeclareRoles
javax.annotation.security.RunAs
@PermitAll
、@DenyAll
和 @RolesAllowed
注释是为指定 EJB 业务方法权限而定义的。@DeclareRoles
和 @RunAs
是 TYPE 级注释,用于指定与角色相关的元数据。
对于 Web 模块,您仍然需要在 web.xml 应用程序部署描述符中定义一个 <security-constraint>
来添加授权约束,这与 J2EE 1.4 相类似。在 Java EE 5 环境中,与权限相关的注释仅为 EJB 模块定义。下表总结了这些注释的基本用法。有关详细信息,请参阅 JSR 250 规范(参考资料 [5])。
注释
目标
EJB 或其超类
Servlet 或 Web 库
描述
类型
方法
|
X |
X |
X |
指示某 EJB 的某个方法或所有业务方法允许被所有用户访问。 |
|
|
X |
X |
指示 EJB 的某个方法不允许被任何用户访问。 |
||
|
X |
X |
X |
指示 EJB 的某个方法或所有业务方法允许被角色列表中的用户访问。 |
|
|
X |
X |
X |
定义安全检查的角色,供 EJBContext.isCallerInRole、HttpServletRequest.isUserInRole 和 WebServiceContext.isUserInRole 使用。 |
|
|
X |
X(不适用于非 EJB 超类) |
X(仅适用于 Servlet) |
指定某个组件的 run-as 角色。 |
注意:
@PermitAll
、@DenyAll
和 @RolesAllowed
注释,类级别的注释适用于类,方法级的注释适用于方法。方法级注释覆盖类级注释行为。 @Stateless |
hello()
方法允许被所有用户访问,bye()
方法允许被 javaee 角色中的用户访问。@DeclareRoles
注释定义了某个组件将要使用的角色列表。在 Java EE 5 环境中,您可以通过 @javax.annotation.Resource
来查找资源,以及通过调用以下 API 来确认用户是否属于某个角色:组件
检查角色的 API
EJB |
|
Servlet |
|
Web 服务 |
|
@PermitAll
、@DenyAll
和 @RolesAllowed
注释允许实现大部分的授权决策,但仍需要 @DeclareRoles
注释来帮助实现更为复杂的逻辑。 hello
方法允许被属于角色 A 但同时不属于角色 B 的用户访问,则以下代码片段可以实现此目的: @Stateless |
@DeclareRoles
。JSP 页面不支持注释。 @DenyAll
、@PermitAll
和 @RolesAllowed
。例如,以下这些用法是无效的: @PermitAll |
@RolesAllowed
注释两次以上。 @RolesAllowed("javaee") |
@RolesAllowed
注释中提供授权角色列表以实现想要的效果,如下所示: @RolesAllowed({"javaee", "j2ee"}) |
本节讨论安全注释的继承。因为 GlassFish 方法的默认行为是 @PermitAll
,因此为便于阅读,以下讨论将省略该注释。
继承的一般规则如下:
@RunAs
注释,只考虑层次结构叶节点中的注释。 @DeclareRoles
注释,继承附加在继承层次结构中。下面这个示例演示了这些注释继承规则:
示例:在 EJB 的如下层次结构中:
<!-- BEGIN IMAGE WITHOUT CAPTION -->
|
可以使用以下方法权限:
Hello 方法
HelloBaseEJB 方法权限
HelloEJB 方法权限
|
允许被 manager 角色中的用户访问 |
允许被所有用户访问 |
|
允许被 employee 角色中的用户访问 |
允许被 staff 角色中的用户访问 |
|
允许被 employee 角色中的用户访问 |
允许被 staff 角色中的用户访问 |
示例:在 Servlet 的以下层次结构中:
<!-- BEGIN IMAGE WITHOUT CAPTION -->
|
Servlet
定义的角色
RunAs
|
employee |
engineer |
|
employee、manager |
staff |
|
employee |
注意,HelloServlet2
中没有设置 run-as 角色。
使用注释可以简化应用程序的部署描述符。但是在某些场景中,我们仍然需要或者更喜欢使用部署描述符。本节将描述这些场景。
@RolesAllowed
的 EJB Web 服务端点,您需要在 sun-ejb-jar.xml 中指定 <login-config>
和 <auth-method>
元素来定义将要使用的身份验证类型。对于用户名密码身份验证,将 <auth-method>
元素设置为 BASIC,如以下示例所示。只有 EJB Web 服务端点需要执行此步骤,EJB 不需要。 <sun-ejb-jar> |
@PermitAll
、@RolesAllowed
和 @DenyAll
注释在 servlet 中不受支持。当使用 servlet 时,在 web.xml 部署描述符中指定身份验证和授权方式。以下信息必须在 web.xml 中指定:
<security-constraint>/<web-resource-collection>
<security-constraint>/<auth-constraint>
<login-config>
<auth-method>
(BASIC 或 FORM))、将要执行身份验证的域 (<realm-name>
),以及(如果是基于表格验证)登录表格和错误页面的位置 (<form-login-config>
)。<security-role>
该元素指定了该 Web 应用程序使用的角色列表。该列表必须包含上面提到的 <auth-constraint>
中指定的角色。 ... |
<security-role-mapping> |
@Stateless |
您可以通过应用程序部署描述符 ejb-jar.xml 来覆盖方法权限:
<!-- BEGIN VCD7 CODE SAMPLE COMPONENT --> <ejb-jar ...> |
方法
注释
部署描述文件覆盖
|
允许被所有用户访问 |
允许被 |
|
允许被 |
不允许被任何用户访问 |
|
不允许被任何用户访问 |
允许被所有用户访问 |
<realm>
元素或在 web.xml 中使用 <realm-name>
元素来覆盖该设置。 @RunAs
注 释,则需要将 run-as 角色关联到一个主体,如果只关联了一个主体,则该主体将作为 run-as 主体的默认值;如果关联了多个主体,则需要明确设置 run-as 主体。以下示例演示了如何在 sun-ejb-jar.xml 中设置 run-as 主体: ... |
以下示例演示了如何在 sun-web.xml 中设置 run-as 主体:
<!-- BEGIN VCD7 CODE SAMPLE COMPONENT --> ... |
总而言之,注释可以通过身份验证和授权为 Java EE 5 环境中的应用程序提供安全性。在 Java EE 5 环境中使用身份验证和授权时,通常需要遵循以下几个步骤:
<login-config>
。 <security-role-mapping>
元素添加到运行时部署描述文件中,在应用程序角色和应用服务器组或主体之间建立映射。javax.annotation.security
Descripton 感谢 Debbie Carson 和 Rick Palkovic 为本文提出的宝贵建议。
转系:Sun中国技术社区