Java secure coding guide: mutability variability

brief introduction

Mutable (variable) and immutable (immutable) objects are often used in the process of Java programming.

Variable type object means that after an object is created, its internal data may be modified. So its security is not guaranteed.

The immutable type object means that once an object is created, its internal data cannot be modified. We can fully trust this object.

Although the mutable object is not secure enough, because it can be modified, it will effectively reduce the copy of the object.

The immutable object cannot be changed, so any attempt to modify the object will result in a copy of the object and generate a new object.

The most commonly used string is an immutable object.

So what is the best practice of variability in Java's secure coding? Let's have a look.

Mutable and immutable objects

After knowing the difference between a variable object and an immutable object, how can we judge whether the object is a variable object or an immutable object?

First, the simplest point is that immutable objects cannot be modified after they are created, so there are basically no setXXX methods in immutable objects, while variable objects provide setXXX methods that can modify the state of internal variables.

Look at an example Java util. Date is a mutable object, while Java time. Localtime is an immutable object.

What's the difference between their method definitions?

The first is date. We can see that many setXXX methods are defined in it.

In Localtime, we can hardly see the setXXX method.

At the same time, the fields of immutable objects are basically final to prevent secondary modification.

Second, immutable objects are generally non inheritable. In Java, they are limited by the final keyword:

public class Date
public final class LocalTime

Third, immutable objects generally hide constructors, but use methods similar to factory mode to create objects, which provides more flexibility for instance creation.

Create a copy of the mutable object

So what if we want to use mutable objects without being modified by others?

The simple way is to copy an object to be used:

public class CopyOutput {
            private final java.util.Date date;
            ...
            public java.util.Date getDate() {
                return (java.util.Date)date.clone();
            }
        }

Here we should also pay attention to the problem of deep copy and shallow copy.

Create a copy method for the mutable class

Since you want to create a copy of the mutable object, the corresponding mutable class also needs to provide a copy method to assist in copying.

Here we need to consider the problem of deep copy and shallow copy.

Don't trust equals

Do we know how to find a key in HashMap? First find the hash value of the key, and then judge the key Whether the equals method is equal, consider the following:

private final Map<Window,Extra> extras = new HashMap<>();

        public void op(Window window) {
            Extra extra = extras.get(window);
        }

The op method receives a window object and takes it as a key to get the corresponding value from the HashMap.

If, at this time, a class a inherits window, and the hash value and equals are the same as those of another window object B, then you can use the key a to obtain the data stored by the key B!

How to solve this problem?

There is a special HashMap in Java: identityhashmap. The key and value of this map are compared with = = instead of equals, so the above problems can be effectively avoided.

private final Map<Window,Extra> extras = new IdentityHashMap<>();

        public void op(Window window) {
            Extra extra = extras.get(window);
        }

If no such map is available, an immutable object can be used as a key or a private variable of window, so that a malicious attacker cannot obtain this variable.

public class Window {
            /* pp */ 
            class PrivateKey {
                Window getWindow() {
                    return Window.this;
                }
            }
            final PrivateKey privateKey = new PrivateKey();

            private final Map<Window.PrivateKey,Extra> extras =
                 new WeakHashMap<>();
            ...
        }

        public class WindowOps {
            public void op(Window window) {
                // Window.equals may be overridden,// but safe as we don't use it.
                Extra extra = extras.get(window.privateKey);
                ...
            }
        }

Do not directly expose modifiable properties

If a property in a variable class really needs to be exposed for external use, it must be defined as private and wrapped with the wrapper method.

If it is directly exposed, there is basically no permission control. Any program can modify the properties as long as it can get your object. Considering the following application methods, we add a parameter verification and permission control to the method of modifying state.

public final class WrappedState {
            // private immutable object
            private String state;

            // wrapper method
            public String getState() {
                return state;
            }

            // wrapper method
            public void setState(final String newState) {
                this.state = requireValidation(newState);
            }

            private static String requireValidation(final String state) {
                if (...) {
                    throw new IllegalArgumentException("...");
                }
                return state;
            }
        }

Public static fields should be set to final

Similarly, if you are a class variable and of course do not want this variable to be modified by anyone, you need to set it to final.

public class Files {
            public static final String separator = "/";
            public static final String pathSeparator = ":";
        }

Public static final field should be immutable

If the class variable is public static final, the variable must be immutable.

Some people will ask, are all defined as final, is it immutable?

In fact, it is not. For example, we define a final list. Although the list cannot be changed, the values in the list can be changed. We need to change the variable variable variable to the immutable variable, as shown below:

import static java.util.Arrays.asList;
        import static java.util.Collections.unmodifiableList;
        ...
        public static final List<String> names = unmodifiableList(asList(
            "Fred","Jim","Sheila"
        ));

If you use the of () or ofentries () methods introduced in jdk9, you can directly create immutable Collections:

public static final List
<String> names =
 List.of("Fred","Sheila");
The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>