0

My GWT app (2.1.0) allows users to choose different methods of combining data. They can average, find the variance, etc. I achieve this effect with an enum that specifies which method to use.

Now I want to code custom methods for individual clients. For instance, someone could request a MODE feature.

One solution would be to just add MODE to the enum, write the getMode() function, and add it to the app. The problem comes in with 10,000 custom options. I don't mind writing 10,000 different methods, but I don't want all 10,000 functions being sent to each client. In fact, I want to make sure that one client can't see the implementation of another client's method, which may contain private data.

GWT.runAsync can help me split all of these methods into different chunks that will only be downloaded if the user requests it. Is there a way to run some sort of permission check before downloading that code? For example, I don't want someone changing the value of their enum-specified preference to trick the (private) code in to downloading.

I'm running this on the java GAE. I could write a filter to do a permission check before downloading cachedjs files, but since the names of the GWT files change after every compile I can't think of a way to control access to the different chunks in a meaningful way.

I hope this is clear. Thanks for any pointers!

Riley Lark
  • 20,660
  • 15
  • 80
  • 128

2 Answers2

1

If you're really concerned about the security of your source code, I would keep your private algorithm implementation on the server. Someone could easily look at your source (though obfuscated) and download any deferred source (also obfuscated).

If you use deferred binding (runAsync), you'll see something like this at the top of your main .cache.html file:

// spacing modified for readability
var $strongName = '02F159CD1F48EEB372B36E0BA704A0BE';
function __gwtStartLoadingFragment(frag) {
    return $moduleBase + 'deferredjs/'  + $strongName + '/' + frag + '.cache.js';
}

Looking at that, one can determine the path to download the source of your deferred code. If your server allows it (because checking permissions for a specific fragment might be hard), it will be served.

If you instead keep your code on the server, you can create an rpc service and check permissions on the server before returning the result. If you don't want to have a bunch of service methods, create one with the name of the method for dispatch and the data for the computation.


If you need to run your algorithm on the client, your could make it easier to protect your code by serving it dynamically via an RPC service and doing an eval() of it on the client. This would require implementing your algorithms in Javascript instead of GWT (the rest of your code would still be GWT).

1) Create a service method with a server implementation that looks something like this:

public String getAlgorithmCode(String name) {
    // locate the code. store it in a file, database, cache it in memory, etc.
    // ...
    return javascriptSourceCode;
}

2) Load the javascript into the page. Since you're only using this from GWT code, you can just eval() it in the current frame, but check out this article if you want to load it into $wnd.

http://blog.lexspoon.org/2009/03/many-scopes-of-javascripts-eval.html

If you write your javascript implementations using the same naming convention and function signature, you can just invoke it using JSNI.

3) When it's time to call this method, you can check to see if the function is defined.

If it doesn't exist, use the service to get it.

If it exists, call it using apply as described here Calling dynamic function with dynamic parameters in Javascript

Community
  • 1
  • 1
andykellr
  • 789
  • 6
  • 9
  • Unfortunately the code needs to be on the client because it's run several hundred times. I'd really need to do something like checking the permissions for a specific fragment. It could be that this is still the best possible answer - checking the permissions for a specific fragment could be too unwieldy to be worth the trouble! – Riley Lark Jan 24 '11 at 23:40
  • Can you implement your algorithms in pure Javascript and call them via JSNI? I can suggest an approach if that works for you. – andykellr Jan 24 '11 at 23:48
  • I'll post it anyway. Someone else may find it useful. – andykellr Jan 24 '11 at 23:52
  • This seems like the best solution. Thanks! – Riley Lark Jan 27 '11 at 22:07
0

Wrap the runAsync() call in your test.

if (testPermission()) {
  GWT.runAsync(...);
}

Or, if you want to make a call to a service

myService.testPermissions(user, new AsyncCallback() {
  @Override
  public void onFailure(Throwable caught) {
    ...
  }

  public void onSuccess(Boolean hasPermission) {
    GWT.runAsync(...);
  }
});
Jason Terk
  • 6,005
  • 1
  • 27
  • 31
  • But since testPermissions is on the client in this case, anyone can skip that code and go straight to the code download, right? – Riley Lark Jan 24 '11 at 23:35
  • If they go through the trouble, yes. As pulazzo said, if you don't want unauthorized users to be able to download the source file at all you need to enforce that on the server, either by denying access to the JS files or moving the logic server side. – Jason Terk Jan 24 '11 at 23:40