保护企业Java Bean(EJB)是Java EE应用程序安全性的最重要方面之一。 IBM WebSphere Application Server社区版V2.1(以下称为社区版)是基于Apache Geronimo v2.1的免费使用的Java Enterprise Edition 5.0(Java EE5)认证的应用程序服务器,用于保护EJB应用程序。 Community Edition使用Apache OpenEJB作为其EJB容器。 通过在部署描述符中定义安全角色来配置EJB身份验证和授权,每种方法都将在该描述符中执行。 然后,您将安全角色映射到Community Edition特定的部署计划中的主体。
在本文中,我们讨论了使用Community Edition保护会话,实体和消息驱动的EJB可用的不同选项。 我们还开发了一些EJB应用程序来演示各种安全配置。 要继续学习,您需要WebSphere Application Server Community Edition v2.1。
一个没有安全性的简单EJB应用程序
让我们检查一个没有配置安全性的简单EJB应用程序。 该应用程序包含一个EJB2.1无状态会话Bean和一个EJB3无状态会话Bean。 清单1显示了该应用程序的部署描述符ejb-jar.xml
。
清单1:显示bean定义的部署描述符
<?xml version="1.0" encoding="UTF-8"?>
<ejb-jar ...>
<display-name>SimpleEjbApp</display-name>
<enterprise-beans>
<session>
<description>Simple Session Bean</description>
<display-name>SimpleSessionBean</display-name>
<ejb-name>SimpleSessionBean</ejb-name>
<home>simple.ejb21.SimpleServiceHome</home>
<remote>simple.ejb21.SimpleService</remote>
<local-home>simple.ejb21.SimpleServiceLocalHome</local-home>
<local>simple.ejb21.SimpleServiceLocal</local>
<ejb-class>simple.ejb21.SimpleServiceBean</ejb-class>
<session-type>Stateless</session-type>
<transaction-type>Container</transaction-type>
</session>
</enterprise-beans>
</ejb-jar>
注意,部署描述符仅显示一个bean定义,即SimpleSessionBean。 我们使用bean类中的注释指定EJB3会话bean的部署元数据。 清单2显示了Simple3ServiceBean的bean类。
清单2:Simple3ServiceBean类
import javax.ejb.Stateless;
...
@Stateless
public class Simple3ServiceBean implements Simple3Service {
public String commonMethod(){
...
}
public String userMethod(){
...
}
public String adminMethod(){
...
}
public String noaccessMethod(){
...
}
}
在此示例中,@Stateless批注指定Simple3ServiceBean是无状态会话Bean。
会话bean SimpleSessionBean
和Simple3ServiceBean
都没有配置任何安全性,因此所有方法都具有不受限制的访问权限。 清单3显示了此应用程序的部署计划openejb-jar.xml
。
清单3:简单的EJB应用程序部署计划
<openejb-jar ...>
<environment>
<moduleId>
<groupId>dw</groupId>
<artifactId>simple-ejb-app</artifactId>
<version>1.0</version>
<type>jar</type>
</moduleId>
<dependencies/>
<hidden-classes/>
<non-overridable-classes/>
</environment>
<enterprise-beans>
<session>
<ejb-name>SimpleSessionBean</ejb-name>
<jndi-name>ejb/SimpleSessionBean</jndi-name>
</session>
</enterprise-beans>
</openejb-jar>
EJB应用程序部署在ID为dw/simple-ejb-app/1.0/jar
。 请注意,我们将使用moduleId
元素下的信息来映射到此应用程序中的EJB,正如我们将在本文后面看到的那样。
一个演示EJB安全性的简单Web应用程序
在本文中,我们使用一个简单的Web应用程序来演示EJB安全性。 Web应用程序使用两个安全角色,即“ bank
”和“ customer
”。 该Web应用程序由一个具有不受限制的访问权限的主页和两个可通过“ bank
”和“ customer
”角色访问的安全页面组成。 每个页面都访问SimpleSessionBean
和Simple3ServiceBean
方法,并显示该方法的结果或方法调用时引发的任何异常。 清单4显示了web.xml
部署描述符。
清单4:简单的Web应用程序部署描述符
<web-app ...>
<display-name>simple-web-app</display-name>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
...
</welcome-file-list>
<login-config>
<auth-method>FORM</auth-method>
<realm-name>Not required for FORM auth</realm-name>
<form-login-config>
<form-login-page>/login/login.jsp</form-login-page>
<form-error-page>/login/loginerror.jsp</form-error-page>
</form-login-config>
</login-config>
<security-role>
<role-name>customer</role-name>
</security-role>
<security-role>
<role-name>bank</role-name>
</security-role>
<security-constraint>
<web-resource-collection>
<web-resource-name>Customer</web-resource-name>
<url-pattern>/customer/*</url-pattern>
<http-method>GET</http-method>
<http-method>POST</http-method>
</web-resource-collection>
<auth-constraint>
<role-name>customer</role-name>
<!-- This comes from the security-role element -->
</auth-constraint>
</security-constraint>
<security-constraint>
<web-resource-collection>
<web-resource-name>Bank</web-resource-name>
<url-pattern>/bank/*</url-pattern>
<http-method>GET</http-method>
<http-method>POST</http-method>
</web-resource-collection>
<auth-constraint>
<role-name>bank</role-name>
<!-- This comes from the security-role element -->
</auth-constraint>
</security-constraint>
<ejb-ref>
<ejb-ref-name>ejb/SimpleService</ejb-ref-name>
<ejb-ref-type>Session</ejb-ref-type>
<home>simple.ejb21.SimpleServiceHome</home>
<remote>simple.ejb21.SimpleService</remote>
</ejb-ref>
<ejb-ref>
<ejb-ref-name>ejb/Simple3Service</ejb-ref-name>
<ejb-ref-type>Session</ejb-ref-type>
<remote>simple.ejb3.Simple3Service</remote>
</ejb-ref>
....
</web-app>
Web应用程序使用在login-config
元素中配置的FORM身份验证。 这两个安全角色是使用security-role
元素定义的。 我们使用security-constraint
标签为资源集合配置安全权限。 在此示例中,具有bank
角色的用户可以使用/bank/*
模式访问URL,而具有customer
角色的customer
可以使用/customer/*
模式访问URL。
我们使用ejb-ref
元素声明EJB引用,以通过其远程本地和远程接口访问Bean。 在此样本中,我们定义了两个EJB引用,即ejb/SimpleService
和ejb/Simple3Service
。 注意,没有为Simple3Service
bean(它是EJB3会话bean)定义home接口。 您可以使用ejb-local-ref
元素,用于声明用于通过其本地home和本地接口访问bean的EJB引用。
在geronimo-web.xml
Web应用程序部署计划中,我们将web.xml
定义的EJB引用映射到特定的EJB,并将安全角色映射到主体。 清单5显示了示例Web应用程序的部署计划。
清单5:简单的Web应用程序部署计划
<web-app ...>
...
<context-root>simple-web-app</context-root>
<nam:ejb-ref xmlns:nam="http://geronimo.apache.org/xml/ns/naming-1.2">
<nam:ref-name>ejb/SimpleService</nam:ref-name>
<nam:pattern>
<nam:groupId>dw</nam:groupId>
<nam:artifactId>simple-ejb-app</nam:artifactId>
<nam:version>1.0</nam:version>
<nam:name>SimpleSessionBean</nam:name>
</nam:pattern>
</nam:ejb-ref>
<nam:ejb-ref xmlns:nam="http://geronimo.apache.org/xml/ns/naming-1.2">
<nam:ref-name>ejb/Simple3Service</nam:ref-name>
<nam:pattern>
<nam:groupId>dw</nam:groupId>
<nam:artifactId>simple-ejb-app</nam:artifactId>
<nam:version>1.0</nam:version>
<nam:name>Simple3ServiceBean</nam:name>
</nam:pattern>
</nam:ejb-ref>
...
<security-realm-name>SampleSecurityRealm</security-realm-name>
<app:security ...>
...
<sec:role-mappings>
<sec:role role-name="customer">
<sec:principal name="UserGrp"
class="o.a.g.s.r.providers.GeronimoGroupPrincipal"/>
...
</sec:role>
<sec:role role-name="bank">
<sec:principal name="AdminGrp"
class="o.a.g.s.r.providers.GeronimoGroupPrincipal"/>
...
</sec:role>
</sec:role-mappings>
</app:security>
</web-app>
我们使用ejb-ref
将EJB引用映射到特定EJB的元素。 在此示例中,请注意
ejb-ref
下ref-name
元素中的值 在的值相匹配
ejb-ref-name
下元件ejb-ref
中web.xml
(参见清单4 )。 同样,我们使用ejb-local-ref
元素将EJB本地引用映射到特定的EJB。
security-realm-name
元素用于配置应用程序对其进行身份验证的安全领域。 在此示例中,我们使用名称为SampleSecurityRealm
的领域。
安全角色映射到security
元素内的role-mappings
元素下的主体。 我们将role
元素用于要映射的每个安全角色。 安全角色role-name
在role
元素的role-name
属性中指定。 我们使用角色元素内的主体元素指定映射到安全角色的主体。 在此示例中,我们将bank
角色映射到名称为AdminGrp
的GeronimoGroupPrincipal
以及customer
名称为
UserGrp
的GeronimoGroupPrincipal
角色。 请参阅参考资料中提供的WebSphere Application Server Community Edition V2.0中的配置Web应用程序安全性,以详细说明角色映射的主体。
在没有EJB安全性的情况下运行示例应用程序
现在,我们将运行访问EJB应用程序中EJB的简单Web应用程序。 请注意,目前我们还没有为EJB配置安全性。 在继续进行操作之前,将样本存档下载并解压缩到您选择的目录中(我们将此目录称为<SAMPLES_HOME>
),然后将dw_users.properties和dw_groups.properties文件复制到<WASCE_HOME>
/var/security
目录( <WASCE_HOME>
是指Community Edition安装目录。
要运行示例应用程序:
- 启动Community Edition,然后在浏览器中打开
http://localhost:8080/console/
。 - 输入
system
作为用户名 ,输入manager
作为密码 。 单击登录 ,这将在管理控制台中打开“欢迎”页面。 - 浏览至Deploy New portlet。
- 在“ 计划”字段下,导航到
<SAMPLES_HOME>
并选择文件SampleSecurityRealm-plan.xml
。 - 单击安装以完成安全领域部署。
- 在“ 存档”字段下,导航到
<SAMPLES_HOME>
并选择simple-ejb-app.jar 。 - 单击安装以完成EJB应用程序部署。
- 在“存档”字段下,导航到
<SAMPLES_HOME>
并选择simple-web-app.war 。 - 单击“ 安装”以完成Web应用程序部署。
- 访问
http://localhost:8080/simple-web-app
,该屏幕显示图1中的屏幕。图1:Web应用程序主页
“ 用户信息”部分显示了Web应用程序中当前登录的用户的
UserPrincipal
和User
Roles
。 EJB2.1部分显示了调用SimpleSessionBean
每个方法的结果。 EJB3部分显示了调用Simple3ServiceBean
每个方法的结果。 由于我们尚未登录该应用程序,因此UserPrincipal
和UserRole
为空。 由于没有为任何EJB方法配置安全性,因此所有方法都是可访问的,并以未经身份验证的用户身份调用。 - 访问
http://localhost:8080/simple-web-app/bank
。 使用密码admin
以用户dwadmin
登录,
该密码显示在图2中。图2:Web应用程序银行页面
请注意,
UserPrincipal
将登录用户dwadmin
和UserRole显示为bank
。 由于没有为任何EJB方法配置安全性,因此所有方法都是可访问的,并以未经身份验证的用户身份调用。
到目前为止,我们已经看到Web应用程序通过不受限制的方法访问来调用EJB2.1和EJB3会话Bean。 接下来,我们将配置EJB2.1和EJB3会话Bean的方法权限。
EJB2.1部署描述符中的安全性配置
EJB应用程序将基于角色的安全性用于bean级和方法级安全性。 在本节中,我们将了解如何定义安全角色和配置方法权限。
定义安全角色
我们使用assembly-descriptor
下的security-role
元素在部署描述符文件ejb-jar.xml
定义安全角色。 role-name
元素指定安全角色的名称。 清单6显示了本文中使用的示例应用程序之一的ejb-jar.xml
的摘录。
清单6:显示角色定义的汇编描述符
<ejb-jar ...>
<display-name>SimpleEjbApp</display-name>
<enterprise-beans>
...
</enterprise-beans>
<assembly-descriptor>
<security-role>
<description>User role</description>
<role-name>ejbuser</role-name>
</security-role>
<security-role>
<description>Administrator role</description>
<role-name>ejbadmin</role-name>
</security-role>
...
</assembly-descriptor>
</ejb-jar>
在此示例中,应用程序定义了两个角色,即ejbuser
和ejbadmin
。
配置方法权限
为了配置安全身份以调用EJB中的方法,我们在ejb-jar.xml
enterprise-beans
元素下的bean定义中使用了security-identity
元素。 我们通过使用ejb-jar.xml
assembly-descriptor
下的method-permission
元素来配置Bean方法权限。 清单7显示了用于配置SimpleSessionBean
的方法许可权的EJB应用程序部署描述符的片段。
清单7:EJB应用程序部署描述符
<ejb-jar id="SimpleEjbAppWithSecurity" ...>
<enterprise-beans>
<session>
...
<ejb-name>SimpleSessionBean</ejb-name>
...
<security-identity>
<use-caller-identity />
</security-identity>
</session>
...
</enterprise-beans>
<assembly-descriptor>
<security-role>
...
</security-role>
<method-permission>
<role-name>ejbuser</role-name>
<method>
<ejb-name>SimpleSessionBean</ejb-name>
<method-name>userMethod</method-name>
</method>
</method-permission>
<method-permission>
<role-name>ejbadmin</role-name>
<method>
<ejb-name>SimpleSessionBean</ejb-name>
<method-name>adminMethod</method-name>
</method>
</method-permission>
<method-permission>
<unchecked/>
<method>
<ejb-name>SimpleSessionBean</ejb-name>
<method-name>commonMethod</method-name>
</method>
</method-permission>
<method-permission>
<role-name/>
<method>
<ejb-name>SimpleSessionBean</ejb-name>
<method-name>noaccessMethod</method-name>
</method>
</method-permission>
</assembly-descriptor>
</ejb-jar>
让我们看一下在此示例中使用的标签:
-
security-identity
元素指定用于调用SimpleSessionBean
方法的安全性标识。 -
use-caller-identity
元素指定将调用者的安全身份用作执行企业bean方法的安全身份。 另一种选择是使用run-as
元素,用于指定使用运行身份来调用Bean的方法,如本文稍后所述。
-
method-permission's
method
元素指定Bean中一个或多个方法的安全权限。 - 您可以使用一个或多个
role-name
元素来指定权限,每个允许访问该方法的角色都可以指定一个。 单个空的role-name
元素表示该角色无权访问该方法。 您可以使用unchecked
元素来指定不受限制的访问权限。 - 方法的
ejb-name
元素指定EJB的名称。method-name
元素指定method-name
。method-name
值“*”
对应于EJB中的所有方法。 - 特定的
method-name
对应于该名称的所有方法,包括任何重载方法。 要从重载方法中指定特定方法,请使用method-params
元素。 - 您可以在Bean的Home,Remote,Local和LocalHome接口中为方法配置
method-permission
。 要在特定接口中指定方法的许可权,请在method下的method-intf
元素中使用相应的值。
在清单7中,在SimpleSession
bean中,我们配置了:
-
userMethod
是通过访问ejbuser
作用。 -
adminMethod
是通过访问ejbadmin
作用。 -
c
ommonMethod
具有不受限制的访问。 -
noaccessMethod
不能由任何角色访问。
使用注释在EJB3 bean中进行安全性配置
在EJB3企业bean中,可以使用安全注释配置bean级和方法级安全性。 在本节中,我们讨论各种安全注释( @DeclareRoles, @DenyAll, @PermitAll, @RolesAllowed
)以及它们如何影响安全配置。 请注意,我们将在本文后面讨论@RunAs
批注。
定义安全角色
您可以通过在bean类上使用@DeclareRoles
注释来定义安全角色,如清单8所示。
清单8:具有@DeclareRoles批注的Simple3ServiceBean
@Stateless
@DeclareRoles({"ejb3user", "ejb3admin"})
public class Simple3ServiceBean implements Simple3Service {
...
}
在此示例中, Simple3ServiceBean
定义了两个安全角色,即ejb3user
和ejb3admin
。
配置方法权限
您可以使用@DenyAll, @PermitAll
和@RolesAllowed
批注配置企业bean方法的权限。 @PermitAll
和@RolesAllowed
批注可以应用于bean类以及bean方法,而@DenyAll
批注只能应用于bean方法。 应用于类的注释适用于该类中的所有方法。 应用在方法上的注释会覆盖应用在类上的所有注释。 清单9显示了Simple3ServiceBean类。
清单9:具有安全注释的Simple3ServiceBean类
@Stateless
@DeclareRoles({"ejb3user", "ejb3admin"})
public class Simple3ServiceBean implements Simple3Service {
@Resource
private SessionContext ctx;
@PermitAll
public String commonMethod() {
return logCall("commonMethod");
}
@RolesAllowed({"ejb3user"})
public String userMethod() {
return logCall("userMethod");
}
@RolesAllowed({"ejb3admin"})
public String adminMethod() {
return logCall("adminMethod");
}
@DenyAll
public String noaccessMethod() {
return logCall("noaccessMethod");
}
private String logCall(String method) {
...
return msg;
}
}
本示例定义以下访问配置:
-
commonMethod
具有不受限制的访问。 - 通过ejb3user角色可以访问
userMethod
。 -
adminMethod
可由ejb3admin角色访问。 - 任何角色均无法访问
noaccessMethod
。
EJB部署计划中的安全角色映射
EJB部署描述符中定义的安全角色和使用@DeclareRoles
批注定义的角色被映射到EJB部署计划openejb-jar.xml.
中的主体openejb-jar.xml.
显示了EJB部署计划中主体到角色的映射。
清单10:主体到角色的映射
<security>
<role-mappings>
<role role-name="ejbuser">
<principal class="o.a.g.s.r.providers.GeronimoGroupPrincipal"
name="UserGrp"/>
</role>
<role role-name="ejbadmin">
<principal class="o.a.g.s.r.providers.GeronimoGroupPrincipal"
name="AdminGrp"/>
</role>
<role role-name="ejb3user">
<principal class="o.a.g.s.r.providers.GeronimoGroupPrincipal"
name="UserGrp"/>
</role>
<role role-name="ejb3admin">
<principal class="o.a.g.s.r.providers.GeronimoGroupPrincipal"
name="AdminGrp"/>
<principal class="o.a.g.s.r.providers.GeronimoUserPrincipal"
name="dwuser3"/>
</role>
</role-mappings>
</security>
请注意, ejb-jar.xml
和@DeclareRoles
批注中的安全角色已映射到主体:
-
ejbuser
角色映射到名称为“UserGrp”
的GeronimoGroupPrincipal
。 - 我们将
ejbadmin
角色映射到名称为“AdminGrp”
的GeronimoGroupPrincipal
。 -
ejb3user
角色映射到名称为“UserGrp”
的GeronimoGroupPrincipa
。 - 该
ejb3admin
角色映射到GeronimoGroupPrincipal
与名称“AdminGrp”
和GeronimoUserPrincipal
名称为“dwuser3”
。
有关主体到角色映射的详细说明,请参阅WebSphere Application Server社区版V2.0中的配置Web应用程序安全性 。
使用EJB安全性运行示例应用程序
浏览至Deploy New portlet。
- 在“ 存档文件”下,导航到< SAMPLES_HOME >,然后选择simple-ejb-app-w-security.jar。
- 选择重新部署应用程序选项,然后单击安装 。
- 导航到Web App WARs portlet并启动dw / simple-web-app / 1.0 / war 。
- 访问
http://localhost:8080/simple-web-app
,它显示了图3中的屏幕。图3:访问安全EJB的Web应用程序主页
请注意,由于用户尚未登录应用程序,因此只能从主页调用
SimpleSessionBean
和Simple3ServiceBean
commonMethod
(
具有不受限制的访问权限)。 所有其他方法调用都导致AccessException
或EJBAccessException
因为未经授权的Principal
。 - 访问
http://localhost:8080/simple-web-app/bank/
。 使用密码admin
登录名为dwadmin
用户,
该密码显示在图4中。图4:访问安全EJB的Web应用程序银行页面
由于用户现在登录为
dwadmin
,该Subject
包含GeronimoUserPrincipal
与名称dwadmin
和GeronimoGroupPrincipal
与名称AdminGrp
。 用户根据角色映射映射到ejbadmin
和ejb3admin
角色。 因此,用户可以访问commonMethod,
具有无限制访问,并adminMethod
,这是访问(由ejbadmin
角色SimpleSessionBean
和ejb3admin
的角色Simple3ServiceBean
)。 调用时,userMethod
和noaccessMethod
导致AccessException
或EJBAccessException
。userMethod
可以通过ejbuser
角色(ejb3user
角色)Simple3ServiceBean
,noaccessMethod
不能由任何角色访问, - 打开一个新的浏览器窗口,然后访问
http://localhost:8080/simple-web-app/customer/
。 使用密码user3
登录名为dwuser3
用户,
该密码显示在图5中。图5:访问安全EJB的Web应用程序客户页面
由于用户现在以
dwuser3
登录,因此Subject
包含名称为dwuser3
GeronimoUserPrincipal
。和
GeronimoGroupPrincipal
,名称为UserGrp
。 用户根据角色映射映射到ejbuser
,ejb3user
和ejb3admi
n角色。 在SimpleSessionBean
,用户可以访问commonMethod,
具有不受限制的访问权限)和可以通过ejbuse
r角色访问的userMethod
。 在Simple3ServiceBean中,用户可以访问commonMethod,
具有无限制访问的userMethod
即由可访问ejb3user
作用和adminMetho
d是通过访问ejb3admin
作用(见在EJB2.1部署描述符安全配置 )。 所有其他方法在调用时都导致AccessException
或EJBAccessException
。
运行方式和默认主题
除了为bean的方法配置方法权限之外,还可以为bean配置Run-as
身份,以指定bean调用其他bean的安全身份。 当bean的方法需要调用其他安全标识与调用它的安全标识不同的其他bean时,例如,消息驱动的bean方法(不带任何安全标识调用)调用安全的会话bean时,此配置很有用。方法。 您可以配置安全凭据,这些凭据构成了部署计划中运行角色安全性的主题。
在2.0之前的Community Edition版本中,运行方式和默认主题的安全性配置是使用使用default-principal
标签和default-principal
designated-run-as
属性指定的主体和凭证构造的。 从Community Edition 2.0开始,所有安全性都源于登录到安全领域所产生的主题。 要使用这些主题,您需要提供每个此类主题的登录信息。 此登录信息在凭据存储中捕获。
凭证存储
Community Edition提供了凭据存储的实现,即SimpleCredentialStoreImpl
,它使您可以在部署计划中使用XML配置凭据存储。 清单11显示了我们在本文的示例应用程序中使用的凭证存储。
清单11:凭证存储gbean
<gbean name="SampleCredentialStore"
class="o.a.g.s.credentialstore.SimpleCredentialStoreImpl" ...>
<xml-attribute name="credentialStore">
<credential-store
xmlns="http://geronimo.apache.org/xml/ns/credentialstore-1.0">
<realm name="SampleSecurityRealm">
<subject>
<id>dwuser1-subject</id>
<credential>
<type>o.a.g.s.credentialstore.NameCallbackHandler</type>
<value>dwuser1</value>
</credential>
<credential>
<type>o.a.g.s.credentialstore.PasswordCallbackHandler</type>
<value>user1</value>
</credential>
</subject>
<subject>
<id>dwuser2-subject</id>
...
</subject>
<subject>
<id>dwuser3-subject</id>
...
</subject>
<subject>
<id>dwadmin-subject</id>
...
</subject>
</realm>
<realm name="AnotherRealm">
<subject>
...
</subject>
...
</realm>
</credential-store>
</xml-attribute>
</gbean>
在这里, name
的属性realm
元素指定的名称security-realm
,你用它来创建subjec
吨。 该id
下元素subject
元素指定的ID subject
,可与结合使用security-realm
的名称配置运行的主体和缺省主体为我们后来显示的时候。
您可以在subject
下使用credential
元素来配置security-realm
的登录信息。 在清单11中,我们获得使用用户名dwuser1
和密码user1
登录到SampleSecurityRealm
dwuser1-subject
。 当前,Community Edition提供了用于名称和密码的回调处理程序,足以使用需要名称和密码进行身份验证的安全领域。 要对凭据存储使用其他安全领域,例如使用数字证书的领域,则需要实现所需的回调处理程序。 此外,凭据存储可以是每个应用程序,也可以有一个凭据存储供所有应用程序使用。
配置应用程序以使用凭据存储
您可以在应用程序的部署计划中的安全配置中指定应用程序要使用的凭据存储。 清单12显示了本文中使用的示例应用程序之一的安全性配置。
清单12:显示credential-store-ref的安全配置
<security>
<credential-store-ref>
<name xmlns="http://geronimo.apache.org/xml/ns/deployment-1.2">
SampleCredentialStore</name>
</credential-store-ref>
...
</security>
在此示例中, credential-store-ref
下的name
元素指定应用程序要使用的凭据存储。 请注意,此值与清单11中所示的凭证存储gbean的name属性匹配。
配置运行方式和默认主题
您可以在应用程序的部署计划的安全性配置中为应用程序指定运行方式和默认主题。 如果没有为任何角色配置运行主题,则将使用配置的默认主题。 清单13显示了本文中使用的示例应用程序之一的运行方式和默认主题配置。
清单13:显示运行方式和默认主题的安全性配置
<security>
...
<default-subject>
<realm>SampleSecurityRealm</realm>
<id>dwuser1-subject</id>
</default-subject>
<role-mappings>
<role role-name="ejb3user">
<run-as-subject>
<realm>SampleSecurityRealm</realm>
<id>dwuser3-subject </id>
</run-as-subject>
<principal class="o.a.g.s.r.providers.GeronimoGroupPrincipal" name="UserGrp"/>
</role>
<role role-name="another">
...
</role>
...
</role-mappings>
</security>
default-subject
security
元素下的元素可配置应用程序使用的默认主题。 default-subject
下的realm
元素指定安全领域,而id
元素指定在凭证存储中配置的主题的ID。 请注意,在default-subject
下为该realm
指定的值与清单11中的realm
元素的name
属性匹配。另外,请注意,在default-subject
下为该id
指定的值与清单11中的主题id
之一匹配。
在run-as-subject
的要素role
下元素role-mappings
配置运行为主体的那个角色。 清单13显示了为ejb3user
角色配置的运行主题。 注意,在run-as-subject
下为realm
指定的值与清单11中的realm
元素的name
属性匹配。另外,请注意,在run-as-subjec
t下为id
指定的值与清单11中的主题id
之一匹配。
具有运行方式的示例EJB应用程序
我们又添加了两个会话bean( Simple3ServiceBean2
和Simple3SeviceBean3
),它们依次调用Simple3ServiceBean
的相应方法。 我们将Simple3ServiceBean2
配置为以ejb3user
角色运行。 Simple3ServiceBean3
未配置运行角色。 清单14显示了Simple3ServiceBean2
bean类。
清单14:Simple3ServiceBean2类
@Stateless
@DeclareRoles(value = {"ejb3user", "ejb3admin"})
@RunAs("ejb3user")
public class Simple3ServiceBean2 implements Simple3Service2 {
@EJB
private Simple3Service simple; // Simple3Service injected here
@PermitAll
public String commonMethod() {
Object temp;
try {
temp = simple.commonMethod();
} catch(Throwable t) {
temp = t;
}
return logCall("commonMethod") + "::" + temp;
}
@RolesAllowed({"ejb3user"})
public String userMethod() {
...
}
@RolesAllowed({"ejb3admin"})
public String adminMethod() {
...
}
@DenyAll
public String noaccessMethod() {
...
}
private String logCall(String method) {
...
}
}
在这个例子中,我们使用了@RunAs
注释与ejb3user
角色配置运行作为角色Simple3ServiceBean2
。 使用此配置,在Simple3Service
上的方法调用使用部署计划中指定的run-as-subject。 请注意, ejb3user
角色的按主题运行被指定为dwuser3-subject
(请参见清单13)。
使用运行时EJB安全性运行示例应用程序
- 浏览至Deploy New portlet。
- 部署示例中提供的simple-ejb-app-w-runas.jar 。 在单击“ 安装”之前,请确保选择“ 重新部署”应用程序选项。
- 导航到Web App WARs portlet并启动dw / simple-web-app / 1.0 / war 。
- 访问
http://localhost:8080/simple-web-app
。 向下滚动至RunAs部分,该部分显示图6中的屏幕。图6:Web应用程序主页以运行方式访问EJB
请注意,在RunAs部分下,以未经身份验证的用户身份调用
Simple3ServiceBean2
中的commonMethod
,但是按照run-as-subject的配置,依次将Simple3ServiceBean
中的dwuser3
作为commonMethod
进行调用。 由于Simple3ServiceBean3
未配置运行角色,因此Simple3ServiceBean
的commonMethod
作为未经身份验证的用户来调用。 - 访问
http://localhost:8080/simple-web-app/customer/
。 使用密码user1
以名称dwuser1
登录。 向下滚动至RunAs部分,该部分显示图7中的屏幕。图7:Web应用程序客户页面以运行方式访问EJB
注意,在RunAs部分下, Simple3ServiceBean2
中的commonMethod
和userMethod
作为dwuser
1
调用,
当前用户已登录到Web应用程序。 但是,按照run-as-subject的配置,依次将Simple3ServiceBean
中的commonMethod
和userMethod
作为dwuser3
调用。 由于未为Simple3ServiceBean3
配置运行身份角色,因此Simple3ServiceBean
中的commonMethod
和userMethod
将作为dwuser1
调用。
配置实体bean安全
您可以使用部署描述符和安全批注来配置实体Bean安全性,方法与会话Bean安全性相同。 清单15显示了带有实体bean的示例EJB应用程序中的组装描述符。
清单15:汇编描述符
<assembly-descriptor>
<security-role>
<description>Bank Manager</description>
<role-name>manager</role-name>
</security-role>
<method-permission>
<role-name>manager</role-name>
<method>
<ejb-name>MyBank</ejb-name>
<method-name>create</method-name>
</method>
</method-permission>
</assembly-descriptor>
在此示例中,我们将MyBank
实体bean的Home
接口上的create
方法配置为只能由manager
角色访问。
运行实体bean示例应用程序
样本中提供的MyBankEJB
样本应用程序包含一个名为MyBank
EJB2.1实体bean。 我们将bean的LocalHome
和Home
接口中的create
方法配置为只能由manager
访问 角色。
请按照以下步骤运行应用程序:
- 浏览至Deploy New portlet。
- 在“ 存档”字段中,浏览至
< SAMPLES_HOME >
并选择bank-db-pool.rar。 - 单击“ 安装”以部署
MyBankEJB
应用程序使用的数据库池。 - 在“ 存档”字段中,浏览到
< SAMPLES_HOME >
并选择MyBankEJB.jar。 - 单击安装以部署
MyBankEJB
应用程序。 - 在“ 存档”字段中,浏览到<
SAMPLES_HOME
>并选择MyBankWeb.war。 - 单击“ 安装”以部署
MyBankWeb
应用程序。 - 访问
http://localhost:8080/MyBankWeb.
请注意,显示的页面显示在“ 创建帐户” 部分中发生了异常,因为用户尚未登录。
- 现在访问
http://localhost:8080/MyBankWeb/manager
请注意,现在显示的页面显示帐户创建成功。 它之所以成功,是因为该页面使用运行角色配置为使用用户ID dwadmin
访问MyBank
bean,该ID映射到MyBankEJB
部署计划中配置的manager
角色。
配置消息驱动的Bean安全性
与会话和实体Bean不同,消息驱动的Bean不会被其他Bean或客户端应用程序调用。 当消息到达侦听器正在监视的输入目标时,它们将由JMS侦听器调用。 消息驱动的Bean可以调用其他会话和实体Bean。 要从消息驱动的Bean调用安全EJB,需要为消息驱动的Bean配置运行身份。 对于EJB2.1消息驱动的bean,可以使用部署描述符中的security-identity
元素配置运行方式角色。 对于EJB3消息驱动的bean,您可以使用@RunAs
注释配置运行角色。
运行消息驱动的Bean示例应用程序
为了演示EJB3消息驱动bean的运行时安全性,我们在jms-mdb-sample-ear-2.1.0.1.ear)
提供了一个应用程序( jms-mdb-sample-ear-2.1.0.1.ear)
。 该应用程序由一个称为OrderRecvMDB
消息驱动的bean和一个名为OrderRecvMDB
的无状态会话bean Simple30ServiceBean
。 我们将会话bean的userMethod
配置为可以由ejb3user
角色访问,并且将OrderRecvMDB
bean配置为具有运行身份ejb3user
。 在部署计划中,安全配置为ejb3user
角色指定一个按主题运行dwuser1-subject
。 清单16显示了OrderRecvMDB
bean类:
清单16:OrderRecvMDB bean类
import javax.annotation.security.RunAs;
...
//
// MessageDrivenBean that listens to items on the
// 'OrderQueue' queue and processes them accordingly.
//
@MessageDriven(activationConfig = {
@ActivationConfigProperty(propertyName="destinationType",
propertyValue="javax.jms.Queue"),
@ActivationConfigProperty(propertyName="destination",
propertyValue="OrderQueue")
})
@RunAs("ejb3user")
public class OrderRecvMDB implements MessageListener {
@EJB
private Simple30Service simple; // Session bean is injected
/*
* Process a message.
*
* @param message The message to process.
*/
public void onMessage(Message message) {
TextMessage textMessage = (TextMessage) message;
try {
System.out.println("Order Received \n"+ textMessage.getText());
simple.userMethod();
} catch ( JMSException e ) {
e.printStackTrace();
}
}
}
请按照以下步骤运行应用程序:
- 浏览至Deploy New portlet。
- 在“ 存档”字段中,浏览到<
SAMPLES_HOME
>并选择jms-mdb-sample-ear-2.1.0.1.ear 。 - 单击安装以部署示例应用程序。
- 访问
http://localhost:8080/order
。 - 输入字段值,然后单击订购 。
请注意,服务器控制台窗口中显示的顺序与安全标识的细节一起接收dwuser1
与该userMethod
在Simple30ServiceBean
被调用。
结论
我们创建了EJB2.1和EJB3会话Bean,一个EJB2.1实体Bean,并使用部署描述符和安全注释为Bean方法配置了访问权限。 我们还为会话和消息驱动的bean配置了运行方式角色,并创建了必要的工件(如凭证存储)来部署使用此安全配置的EJB应用程序。 我们还使用示例Web应用程序调用EJB演示了EJB安全性。
致谢
感谢Phani Madgula审阅了此材料。
翻译自: https://www.ibm.com/developerworks/websphere/library/techarticles/0811_vamsi/0811_vamsi.html