Architecture & Design Java Language Security: Controlling Access to a Class

Java Language Security: Controlling Access to a Class

This series, The Object-Oriented Thought Process, is intended for someone just learning an object-oriented language and who wants to understand the basic concepts before jumping into the code, or someone who wants to understand the infrastructure behind an object-oriented language he or she is already using. These concepts are part of the foundation that any programmer will need to make the paradigm shift from procedural programming to object-oriented programming.

Figure 3: Compiler Controlling Access to a Protected Attribute

You have encountered the two extremes of security in terms of access members of a class. Using the public access modifier basically leaves the class member totally unprotected, whereas the private access modifier explicitly prohibits any other class from accessing the item directly—even a subclass.

There are other access modifiers besides public and private. In the rest of the article, you will explore the subtleties of using the various access modifiers and when to use them in your design.

Access level modifiers

Before you specifically look at other individual access modifiers, it is helpful to look at a table that is provided on the Sun web site. This table indicates the access levels permitted by each of the modifiers.

Access Levels
Modifier Class Package Subclass World
public Y Y Y Y
protected Y Y Y N
no modifier Y Y N N
private Y N N N

Source: http://java.sun.com/docs/books/tutorial/java/javaOO/accesscontrol.html

Table 1: Class Access Levels

As you determined in your code examples, the table confirms that the public access modifier allows unlimited access to the class, the package, and any subclass as well any other class (in this table designation, the world). Likewise, the table indicates that the private modifier prohibits access to any outside classes.

Protected level access modifiers

To solve your problem with your inheritance example, you will have to use the protected access modifier to gain access to the accountBalance attribute.

class CheckingAccount {

   protected String accountNumber;
   protected double accountBalance = 1000000.00;

   public double getAccountBalance() {

      return (accountBalance);

   }

}

class PlatinumChecking extends CheckingAccount {

}

class AccountList {

   public static void main(String args[]) {

      PlatinumChecking myList = new PlatinumChecking();

      System.out.println("Balance = " + myList.getAccountBalance());

   }
}

Listing 7: Protected Access using Inheritance

It is important to note that to gain access to the protected attribute from the AccountList application, you had to provide the getAccountBalance() method in the CheckingAccount class. As can be seen in Table 1, the protected access modifier not only allows access to subclasses, but also to any class in the same package.

// CheckingAccount

package Account;

public class CheckingAccount {

   protected String accountNumber;
   protected double accountBalance = 1000000.00;

   public double getAccountBalance() {

      return (accountBalance);

   }

}

// PlatinumChecking
package Account;

public class PlatinumChecking extends CheckingAccount {

}

// AccountList
package Account;

public class AccountList {

   public static void main(String args[]) {

      PlatinumChecking myList = new PlatinumChecking();

      System.out.println("Balance = " + myList.accountBalance);

   }
}

Listing 8: Protected Access using Packages

The interesting issue with the code in Listing 8 is that the AccountList application has been placed in the Account package:

// AccountList
package Account;

Also, note that you are directly accessing the accountBalance attribute—which should not be allowed.

      System.out.println("Balance = " + myList.accountBalance);

When this code is compiled, it compiles cleanly, confirming that the protected access modifier allows all classes within the package full access.

Figure 4: Protected Access using Packages

Note: You instantiated a PlatinumChecking object in the AccountList application., and not a CheckingAccount object. This is important because using the getAccountBalance() method is what actually requires the protected access modifier.

Security and the default level access modifier

While the protected access modifier allows you to access attributes and methods within a package and a subclass, the default access modifier allows access to classes in the package. However, it restricts access to subclasses.

Subclass
Access Levels
Modifier Class Package World
no modifier (default) Y Y N N

Listing 9 and Figure 6 illustrates this behavior.

Note: Because classes in the same directory are considered to be in the same package, the PlatinumChecking class was moved out of the Account directory. You can see this in the command line in Figure 5.

// CheckingAccount
package Account;

public class CheckingAccount {

   String accountNumber;                  // no access modifier (default)
   double accountBalance = 1000000.00;    // no access modifier (default)

   public double getAccountBalance() {

      return (accountBalance);

   }

}

// PlatinumChecking
import Account.*;

public class PlatinumChecking extends CheckingAccount {

   public void PlatinumChecking() {

      accountBalance=0;    // subclass can't access
   }

}

// AccountList
import Account.*;

public class AccountList {

   public static void main(String args[]) {

      PlatinumChecking myList = new PlatinumChecking();

   }
}

Listing 9: Default Access using Inheritance & Packages

Figure 5: Default Access using Packages

Why would this be a security issue? By using the default access modifier, a subclass is prevented from altering an attribute in a parent class without going through the security constraints in that parent class. For example, rather than directly changing an attribute as follows:

      accountBalance=0;    // subclass can't access

The subclass would be required to call a method in the superclass to access/change the attribute.

Conclusion

Once of the great advantages that Java brought to the table when it was first introduced was that several levels of security were built directly into the language itself. In this article, you explore just one of those security concerns.

The concept of secure access levels is even more interesting when you consider that this type of security is enforced at the compilation level. In other words, if properly designed, security anomalies are caught prior to the creation of the bytecodes, so the application can never be executed. This not only makes the code more secure, it also assists the software development process itself.

There are several other compiler enforced security concepts to explore in future articles, as well as security issues enforced by the Virtual Machine.

References

About the Author

Matt Weisfeld is a faculty member at Cuyahoga Community College (Tri-C) in Cleveland, Ohio. Matt is a member of the Information Technology department, teaching programming languages such as C++, Java, C#, and .NET as well as various Web technologies. Prior to joining Tri-C, Matt spent 20 years in the information technology industry gaining experience in software development, project management, business development, corporate training, and part-time teaching. Matt holds an MS in computer science and an MBA in project management. Besides The Object-Oriented Thought Process, which is now in its second edition, Matt has published two other computer books, and more than a dozen articles in magazines and journals such as Dr. Dobb’s Journal, The C/C++ Users Journal, Software Development Magazine, Java Report, and the international journal Project Management. Matt has presented at conferences throughout the United States and Canada.

Latest Posts

Related Stories