32
1 Security Security Most Java EE applications need to provide identity to users who access them and security for that access. Applications may want to prevent hostile users from logging into their systems. They might also want to restrict the actions of the individuals using their systems. The Java EE and EJB specifications provide a core set of security services that application developers can integrate declaratively and programmatically. These include: Authentication Authorization Confidentiality and integrity protection

1 Security Most Java EE applications need to provide identity to users who access them and security for that access. Applications may want to prevent hostile

Embed Size (px)

Citation preview

Page 1: 1 Security Most Java EE applications need to provide identity to users who access them and security for that access. Applications may want to prevent hostile

11

SecuritySecurity

Most Java EE applications need to provide identity to users who access them and security for that access. Applications may want to prevent hostile users from logging into their systems.

They might also want to restrict the actions of the individuals using their systems.

The Java EE and EJB specifications provide a core set of security services that application developers can integrate declaratively and programmatically. These include:

Authentication Authorization Confidentiality and integrity protection

Page 2: 1 Security Most Java EE applications need to provide identity to users who access them and security for that access. Applications may want to prevent hostile

22

SecuritySecurity

Although a small programmatic API is available for interacting with Java EE security services, users rarely have to write any code to secure their applications because setting up security is usually a static declarative process.

Only session beans can be secured in EJB land. Java Persistence does not yet have a mechanism to secure access, but it is possible - depending on the RDBMS system you are using - to assign privileges at the database level.

This lesson focuses on how to set up authentication and authorization for your session beans.

Page 3: 1 Security Most Java EE applications need to provide identity to users who access them and security for that access. Applications may want to prevent hostile

33

Authentication and IdentityAuthentication and Identity In a secure EJB application, authentication involves verifying

that a user is who she says she is. When a remote client logs on to the EJB system, it is

associated with a security identity for the duration of that session.

Once a remote client application has been associated with a security identity, it is ready to use beans to accomplish some task.

When a client invokes a method on a bean, the EJB server implicitly passes the client's identity with the method invocation.

When the EJB object receives the method invocation, it checks the identity to ensure that the client is valid and is allowed to invoke that method.

Page 4: 1 Security Most Java EE applications need to provide identity to users who access them and security for that access. Applications may want to prevent hostile

44

Authentication and IdentityAuthentication and Identity

Unfortunately the EJB specification does not specify how authentication happens. It also does not define how the application server stores and retrieves authentication information.

The vendor must decide how to package and provide these services on the client and server.

When invoking on a remote EJB, many application servers accomplish authentication by using the JNDI API.

For example, a client using JNDI can provide authenticating information using the JNDI API to access a server or resource in the server.

This information is frequently passed when the client attempts to initiate a JNDI connection on the EJB server.

Page 5: 1 Security Most Java EE applications need to provide identity to users who access them and security for that access. Applications may want to prevent hostile

55

Authentication and IdentityAuthentication and Identity

The following code shows how a client's password and username can be added to the connection properties for obtaining a JNDI connection to the EJB server:

properties.put(Context.SECURITY_PRINCIPAL, userName);

properties.put(Context.SECURITY_CREDENTIALS, userPassword);

InitialContext ctx = new InitialContext(properties);

Object ref = jndiContext.lookup("TravelAgent");

TravelAgentRemote remote = (TravelAgentRemote)

PortableRemoteObject.narrow(ref, TravelAgentRemote.class);

Page 6: 1 Security Most Java EE applications need to provide identity to users who access them and security for that access. Applications may want to prevent hostile

66

Authentication and IdentityAuthentication and Identity

In this example, the user is authenticated with the connection to the JNDI InitialContext.

The username and password are associated with the client thread and propagated to the server internally when calls are made to remote EJBs.

Many application servers provide a mechanism other than JNDI with which to authenticate.

For instance, the JBoss application server uses the JAAS specification, which provides a rich API for performing authentication.

Page 7: 1 Security Most Java EE applications need to provide identity to users who access them and security for that access. Applications may want to prevent hostile

77

AuthorizationAuthorization

Once a user is authenticated by a vendor-specific mechanism, he must be checked to see if he is allowed to invoke a particular EJB method.

Authorization is performed in Java EE and EJB by associating one or more roles with a given user and then assigning method permissions based on that role.

While an example of a user might be "Scott" or "Gavin," roles are used to identify a group of users—for instance, "administrator," "manager," or "employee."

In EJB, you assign access control on a per-method basis. You do not assign these permissions on a per-user basis, but

rather, on a per-role basis.

Page 8: 1 Security Most Java EE applications need to provide identity to users who access them and security for that access. Applications may want to prevent hostile

88

AuthorizationAuthorization

Unlike authentication, authorization is something that the EJB specification clearly defines.

You begin by declaring the roles that are accessed programmatically in your code base. Then you assign permissions for each method in your class.

This is done declaratively through Java annotations or through the ejb-jar.xml deployment descriptor.

To illustrate, let's secure access to the ProcessPayment EJB defined in Lesson 11.

Page 9: 1 Security Most Java EE applications need to provide identity to users who access them and security for that access. Applications may want to prevent hostile

99

Assigning Method PermissionsAssigning Method Permissions

To assign method permissions to an EJB's methods, use the @javax.annotation.security.RolesAllowed annotation:

package javax.annotation.security;

@Target({TYPE, METHOD}) @Retention(RUNTIME)

public @interface RolesAllowed {

String[] value( );

}

The @javax.annotation.security.PermitAll annotation specifies that any authenticated user is permitted to invoke the method.

Page 10: 1 Security Most Java EE applications need to provide identity to users who access them and security for that access. Applications may want to prevent hostile

1010

Assigning Method PermissionsAssigning Method Permissions As with @RolesAllowed, you can use this annotation on the

bean class to define the default for the entire bean class, or you can use it on a per-method basis.

@PermitAll is also the default value if no default or explicit security metadata is provided for a method.

This means that if you do not use any security annotations on your bean class, every user is granted unlimited access.

Let's apply these annotations to ProcessPaymentBean using the permissions we discussed earlier:

package com.titan.processpayment;

import com.titan.domain.*;

import javax.ejb.*;

import javax.annotation.Resource;

import javax.annotation.security.*;

Page 11: 1 Security Most Java EE applications need to provide identity to users who access them and security for that access. Applications may want to prevent hostile

1111

Assigning Method PermissionsAssigning Method Permissions@Stateless

@RolesAllowed("AUTHORIZED_MERCHANT")

public class ProcessPaymentBean implements ProcessPaymentRemote,

ProcessPaymentLocal

{

...

@PermitAll

public boolean byCash(Customer customer, double amount)

throws PaymentException

{

...

}

@RolesAllowed("CHECK_FRAUD_ENABLED")

public boolean byCheck(Customer customer, CheckDO check, double amount)

throws PaymentException

{

...

}

Page 12: 1 Security Most Java EE applications need to provide identity to users who access them and security for that access. Applications may want to prevent hostile

1212

Assigning Method PermissionsAssigning Method Permissions

public boolean byCredit(Customer customer, CreditCardDO card,

double amount) throws PaymentException

{

...

}

private boolean process(int customerID, double amount, String type, String checkBarCode, int checkNumber, String creditNumber,

java.sql.Date creditExpDate) throws PaymentException

{

...

}

}

Let's apply this security metadata with XML instead:

Page 13: 1 Security Most Java EE applications need to provide identity to users who access them and security for that access. Applications may want to prevent hostile

1313

Assigning Method PermissionsAssigning Method Permissions<ejb-jar version="3.0">

<assembly-descriptor>

<security-role>

<description>This role represents an authorized merchant</description>

<role-name>AUTHORIZED_MERCHANT</role-name>

</security-role>

<security-role>

<description>

This role represents a merchant that has check fraud enabled

</descripton>

<role-name>CHECK_FRAUD_ENABLED</role-name>

</security-role>

<method-permission>

<role-name>AUTHORIZED_MERCHANT</role-name>

<method>

<ejb-name>ProcessPaymentBean</ejb-name>

<method-name>byCredit</method-name>

</method>

</method-permission>

Page 14: 1 Security Most Java EE applications need to provide identity to users who access them and security for that access. Applications may want to prevent hostile

1414

Assigning Method PermissionsAssigning Method Permissions <method-permission>

<role-name>CHECK_FRAUD_ENABLED</role-name>

<method>

<ejb-name>ProcessPaymentBean</ejb-name>

<method-name>byCheck</method-name>

</method>

</method-permission>

<method-permission>

<unchecked/>

<method>

<ejb-name>ProcessPaymentBean</ejb-name>

<method-name>byCheck</method-name>

</method>

</method-permission>

</assembly-descriptor>

</ejb-jar>

Page 15: 1 Security Most Java EE applications need to provide identity to users who access them and security for that access. Applications may want to prevent hostile

1515

Wildcard declarationsWildcard declarations The method name in a <method> element can be a simple

wildcard (*). A wildcard applies to all methods of the bean's home and

remote interfaces. For example:

<method>

<ejb-name>ProcessPaymentBean</ejb-name>

<method-name>*</method-name>

</method>

Although it's tempting to combine the wildcard with other characters, don't do this.

The value get*, for example, is illegal. The asterisk character can only be used by itself.

Page 16: 1 Security Most Java EE applications need to provide identity to users who access them and security for that access. Applications may want to prevent hostile

1616

Named method declarationsNamed method declarations Named declarations apply to all methods defined in the

bean's remote and local interfaces that have the specified name.

For example:

<method>

<ejb-name>ProcessPaymentBean</ejb-name>

<method-name>byCheck</method-name>

</method>

This declaration applies to all methods with the given name in any business interface.

It does not distinguish between overloaded methods.

Page 17: 1 Security Most Java EE applications need to provide identity to users who access them and security for that access. Applications may want to prevent hostile

1717

Specific method declarationsSpecific method declarations Specific method declarations use the <method-params>

element to pinpoint a method by listing its parameters, which allows you to differentiate between overloaded methods.

The <method-params> element contains zero or more <method-param> elements that correspond, in order, to each parameter type (including multidimensional arrays) declared in the method.

For example, let's look again at our ProcessPayment EJB, to which we have added some overloaded byCheck( ) methods.

Here are three <method> elements, each of which unambiguously specifies one of the methods by listing its parameters:

Page 18: 1 Security Most Java EE applications need to provide identity to users who access them and security for that access. Applications may want to prevent hostile

1818

Specific method declarationsSpecific method declarations<method>

<ejb-name>ProcessPaymentBean</ejb-name>

<method-name>byCheck</method-name>

<method-params>

<method-param>com.titan.domain.Customer</method-param>

<method-param>com.titan.processpayment.CheckDO</method-param>

<method-param>double</method-param>

</method-params>

</method>

<method>

<ejb-name>ProcessPaymentBean</ejb-name>

<method-name>byCheck</method-name>

<method-params></method-params>

</method>

<method>

<ejb-name>ProcessPaymentBean</ejb-name>

<method-name>byCheck</method-name>

<method-params>double[]</method-params>

</method>

Page 19: 1 Security Most Java EE applications need to provide identity to users who access them and security for that access. Applications may want to prevent hostile

1919

Remote/home/local differentiationRemote/home/local differentiation

There's one problem left. The same method name can be used in the remote interface and the local interface.

To resolve this ambiguity, add the <method-intf> element to a method declaration as a modifier.

Five values are allowed for a <method-intf> element: Remote, Home, LocalHome, Local, and ServiceEndpoint.

All of these styles of method declarations can be used in any combination and within any element that uses the <method> element.

The <method-permission> elements are combined to form a union of role-to-method permissions.

Page 20: 1 Security Most Java EE applications need to provide identity to users who access them and security for that access. Applications may want to prevent hostile

2020

Remote/home/local differentiationRemote/home/local differentiation

For example, in the following code, the first <method-permission> element declares that only administrators have access to the remote methods of the ProcessPayment EJB:

<method-permission>

<role-name>administrator</role-name>

<method>

<ejb-name>ProcessPaymentBean</ejb-name>

<method-name>*</method-name>

<method-intf>Remote</method_intf>

</method>

</method-permission>

Page 21: 1 Security Most Java EE applications need to provide identity to users who access them and security for that access. Applications may want to prevent hostile

2121

Excluded MethodsExcluded Methods EJB security metadata has a rarely used feature that allows

you to forbid access to one or more methods. Excluded methods are identified with the @javax.annotation.security.DenyAll annotation or with the <exclude-list> element.

Denying access to a particular method with an annotation isn't a very useful proposition.

Why would you write a bean class method, add it to the business interface, and then annotate it so that it couldn't be used?

Using this feature in XML, though, does have some uses. What if the ProcessPayment EJB was part of a third-party

vendor library?

Page 22: 1 Security Most Java EE applications need to provide identity to users who access them and security for that access. Applications may want to prevent hostile

2222

Excluded MethodsExcluded Methods The <exclude-list> element could be used to turn off various

features of the API per deployment. Let's look at an example:

<ejb-jar> <assembly-descriptor> <exclude-list> <method> <ejb-name>ProcessPaymentBean</ejb-name> <method-name>byCash</method-name> </method> </exclude-list> </assembly-descriptor></ejb-jar>

This example disallows all access to the ProcessPaymentBean.byCash( ) method. The <exclude-list> element can take one or more method signatures.

Page 23: 1 Security Most Java EE applications need to provide identity to users who access them and security for that access. Applications may want to prevent hostile

2323

The RunAs Security IdentityThe RunAs Security Identity In addition to specifying the roles that have access to an

enterprise bean's methods, the deployer can also specify the runAs role for the entire enterprise bean.

While the @RolesAllowed annotation and <method-permission> elements specify which roles have access to the bean's methods, runAs specifies the role under which the method will run.

The @javax.annotation.security.RunAs annotation is used to specify this special role.

Although they are not allowed to use method permissions, message-driven beans can use the @RunsAs feature:

Page 24: 1 Security Most Java EE applications need to provide identity to users who access them and security for that access. Applications may want to prevent hostile

2424

The RunAs Security IdentityThe RunAs Security Identitypackage javax.annotation.security;

public @interface RunAs {

String value( );

}

@RunAs could be used to simplify our role mapping for the ProcessPayment EJB.

Let's look at how TravelAgentBean would use the @RunAs annotation:

package com.titan.travelagent;

import javax.ejb.*;

import javax.annotation.security.*;

Page 25: 1 Security Most Java EE applications need to provide identity to users who access them and security for that access. Applications may want to prevent hostile

2525

The RunAs Security IdentityThe RunAs Security Identity@Stateful@RunAs("AUTHORIZED_MERCHANT")public class TravelAgentBean implements TravelAgentRemote{...}

This can also be expressed in ejb-jar.xml:<ejb-jar version="3.0"> <enterprise-beans> <session> <ejb-name>TravelAgentBean</ejb-name> <security-identity> <run-as> <role-name>AUTHORIZED_MERCHANT</role-name> </run-as> </security-identity> </session> </enterprise-beans></ejb-jar>

Page 26: 1 Security Most Java EE applications need to provide identity to users who access them and security for that access. Applications may want to prevent hostile

2626

The RunAs Security IdentityThe RunAs Security Identity To specify that an enterprise bean will execute under the

caller's identity rather than a propagated run-as identity, the <security-identity> role contains a single empty element, <use-caller-identity/>.

The following declarations specify that the EmployeeService EJB should always execute under the caller's identity:<enterprise-beans> <entity> <ejb-name>EmployeeService</ejb-name> <security-identity>

<user-caller-identity/> </security-identity> </entity></enterprise-beans>

The use of <security-identity> applies to session beans. Message-driven beans have only a runAs identity; they never execute under the caller identity because there is no "caller."

Page 27: 1 Security Most Java EE applications need to provide identity to users who access them and security for that access. Applications may want to prevent hostile

2727

Programmatic SecurityProgrammatic Security Most of the security features in this chapter have focused

solely on declarative security metadata, or metadata that is statically defined before an application even runs.

EJB also has a small programmatic API for gathering information about a secured session.

Specifically, the javax.ejb.EJBContext interface has a method for determining the concrete user that is invoking on the EJB.

It also has a method that allows you to check whether the current user belongs to a certain role:package javax.ejb;

public interface EJBContext { javax.security.Principal getCallerPrincipal( ); boolean isCallerInRole (String roleName);}

Page 28: 1 Security Most Java EE applications need to provide identity to users who access them and security for that access. Applications may want to prevent hostile

2828

Programmatic SecurityProgrammatic Security The getCallerPrincipal( ) method returns a standard Java SE

javax.security.Principal security interface. A Principal object represents the individual user that is

currently invoking on the EJB. We can expand our ProcessPayment EJB to store the travel

agent that logged the payment for a customer as well. This addition allows us to audit the payment if there are any

problems with the transaction.

package com.titan.processpayment;

import javax.security.Principal;

import javax.ejb.*;

import javax.annotation.*;

Page 29: 1 Security Most Java EE applications need to provide identity to users who access them and security for that access. Applications may want to prevent hostile

2929

Programmatic SecurityProgrammatic Security@Statelesspublic class ProcessPaymentBean implements ProcessPaymentLocal {

@Resource SessionContext ctx;...

private boolean process(int customerID, double amount, String type,String checkBarCode, int checkNumber, String

creditNumber, java.sql.Date creditExpDate) throws PaymentException

{Principal caller = ctx.getCallerPrincipal( ); String travelAgent = caller.getName( ); // add travelAgent to payment record ... }}

The EJBContext.isCallerInRole( ) method allows you to determine whether the current calling user belongs to a certain role.

For instance, we might want to forbid large payment transactions above a certain dollar amount for junior travel agents.

Page 30: 1 Security Most Java EE applications need to provide identity to users who access them and security for that access. Applications may want to prevent hostile

3030

Programmatic SecurityProgrammatic Security To make the EJB container's job easier, you must declare all

programmatic role access using the @javax.annotation.security.DeclareRoles annotation:

package javax.annotation.security;

@Target(TYPE) @Retention(RUNTIME)public @interface DeclareRoles { String[] value( );}

Let's use isCallerInRole( ) with the ProcessBean EJB: package com.titan.processpayment;

import javax.security.Principal;import javax.ejb.*;import javax.annotation.*;import javax.annotation.security.*;

Page 31: 1 Security Most Java EE applications need to provide identity to users who access them and security for that access. Applications may want to prevent hostile

3131

Programmatic SecurityProgrammatic Security@Stateless

@DeclareRoles

("JUNIOR_TRAVEL_AGENT")

public class ProcessPaymentBean implements ProcessPaymentLocal {

@Resource SessionContext ctx;

@Resource double maximumJuniorTrade = 10000.0;

...

private boolean process(int customerID, double amount, String type,

String checkBarCode, int checkNumber,

String creditNumber, java.sql.Date creditExpDate) throws PaymentException

{

if (amount > maximumJuniorTrade &&

ctx.isCallerInRole("JUNIOR_TRAVEL_AGENT"))

throw new PaymentException("Travel agent is not authorized to make such

a large purchase. Manager approval is required.");

...

}

}

Page 32: 1 Security Most Java EE applications need to provide identity to users who access them and security for that access. Applications may want to prevent hostile

3232

Programmatic SecurityProgrammatic Security If you do not use the @DeclareRoles annotation, then you

must use the <security-role-ref> element within the session bean's declaration:

<ejb-jar version="3.0"> <enterprise-beans> <session> <ejb-name>ProcessPaymentBean</ejb-name> <security-role-ref> <role-name>JUNIOR_TRAVEL_AGENT</role-name> </security-role-ref> </session> </enterprise-beans></ejb-jar>

The <security-role-ref> element is defined within a <session> or <message-driven> element.

It has one subelement, <role-name>, which names the role that is being referenced.