|
|
||
Elie Levy's BlogCommunity: Java Enterprise ArchivesSecuring the integrity and authenticity of linksPosted by elevy on May 13, 2008 at 12:40 PM | Permalink | Comments (1)It has been a while since my last posting. As you can imagine, I have been really busy. Last week I was presenting at the JavaOne, and it was amazing. Thank you all for all the positive feedback on my session. I will most likely writing something about the demos I showed, and may be I will post them here with Java WebStart. That will have to wait for now... Now back to the blog that I have been thinking to write: Form hidden fields, query string arguments, and cookie values are frequently used as parameters to keep session state on the client of web based application. In this blog, I explore an option for securing those values. The key to this approach is that even if the developer is unaware of the problem, they are safe, thanks to the underlining framework. The problem is that it is extremely easy for an attacker to change the values of any of these parameters. Making the Web Application vulnerable if the developers are not careful. My first recommendation to address this problem is to avoid using those parameters in the first place. If that is not possible, then strong validation is necessary. However, there are some cases where that validation is not easy to do. How do you achieve security? In this blog, I am going to describe a solution for the parameters in the query string. It would be trivial to extrapolate it and apply it to the other cases. The idea is to use a keyed-Hash Message Authentication Code (HMAC). HMAC is just a hash value combined with a private key. In this case we are going to use it as a checksum. The idea is to get the URL with the parameters, pass it through the HMAC algorithm, and append this "checksum" to the query string. In this way when we receive a URL we can calculate the checksum again. If it matches, we know that the URL was generated from our application. If it doesn't, ALARM! someone modified the query string. A problem that we would still have, is that if someone was to be able to get to the computer of an authorized user, after looking at the browse history, the attacker can replicate the requests, and potentially violate the system security. A way to stop that from happening would be to include a timeout as part of the query string, and then obtain the HMAC. The validation phase would include validating that the timeout has not expired. There is no constraint that does not have side effects. In this case, a bookmark would only be good for the lifetime of the session (until the timeout of the query string is good). I personally don't think of this as a problem, on the contrary I see this as a benefit. The links that we would protect using this technique, are the type of links we would not want the user to bookmark in the first place. Now that we have gone through the theory, let's see some code of what would it take to implement something like this. In this case, I will extend the struts framework. Obviously, the same idea can be applied to almost any other framework as well. The first step will be to identify which Actions are going to have this security. For that we can extend the Action Mapping class to include a requireHMAC parameter:
public class SecureActionMapping extends RequestActionMapping {
protected boolean requiresHMAC;
public boolean getRequiresHMAC() {
return requiresHMAC;
}
public void setRequiresHMAC(boolean requiresHMAC) {
this.requiresHMAC = requiresHMAC;
}
}
Then in the struts-config.xml file we need to configure struts to use this as the ActionMapping class:
<action-mappings type="org.zilonis.hmaclinks.SecureActionMapping">
.... all the action mappings
<action path="/editUser" type="EditUserAction">
<set-property property="requiresHMAC" value="true"/>
</action>
</action-mappings>
In the Struts html tag library we have the custom tag html:link. To generate the links all we need to do is extend it to include the HMAC and the timeout as part of the link. To generate the HMAC:
private final static JTIME="&time=";
private final static HMAC="&jval=";
public static String appendHMACSecurity(String url) {
url+= JTIME + System.currentTimeMillis();
url+= HMAC + HMACGenerator.genHMac(url);
return url;
}
public class HMACGenerator {
private final static SecretKey key = genKey();
public static String getMac(String url) {
Mac mac = Mac.getInstance(key.getAlgorithm());
mac.init(key);
byte utf8[] = url.getBytes("UTF8");
byte digest[] = mac.doFinal(utf8);
String result = URLEncoder.encode(new Base64Encoder.encode(digest));
}
private final static SecretKey genKey() {
KeyGenerator keyGen = KeyGenerator.getInstance("HmacMD5");
return keyGen.generateKey();
}
}
I have omited purposely Exception handling for readability. An interesting trick here is that I am generating the key in a static final field. That means that the first time the application gets started, the private key is going to be generated. In this way, there is no need to have any key management procedures with the operations team. If you were on a situation that your application does not get restarted in a long time (more than 15 days) you might want to considering putting some code there to generate a new key every now and then... To verify the HMAC we just need to extend the FrontProcessor servlet to check if the action requires an HMAC. Then a similar piece of code to generate the HMAC and compare it with the one we are receiving. Notice that we are not decrypting the HMAC. The HMAC never gets decrypted. All we do is generate again our "checksum" and verify that it is the same we are receiving. Finally we just need to check the timeout. This technique might be overkill for some environments. But there are some situations where other options are not really feasible. This is easy enough to turn on/off on any use case you application might have. Zilonis JavaOne Presentation SlidesPosted by elevy on October 25, 2007 at 07:59 AM | Permalink | Comments (0)Finally the slides from the Zilonis Rules Engine JavaOne presentation are available. In the slides I presented the internals of how Zilonis uses the Java Concurrency API's to manage concurrent access to the Working Memory. The Java Concurrency API and Deadlock Prevention in a RETE Rules Engine to Implement a Pricing Service Power-N ArchitecturesPosted by elevy on September 21, 2007 at 07:28 AM | Permalink | Comments (0)Early in the dot com boom era, a lot of companies implemented the popular portals. Those portals allowed us to "integrate" multiple applications together into a single screen. I write "integrate" between quotes, because there was nothing really integrated, it was just that the set of applications were displayed in the same screen. The reason for the low level of integration was not because of lack of need, or lack of will. It was primarily because the applications at the time were written to produce data mixed with the rendering information, loosing all the semantics of the "data" that was being produced as a result of a request from the clients. With the services and technologies that are available today I see a completely different future. The ability to create a Rich Client user interface, with most of the benefits that a Thin Client offer, is an amazing technological resource. Think about it for a second. You can create a Rich Client application, that has zero maintenance cost. It is downloaded from the web, it runs on your client machine, and when there is a newer version, it downloads automatically an update (auto-update). For those of you that haven’t have the exposure to it, take a look at Java WebStart. Adding to that we have lots of "backend" services sitting on the web, that can be easily accessed (i.e. google base, etc) and integrated, and semantically integrated. These resources (technologies + services) give birth to what I am calling power-N architectures. We can write a Rich Client application that accesses M * N-Tier services on the Web, integrate the data that the services have, and provide a really powerful tool for the end user. On many cases, as an application/service provider, writing the client application is not going to be enough. Most likely you will still have to provide your own services that provide an extra touch to make your application really unique, but I claim that most of the services that you would need are out there, just waiting to be integrated. There are 2 fundamental differences with the approach I am presenting here. Distribution of Tasks The first one, is using a Rich Client interface that directly accesses the services that are distributed across the network. This is a very important difference. You are having all the advantages of a truly distributed application. Specially scalability and high availability. With the old model, all the services were tunneled through one server that acted as a proxy for you application. With JavaScript, AJAX, and all those technologies you really have no choice but do something like that. It would be extremely complicated to write an application in AJAX that goes to multiple services, and merges the data in an intelligent way. Not the case for full rich client java applications. In this scenario, having your server down, means your application is fully down. In the Power-N architecture, the clients are more independent of the backend availability. If one of the services is down, that only means that the areas of the application that depend on that service is down. But the user can continue using the rest of the services without a problem. I will not write about Scalability, I think it is obvious. Integration The second fundamental difference is Integration. With XML, and the semantic web technologies, we can write application that truly integrate different services. Here I am not talking about just presenting different unrelated information in the same screen. I am talking about real integration. Specialized Browers What will end up happening is that these Rich Client applications distributed across the web, are going to be sort of specialized browsers, that will access and integrate different web services, and provide rich and unique functionalities that are going to facilitate the life of the users. You can access the reviews of a book in amazon.com, and query wikipedia on that book, find the author and its place of birth, get the geo coordinates and map the location, then go to another service and find how much would be a flight ticket to get there, and on, and on, and on… I am not trying to present here a specific use case of a business that would work. I am just presenting an architecture that is here in front of us just waiting to be exploded into what will be the real new web. Single Sign OnPosted by elevy on August 29, 2007 at 12:56 PM | Permalink | Comments (6)In the last few weeks I was asked to help to integrate a set of built-in-house web applications with a Single Sign On (SSO) solution. After working with people from different teams, I realized that it would be a good idea to write a brief description of how the SSO solutions work in general. Perhaps this might help you to get started if you have to do something like this at some point. SSO is by no means a new technology. It has been in use for a long time. Even before the Web Applications were available. The most primitive of SSO systems is a piece of paper per user with a small table listing systems with the user names and passwords. This list can be generally stamped on the user monitor. Later on it can evolve, instead any simple piece of paper, it can be a post-it. ![]() (for those of you interested in how I created this picture, I did it using the napkin look and feel) Yes, you might be thinking that I am kidding here. And to some extent I am. However, this has been a big concern in the corporate world. That's the way it used to be, not by design, and it still is in some companies. Lots of applications, managed by different teams in the famous "silos", not integrated, each requiring the user to authenticate with its own username/password... you know the picture. I think that that's how the need of SSO got started. Early SSO systems worked as the post-it that the users where sticking to their monitors. They were repositories of users/passwords pairs protected by a password. In that way before the user would authenticate to the destination system, they would first access the SSO repository, fetch their passwords, and continue authenticating with the system they were intending to work on the first place. Lately, In a web based environment, this can be extremely simplified with a well know device: cookies. ExampleWe will go over an SSO implementation with an example. Let's have 3 major components: The SSO server, Application A, Application B.Here is how the system would work: 1) The user tries to access the application A. 2) Application A realizes that the user has not been authenticated. (See "user has been authenticated" for details). 3) Application A sends an HTTP redirect to the SSO server. 4) The SSO server sees that the user is not authenticated (again, See "user has been authenticated" for details). 5) The SSO server requires the user to authenticate. 6) The user submits username/password 7) SSO Server validates username/password. If they are valid, the user is "granted permission". 8) The user is redirected to Application A. 9) Application A sees that the user has been authenticated, and proceeds. Granting permission:When the username and password are validated by the SSO server, a unique large token is generated for the user. The token is going to have a unique identifier for the user's session. The SSO server keeps a list of the tokens associated with the credentials of the user that owns it. This token is set by the SSO server in the user's browser as a cookie.User has been authenticated:For an application to validate that a user has been authenticated it has to follow this steps:1) Check for the token in the cookies. 2) Query the SSO server for the credentials associated with the token. If the token is valid, the SSO returns the credentials of the user for the application to continue. If the token is not present, or is invalid, the application knows that the user has not been authenticated, and is redirected to the SSO server. This makes it look like there is a lot of work to get this type of setup. Luckily, it is not complicated at all. Most SSO servers come with a plug-in that is installed in the application/web server that intercepts all the requests, and performs the logic just described. Any application deployed in such a server will automatically get the user credentials, populated by the plug-in, just as if the user was authenticated locally using the JAAS framework. A Note on CookiesAs most of you know the capabilities of setting and reading cookies are restricted by the domains. A web server that does not belong to the domain where the cookie was set will not be able to read the cookie.For that reason the applications and the SSO server have to belong to the same domain. Indeed, if they are not to be part of the same domain the cookies would not work. For that case the URL rewriting technique can be used. Development TIP:When you are developing your app, no need to authenticate with the SSO. Just have each developer to work with a simple JAAS authentication within a local flat file (most of the IDEs have this by default). Get them to complete the development, and when you are ready to test, deploy it in your testing environment using the SSO plugin.Zilonis Rules Engine at JavaOnePosted by elevy on May 10, 2007 at 10:13 PM | Permalink | Comments (3)The Zilonis Rules Engine is a Java Rules Engine that is Thread-Safe. It was presented yesterday at the JavaOne. The presentation discussed the challenges of implementing a Pricing Service in Retail, why using a Rules Engine would be a challenge, and the way Zilonis solves those scalability issues. We finished the session with the details of how it uses Read-Write Locks to achieve the multithreading capabilities with a high degree of concurrency. Also the Zilonis Analysis Tool (100% written with Swing) did its debut, and was used as a way to explain how the RETE algorithm works. After cleaning up a little bit the Analysis Tool, I will be updating the Zilonis Rules Engine web site, and its repository releasing all the updates that I have been working on for quite a while. Some attendees approached me afterwards the presentation to tell me that they enjoyed the session. Thank you guys for your feedback. I am planning to write some blogs explaining some of the optimizations that I have included in the engine. Also, I will be describing in detail all the different parts of the implementation for those of you that were not able to make it to the presentation. Most likely this part will make it in the documentation at the Zilonis web site. JavaOne: Using the Java Concurrency API and Deadlock Prevention in a RETE Rules Engine to Implement a Pricing EnginePosted by elevy on May 04, 2007 at 11:56 AM | Permalink | Comments (0)The JavaOne conference is coming up next week. I am very excited specially because I will be presenting the BOF session: Using the Java Concurrency API and Deadlock Prevention in a RETE Rules Engine to Implement a Pricing Engine. In the presentation I will be covering how the Zilonis Rules Engine manages concurrency, and how it can be used in an E-Commerce application for determining prices. I will demo the Zilonis Rules Analysis Tool. That tool is implemented using some of the Swing hacks available in the Aerith application, and the UI looks really cool! After the JavaOne I will posting some blogs about the engine, the tools, and the algorithm in general. Also I will update the Zilonis web site, with the latest version, more documentation, and some surprises that I have to keep for after the JavaOne. See you guys over there! Multithreaded Hash TablePosted by elevy on April 17, 2007 at 08:49 AM | Permalink | Comments (7)If your application needs a "Hash Table" type of structure you have several options. One is to use the java.util.Hashtable. In a multithreaded environment it would be safe, but not very efficient. If you have a couple of threads that want to read from the hash table, they will have to wait for each other. This wait is not necessary. There is no problem having multiple threads reading a structure. Another solution is to use the java.util.HashMap. Again in a multithreaded environment, you have to ensure that it is not modified concurrently or you can reach a critical memory problem, because it is not synchronized in any way. I thought that the solution was to use the static Collections.synchronizedMap method. I was expecting it to return a better implementation. But if you look at the source code you will realize that all they do in there is just a wrapper with a synchronized call on a mutex, which happens to be the same map, not allowing reads to occur concurrently. In the Jakarta commons project, there is an implementation that is called FastHashMap. This implementation has a property called fast. If fast is true, then the reads are non-synchronized, and the writes will perform the following steps:
This implementation will work fine for the applications that write everything that they need into the structure at startup, and then only perform reads. You can see that writing into this structure is expensive. For the case where you need to do some writes every now and then, it can introduce a significant memory/performance issue. I wrote a very simple implementation. It starts creating a ReentrantReadWriteLock. Then every time we do a read operation we lock for reading. When we want to do an operation that modifies the structure, we call a write lock. Here an excerpt from the code:
public class FastSynchronizedMap implements Map,
Serializable {
private final Map m;
private ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
.
.
.
public V get(Object key) {
lock.readLock().lock();
V value = null;
try {
value = m.get(key);
} finally {
lock.readLock().unlock();
}
return value;
}
public V put(K key, V value) {
lock.writeLock().lock();
V v = null;
try {
v = m.put(key, value);
} finally {
lock.writeLock().lock();
}
return v;
}
.
.
.
}
Note that we do a try finally block, we want to guarantee that the lock is released no matter what problem is encountered in the block. This implementation works well when you have almost no write operations, and mostly read operations. When we want to insert into a hash table, we can see that depending on the hash code of the key that we are trying to insert, we will modify only one section of the structure. We could create a lock for each of the sections. In that way we can even have concurrent writes happening at the same time. An approach like that one is the one followed by the ConcurrentHashMap in the concurrency API. Looking at the implementation is interesting. There is an inner class called Segment. The Segment is a "specialized version of hash tables". When you want to do an insert or read operation in the ConcurrentHashMap, it first finds the Segment where the key belongs too. After that it proceeds to do the operation on the respective Segment. Interestingly enough, the Segment uses a ReentrantLock (actually it extends the ReentrantLock, I guess to save an instance). The lock is only used when writing to the table. When a read occurs no lock is performed. If you are aware of the Java Memory Model you can be asking yourself what about the visibility? Can you get a partially built object when you are accessing it? Actually, the HashEntry that holds the value, and the value itself are defined as volatile. In that way you are guaranteed to read the value only when it has been fully initialized. And there is a check after performing the get to make sure a null reference is not being returned (this can happen if the compiler happens to reorder the operations). In the case of a null reference, it performs the lock to ensure that we have the proper visibility and then read the value. The choice of the structure to use, will depend on the scenario where you want to use it. Understanding how each of the structures work would be the first step into getting the right decision. If you are working on a web application, and you are loading some data into a hash table when the Servlet is initialized and then just reading the data from concurrent requests a HashMap should suffice. If you are just updating the table from time to time on a very controlled way, an implementation like the one I proposed above would do the job. If you are going to be updating the data often, a ConcurrentHashMap will actually give you better performance. However, if you want to iterate the data, and have guarantees that the data is correct, then may be a Hashtable is the answer. For those of you who are interested in concurrency, I would encourage you to look at the implementation of the ConcurrentHashMap. I would say that it is a nice source to learn from.
Multithreaded Hash TablePosted by elevy on April 17, 2007 at 08:49 AM | Permalink | Comments (7)If your application needs a "Hash Table" type of structure you have several options. One is to use the java.util.Hashtable. In a multithreaded environment it would be safe, but not very efficient. If you have a couple of threads that want to read from the hash table, they will have to wait for each other. This wait is not necessary. There is no problem having multiple threads reading a structure. Another solution is to use the java.util.HashMap. Again in a multithreaded environment, you have to ensure that it is not modified concurrently or you can reach a critical memory problem, because it is not synchronized in any way. I thought that the solution was to use the static Collections.synchronizedMap method. I was expecting it to return a better implementation. But if you look at the source code you will realize that all they do in there is just a wrapper with a synchronized call on a mutex, which happens to be the same map, not allowing reads to occur concurrently. In the Jakarta commons project, there is an implementation that is called FastHashMap. This implementation has a property called fast. If fast is true, then the reads are non-synchronized, and the writes will perform the following steps:
This implementation will work fine for the applications that write everything that they need into the structure at startup, and then only perform reads. You can see that writing into this structure is expensive. For the case where you need to do some writes every now and then, it can introduce a significant memory/performance issue. I wrote a very simple implementation. It starts creating a ReentrantReadWriteLock. Then every time we do a read operation we lock for reading. When we want to do an operation that modifies the structure, we call a write lock. Here an excerpt from the code:
public class FastSynchronizedMap implements Map,
Serializable {
private final Map m;
private ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
.
.
.
public V get(Object key) {
lock.readLock().lock();
V value = null;
try {
value = m.get(key);
} finally {
lock.readLock().unlock();
}
return value;
}
public V put(K key, V value) {
lock.writeLock().lock();
V v = null;
try {
v = m.put(key, value);
} finally {
lock.writeLock().lock();
}
return v;
}
.
.
.
}
Note that we do a try finally block, we want to guarantee that the lock is released no matter what problem is encountered in the block. This implementation works well when you have almost no write operations, and mostly read operations. When we want to insert into a hash table, we can see that depending on the hash code of the key that we are trying to insert, we will modify only one section of the structure. We could create a lock for each of the sections. In that way we can even have concurrent writes happening at the same time. An approach like that one is the one followed by the ConcurrentHashMap in the concurrency API. Looking at the implementation is interesting. There is an inner class called Segment. The Segment is a "specialized version of hash tables". When you want to do an insert or read operation in the ConcurrentHashMap, it first finds the Segment where the key belongs too. After that it proceeds to do the operation on the respective Segment. Interestingly enough, the Segment uses a ReentrantLock (actually it extends the ReentrantLock, I guess to save an instance). The lock is only used when writing to the table. When a read occurs no lock is performed. If you are aware of the Java Memory Model you can be asking yourself what about the visibility? Can you get a partially built object when you are accessing it? Actually, the HashEntry that holds the value, and the value itself are defined as volatile. In that way you are guaranteed to read the value only when it has been fully initialized. And there is a check after performing the get to make sure a null reference is not being returned (this can happen if the compiler happens to reorder the operations). In the case of a null reference, it performs the lock to ensure that we have the proper visibility and then read the value. The choice of the structure to use, will depend on the scenario where you want to use it. Understanding how each of the structures work would be the first step into getting the right decision. If you are working on a web application, and you are loading some data into a hash table when the Servlet is initialized and then just reading the data from concurrent requests a HashMap should suffice. If you are just updating the table from time to time on a very controlled way, an implementation like the one I proposed above would do the job. If you are going to be updating the data often, a ConcurrentHashMap will actually give you better performance. However, if you want to iterate the data, and have guarantees that the data is correct, then may be a Hashtable is the answer. For those of you who are interested in concurrency, I would encourage you to look at the implementation of the ConcurrentHashMap. I would say that it is a nice source to learn from.
| ||
|
|