// 
//     Licensed to the Apache Software Foundation (ASF) under one
//     or more contributor license agreements.  See the NOTICE file
//     distributed with this work for additional information
//     regarding copyright ownership.  The ASF licenses this file
//     to you under the Apache License, Version 2.0 (the
//     "License"); you may not use this file except in compliance
//     with the License.  You may obtain a copy of the License at
// 
//       http://www.apache.org/licenses/LICENSE-2.0
// 
//     Unless required by applicable law or agreed to in writing,
//     software distributed under the License is distributed on an
//     "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
//     KIND, either express or implied.  See the License for the
//     specific language governing permissions and limitations
//     under the License.
//

= 在 Java EE 中构建安全企业 Bean
:jbake-type: tutorial
:jbake-tags: tutorials 
:jbake-status: published
:icons: font
:syntax: true
:source-highlighter: pygments
:toc: left
:toc-title:
:description: 在 Java EE 中构建安全企业 Bean - Apache NetBeans
:keywords: Apache NetBeans, Tutorials, 在 Java EE 中构建安全企业 Bean

通过 NetBeans IDE 中的 Java EE 规范支持，您可以充分利用许多 Java EE 功能来简化应用程序开发。Java EE 5 规范的一个重大改进是采用了标注。使用标注，您可以消除在对应用程序进行编码时所使用的许多模板代码，并最大限度地减少部署应用程序时所需的配置量。

通过使用标注而得到极大简化的一个领域是企业 Bean 的开发和配置。使用标注，您可以指定以前在部署描述符文件中所指定的许多配置属性，从而使很多部署描述符文件变得不再必需。尽管应用程序可能仍然需要一些部署描述符文件（如  ``web.xml`` ），但 IDE 的多视图部署描述符编辑器大大简化了对这些文件的编辑。

通过使用标注，现在构建安全的企业 Bean 要简单得多。您可以使用安全标注直接在源代码中配置授权，而无需在  ``ejb-jar.xml``  部署描述符中配置企业 Bean 安全性。Java EE 5 企业应用程序不需要  ``ejb-jar.xml``  或  ``application.xml`` 。

有关 Java EE 规范的一些特性的概述，请参见 link:javaee-intro.html[+Java EE 技术简介+]。有关标注规范的详细信息，请参见 link:http://jcp.org/en/jsr/detail?id=250[+JSR 250：Java 平台的常用标注+]。


*要学习本教程，您需要具备以下软件和资源。*

|===
|软件或资源 |要求的版本 

|link:https://netbeans.org/downloads/index.html[+NetBeans IDE+] |7.2、7.3、7.4、8.0、Java EE 版本 

|link:http://www.oracle.com/technetwork/java/javase/downloads/index.html[+Java 开发工具包 (JDK)+] |版本 7 或 8 

|GlassFish Server |3.1.x、4.x 
|===

在学习本教程之前，您需要在 IDE 中注册 GlassFish Server 的本地实例。如果您安装了 "Java EE" 版本的 IDE，则应已安装并注册应用服务器。如果在 IDE 中未注册该应用服务器，请选择 "Tools"（工具）> "Servers"（服务器），以在服务器管理器中注册它。您不能将企业应用程序部署到 Tomcat Web 服务器。

*先决条件*

本文档假定您具备以下技术的一些基本知识或编程经验：

* Java 编程
* NetBeans IDE


== 在应用服务器上创建安全组

在本示例中，您仅希望  ``bank_users``  组的用户访问企业 Bean。您将在应用服务器  ``file``  安全领域的  ``bank_users``  组中创建  ``manager``  用户。

1. 启动应用服务器，方法是：在 "Services"（服务）窗口中右键单击应用服务器的节点，然后选择 "Start"（启动）。
2. 右键单击应用服务器节点，然后选择 "View Domain Admin Console"（查看域管理控制台），以便在浏览器中打开 GlassFish Server 管理控制台。
3. 展开左导航栏中 "Configurations"（配置）节点下方的 *server-config* 节点。
4. 单击 *"Security"（安全性）> "Realms"（领域）> "file"*，以打开 "Edit Realm"（编辑领域）框架。

image::images/console-file-realm.png[title="在应用服务器的管理控制台中选择文件领域节点"]


[start=5]
. 单击 "Edit Realm"（编辑领域）面板顶部的 "Manage Users"（管理用户）按钮，打开 "File Users"（文件用户）面板。

image::images/console-edit-realm.png[title="应用服务器的管理控制台中的 "Edit Realm"（编辑领域）面板代码"]


[start=6]
. 单击 "File Users"（文件用户）面板中 "File Users"（文件用户）表顶部的 "New"（新建）按钮。

[start=7]
. 在 "New File Realm User"（新建文件领域用户）窗体中输入以下数据。单击 "OK"（确定）。
|===

|名称 |值 

|用户 ID |manager 

|组列表 |bank_users 

|Password |password 
|===

该窗体应与下图类似。

image::images/console-new-user.png[title="应用服务器的管理控制台中的 "New File Realm User"（新建文件领域用户）面板"]

在单击 "OK"（确定）后，该服务器将创建用户，并打开 "File Users"（文件用户）面板。您将会看到，现在有一个名为  ``manager``  的用户。

image::images/console-file-users.png[title="管理控制台中包含用户列表的 "File Users"（文件用户）面板"]

创建用户之后，将创建企业应用程序，以检查该用户是否能够查看数据。


== 为远程接口创建 Java 类库

在本练习中，将创建一个简单的 Java 类库项目，其中包含会话 Bean 的远程接口。然后，将编译的类库 JAR 添加到 EJB 模块以及用于调用会话 Bean 的应用程序客户端的类路径中。

1. 选择 "File"（文件）> "New Project"（新建项目），然后在 "Java" 类别中选择 "Java Class Library"（Java 类库）。单击 "Next"（下一步）。
2. 键入 SecureRemoteInterface 作为项目名称。
3. 指定项目的位置。单击 "Finish"（完成）。

在下一部分中，将在企业应用程序中创建一个会话 Bean。该会话 Bean 可通过远程接口进行访问。在创建会话 Bean 时，IDE 将自动创建类库中的远程接口，并将类库 JAR 添加到企业应用程序的类路径中。


== 创建和保护企业应用程序

企业应用程序中将包含一个简单的会话 Bean，该会话 Bean 可通过类库项目中的远程接口进行访问。


=== 创建企业应用程序项目

在本练习中，将创建一个包含 EJB 模块的企业应用程序。

1. 选择 "File"（文件）> "New Project"（新建项目）（Ctrl-Shift-N 组合键；在 Mac 上为 ⌘-Shift-N 组合键），然后从 "Java EE" 类别中选择 "Enterprise Application"（企业应用程序）模板。单击 "Next"（下一步）。
2. 键入 *Secure* 作为项目名称，并设置项目位置。
3. 取消选中 "Use Dedicated Folder"（使用专用文件夹）选项（如果该选项处于选中状态）。

在本教程中，我们将项目库复制到一个专门的文件夹中，因为需要与其他用户或项目共享库。

单击 "Next"（下一步）。

[start=4]
. 将服务器设置为 "GlassFish"，并将 Java EE 版本设置为 "Java EE 6"。

[start=5]
. 选中 "Create EJB Module"（创建 EJB 模块），并取消选中 "Create Web Application Module"（创建 Web 应用程序模块）。单击 "Finish"（完成）。

image::images/new-entapp-wizard.png[title="应用服务器的管理控制台中的 "New File Realm User"（新建文件领域用户）面板"] 


=== 确保会话 Bean 中的方法安全

在本练习中，将在 EJB 模块项目中创建一个会话 Bean。该会话 Bean 没有任何特殊的功能。它仅仅返回一个余额样例。您将创建一个  ``getStatus``  方法，并通过使用  ``@RolesAllowed``  标注对其进行标注以保护该方法 Bean，然后指定可以访问该方法的安全角色。此安全角色由应用程序使用，它与服务器上的用户和组不同。此后，将在配置部署描述符时将此安全角色映射到用户和组。

安全标注可以分别应用于类中的每个方法，也可以应用于整个类。在此简单练习中，将使用  ``@RolesAllowed``  标注方法，但 Java EE 规范还定义了其他可用在企业 Bean 中的安全标注。

1. 在 "Projects"（项目）窗口中，右键单击 EJB 模块的节点 (Secure-ejb)，然后选择 "New"（新建）> "Session Bean"（会话 Bean）。
2. 键入 *AccountStatus* 作为 Bean 名称，并键入 *bean* 作为包。
3. 选中 "Remote in project"（以远程方式位于项目中）作为接口类型。
4. 在下拉列表中选择 "SecureRemoteInterface"。单击 "Finish"（完成）。

image::images/new-sessionbean-wizard.png[title="新建会话 Bean 向导中选中了远程接口"]

单击 "Finish"（完成），此时 IDE 将创建  ``AccountStatus``  类并在源代码编辑器中打开该文件。

IDE 还将在 SecureRemoteInterface 类库项目中为  ``bean``  包中的 Bean 创建  ``AccountStatusRemote``  远程接口，并将 SecureRemoteInterface 类库 JAR 添加到了 EJB 模块项目的类路径中。

image::images/projects-window-bean.png[title="显示类路径上的会话 Bean 和类库的 "Projects"（项目）窗口"]

如果打开 EJB 模块的 "Properties"（属性）对话框的 "Libraries"（库）类别，则会看到 JAR 已添加到编译时库中。


[start=5]
. 在源代码编辑器中，将以下字段声明（以粗体显示）添加到  ``AccountStatus``  中：

[source,java]
----

public class AccountStatus implements AccountStatusRemote {
    *private String amount = "250";*
----

[start=6]
. 在源代码编辑器中，右键单击类，并选择 "Insert Code"（插入代码）（Alt-Insert 组合键；在 Mac 上为 Ctrl-I 组合键），然后选择 "Add Business Method"（添加 Business 方法），以打开 "Add Business Method"（添加 Business 方法）对话框。

[start=7]
. 键入 *getStatus* 作为方法名称，并将返回类型设置为  ``String`` 。

IDE 将自动在远程接口中公开此业务方法。


[start=8]
. 在源代码编辑器中，将以下代码行（以粗体显示）添加到  ``getStatus``  方法中。

[source,java]
----

public String getStatus() {
*    return "The account contains $" + amount;*
}
----

[start=9]
. 键入以下内容（以粗体显示）来标注  ``getStatus``  方法。*@RolesAllowed({"USERS"})*

[source,java]
----

public String getStatus() {
----

此标注表示只有安全角色为  ``USERS``  的用户才能访问  ``getStatus``  方法。


[start=10]
. 在编辑器中右键单击并选择 "Fix Imports"（修复导入）（Alt-Shift-I 组合键；在 Mac 中为 ⌘-Shift-I 组合键），然后保存您的更改。确保  ``javax.annotation.security.RolesAllowed``  已添加到该文件中。


=== 配置部署描述符

Java EE 企业应用程序通常不需要部署描述符文件，如  ``ejb-jar.xml`` 。如果展开 Secure-ejb 或 Secure 企业应用程序下面的 "Configuration Files"（配置文件）节点，则会看到没有部署描述符。您可以使用标注指定很多已在  ``ejb-jar.xml``  中配置的属性。在本示例中，您通过在会话 Bean 中使用  ``@RolesAllowed``  标注为 EJB 方法指定了安全角色。

不过，在为应用程序配置安全性时，仍然需要在部署描述符中指定一些属性。在本示例中，您需要将企业应用程序中使用的安全角色 ( ``USERS`` ) 映射到在应用服务器上配置的用户和组。您已在应用服务器上创建了  ``bank_users``  组，现在需要将该组映射到企业应用程序中的安全角色  ``USERS`` 。为此，可以编辑企业应用程序的  ``glassfish-application.xml``  部署描述符。

因为企业应用程序不需要部署描述符便可运行，所以 IDE 默认情况下不创建部署描述符。因此，首先需要创建部署描述符文件，然后在多视图编辑器中编辑该文件，以配置安全角色映射。

1. 右键单击 "Secure" 企业应用程序项目，然后选择 "New"（新建）> "Other"（其他），以打开新建文件向导。

此外，也可以从主菜单中选择 "File"（文件）> "New File"（新建文件），以打开新建文件向导。在这种情况下，请确保在 "Project"（项目）下拉列表中选择了 "Secure" 项目。


[start=2]
. 选择 "GlassFish" 类别，然后再选择 "GlassFish Descriptor"（GlassFish 描述符）文件类型。单击 "Next"（下一步）。

image::images/new-gf-descriptor.png[title="新建文件向导中的 GlassFish 描述符文件类型"]


[start=3]
. 接受该向导中的默认值，然后单击 "Finish"（完成）。

单击 "Finish"（完成），此时 IDE 将创建  ``glassfish-application.xml``  并在多视图编辑器中打开该文件。

如果在 "Projects"（项目）窗口中展开 "Secure" 企业应用程序项目节点，则可以看到描述符文件在 "Configuration Files"（配置文件）节点的下方创建。

image::images/glassfish-application-descriptor.png[title="多视图编辑器中的 "Security"（安全）标签"]


[start=4]
. 在多视图编辑器的 "Security"（安全）标签中，单击 "Add Security Role Mapping"（添加安全角色映射），然后在 "Security Role Name"（安全角色名称）中键入 *USERS*。

[start=5]
. 单击 "Add Group"（添加组），然后在对话框的 "Group Name"（组名称）中键入 *bank_users*。单击 "OK"（确定）。

编辑器现在应如下所示。

image::images/security-tab-descriptor.png[title="多视图编辑器中的 "Security"（安全）标签"]


[start=6]
. 保存所做的更改。

通过单击多视图编辑器中的 "XML" 标签，可以在 XML 视图中查看部署描述符文件。您可以看到该部署描述符文件现在包含以下代码：


[source,xml]
----

<glassfish-application>
  <security-role-mapping>
    <role-name>USERS</role-name>
    <group-name>bank_users</group-name>
  </security-role-mapping>
</glassfish-application>
----

 ``getStatus``  方法现在是安全的，只有在服务器上指定的  ``bank_users``  组中的用户才能访问该方法。

现在，您需要一种安全设置测试方法。最简单的方法是，创建一个基本应用程序客户端，以提示用户输入用户名和口令。


== 创建应用程序客户端

在本部分中，将创建一个简单的应用程序客户端，以访问  ``AccountStatus``  会话 Bean。您可以在代码中使用  ``@EJB``  标注，以便通过远程接口调用 Bean。IDE 会将包含该接口的类库 JAR 自动添加到应用程序客户端的类路径中。

1. 选择 "File"（文件）> "New Project"（新建项目），然后在 "Java EE" 类别中选择 "Enterprise Application Client"（企业应用程序客户端）。单击 "Next"（下一步）。
2. 键入 SecureAppClient 作为项目名称。单击 "Next"（下一步）。
3. 在 "Add to Enterprise Application"（添加到企业应用程序）下拉列表中选择 *<None>*。
4. 在 "Server"（服务器）下拉列表中选择 "GlassFish Server"，并选择 "Java EE 6" 或 "Java EE 7" 作为 Java EE 版本。单击 "Finish"（完成）。

单击 "Finish"（完成），此时将在源代码编辑器中打开  ``Main.java`` 。


[start=5]
. 在源代码编辑器中，右键单击  ``Main.java``  文件，并选择 "Insert Code"（插入代码）（Alt-Insert 组合键；在 Mac 上为 Ctrl-I 组合键），然后选择 "Call Enterprise Bean"（调用企业 Bean）。

[start=6]
. 在 "Call Enterprise Bean"（调用企业 Bean）对话框中，展开 "Secure-ejb" 节点，然后选择 "AccountStatus"。单击 "OK"（确定）。

image::images/call-enterprise-bean.png[title=""Call Enterprise Bean"（调用企业 Bean）对话框中选中了接口"]

IDE 将在应用程序客户端中添加以下代码，用于查找会话 Bean。


[source,java]
----

@EJB
private static AccountStatusRemote accountStatus;
----

如果在 "Projects"（项目）窗口中展开 "Libraries"（库）节点，则可以看到 IDE 已将 SecureRemoteInterface JAR 添加到了项目类路径中。


[start=7]
. 通过添加以下代码来修改  ``main``  方法，然后保存所做的更改。

[source,java]
----

public static void main(String[] args) {
    *System.out.println(accountStatus.getStatus());*
}
----

有关应用程序客户端的详细信息，请参见link:entappclient.html[+在 GlassFish Server 上创建和运行应用程序客户端+]。


== 运行应用程序

现在该应用程序已准备就绪。首先，将企业应用程序部署到服务器。部署企业应用程序之后，可以运行应用程序客户端，以测试该企业应用程序中的方法是否安全，以及用户角色映射是否正确。在运行应用程序客户端时，系统将提示您输入  ``bank_users``  组中用户的用户名和口令。

1. 在 "Projects"（项目）窗口中右键单击 "Secure" 企业应用程序项目节点，然后选择 "Deploy"（部署）。

在单击 "Deploy"（部署）后，IDE 将构建 EAR 文件，启动应用服务器（如果没有运行），并将该 EAR 文件部署到该服务器。


[start=2]
. 在 "Projects"（项目）窗口中右键单击 "SecureAppClient" 项目节点，然后选择 "Run"（运行）。此时将出现一个对话框，提示您输入用户名和口令。

image::images/login-window.png[title="提示输入用户名和口令的登录窗口"]


[start=3]
. 在对话框中输入用户名 ( ``manager`` ) 和口令 ( ``password`` )，然后单击 "OK"（确定）。"Output"（输出）窗口中将显示以下内容：

[source,java]
----

The account contains 250$
----

这是一个非常基本的示例，用于说明如何使用 Java 标注保护企业 Bean 中的方法。

link:/about/contact_form.html?to=3&subject=Feedback:%20Building%20Secure%20Enterprise%20Beans[+发送有关此教程的反馈意见+]



== 另请参见

有关使用标注和部署描述符来确保企业 Bean 安全的更多信息，请参见以下资源：

* Java EE 7 教程的link:http://docs.oracle.com/javaee/7/tutorial/doc/partsecurity.htm[+安全性+]部分的link:http://docs.oracle.com/javaee/7/tutorial/doc/security-intro003.htm[+确保容器的安全+]和link:http://docs.oracle.com/javaee/7/tutorial/doc/security-advanced008.htm[+使用部署描述符配置安全性+]这两章

有关使用 NetBeans IDE 开发 Java EE 应用程序的更多信息，请参见以下资源：

* link:javaee-intro.html[+Java EE 技术简介+]
* link:javaee-gettingstarted.html[+Java EE 应用程序入门指南+]
* link:../../trails/java-ee.html[+Java EE 和 Java Web 学习资源+]

要发送意见和建议、获得支持以及随时了解 NetBeans IDE Java EE 开发功能的最新开发情况，请link:../../../community/lists/top.html[+加入 nbj2ee 邮件列表+]。

