I have a sort of challenge with a development, basically I need to authorize the user to go/call to certain page/functionality using a token, those pages can be set to require authorization by demand (perhaps setting a param in a database).
The application was made with Struts 1, so what I have been thinking is just intercepting the URL using a filter, check if the request needs authorization, send the token via e-mail and redirect the user to the "insert token" page, then again intercept via filter if the referer was the token page and validate the value, if correct, then redirect to the original request...
However I can't simply recover the previous request, also the filter intercept the ServletRequest and Struts has a more detailed construction, so I can't loose the action or the form objects.
I'm not sure if this is a good approach to solve this need, if so, I need to keep the original request in memory and I'm not sure how to do that.
This is a legacy project and has a lot of pages and controllers, so it's almost imposible just going through every method doing validations.
I would accept any suggest, have a nice day! :)
EDIT
To add more context, the project has many forms made with Struts, so internally Struts map the html form to a POJO, to get them as parameters in the actions's (controllers) methods: ActionMapping and ActionForm. When I create a filter, my params are ServletRequest, ServletResponse and FilterChain objects, directly I don't have the ActionMapping or the ActionForm, but I know they are part of the request structure, so since I don't know how to get them directly, I'm trying to work with the whole request, hence the security and size issues, and also because I don't know how to store a copy of the original request while I'm doing the redirect operation
Given the amount of information Struts likes to pass around, I would be tempted to keep a session somewhere safe for the user's return. This post talks about a similar idea, though you could possibly just keep the sessions keyed by token.
Aware this idea would depend on the environment though, e.g. how quickly the user is expected to come back with the token, and the total number of users this needs to scale for.
I would have considered encrypted HTTP cookies (if your application privacy policy allows cookies).
You can store the required information for later use and expire it after a while. Also, you don't need to be concerned about session storage and scaling. Seems to me fits the bill.
Having said that, there're details that you need to consider. In particular cookie encryption.
Update
A note on big objects in cookie. Creating big HTTP header is not always a good idea. Most web servers even force a maximum on header size (see Maximum on http header values?). You need to serialize the binary data in Base64 encoding which makes it even larger.
If your objects really big (like Struts constructs) that can't fit in the HTTP header. You probably don't want to store them in your in-memory session either. You might want to consider a database backed session if feasible.
Tomcat (if this is your web container) has one JDBCStore and you can configure it. It's not great though, having a database query on each request/response.
An alternative to storing all sessions in database, is to only store that particular object in database and store its associated key in HTTP cookie. This is what I would probably do given the size of the object.
This is basically a trade-off between memory and speed. (I don't know the exact requirements of your application in terms of resources and performance).
After few days looking for a properly solution, I have decided to change the idea, instead of rewriting (in a very unsafe way) the request, I designed a two side solution, from the frontend side I intercept any request using JavaScript, I do an initial validation of the URL and then ask for the token, so finally I'm sending an additional parameter that I can get in the filter, and then after doing the validation, I can continue the original request or create a redirection.
Thank you all for the time and suggestions, I think is better explain what I did instead of leaving this topic in the air.
Related
I have an application which needs to accept a POST request from an outside server, to confirm payment. I don't want to break the default wicket render strategy (REDIRECT_TO_BUFFER) which is serving to give the users a nicer experience than ONE_PASS_RENDER would, however, the external service is not happy with the 302, and keeps retrying until it gives up.
Is there some sensible way that I can tell wicket to use ONE_PASS_RENDER for only the specific page that handles this request?
Try using a Resource instead of a Page to handle this request. That way, you can return whatever response you want (both HTTP headers and payload) to keep the external service happy.
It's a lower level API, though. If you need to respond with a rendered page, you may need to render it yourself (with lots of println() calls), or hack some way to Wicket to do it.
But since it is a response to a external service, I assume it will expect some kind of simple text, XML or JSON response, which are easy enough to do by hand.
What object can be used to intercept all requests to a web application before they reach the JSP or Servlet? I think the answer might be a filter, but I'm not sure if there is a more specific answer.
The filter is the way to go. You can map a filter much like a servlet so that it can cover the entire web site, or just portions.
Edit for comment -
Yes, that's pretty much what you need to do. Filters are the first part of the request chain. Well, after dispatch by the container, but the first part you as a developer have access to.
Filters can be chained, and each one can pre-empt the request chain (thus never hitting any later Filters or Servlets (JSPs are Servlets), they can proceed down the request chain, and they can usurp the results of the request chain (that is they can change or reject the output from components farther down. You can consider it an implementation of the Decorator pattern.
Some typical filters include security filters (checking whether the request has access to the desired resource), compression filters, request modification filters (the functionality of Apaches mod_rewrite has been implemented as a Filter, for example). Filters can completely replace the actual request and response object (many do so by wrapping the existing ones), so they really do have complete control over the request chain, and eventual Servlet or static resource has no idea the Filter is there.
Filters are a wonderful aspect of the Servlet stack.
The filter is the best way to route all the request to the jsp/servlet ,
Usage:
1. To check whether user has valid session.
2. Add a attribute to the request.
3. Compress the outputstream incase of file download.
4. anlayse request, i.e. frequently visited page for buisness analyst.
Yes Filter is the Right answer . Just wanted to add in a MVC design pattern similiar thing can be done with a controller servlet. Which first takes all the requests before moving somewhere else.
I have a Java web application which stores some data in the session. The data in the session changes as the user interacts with the application (e.g. flow is managed by a controller, each controller has several form pages, on each form page some data is updated in the session and flow goes to the next form page).
The problem is that some users are opening more than one tab to the application, each tab with a different step in the flow. At this point data in the session is messed up since the tabs share the same session (app uses cookie managed sessions).
Telling the users to use different browsers to avoid sharing the same session id (e.g. one Firefox window and one IE window) is not an option since surely at some point somebody will forget to do this and instead use tabs, thus messing up their data.
Adding some verifications that detect that another flow is requested from another tab and display a message to the user saying this is not allowed is not an option either since it pisses of the users and we don't want that do we? :D
The fact is that using another tab is useful for the users because they are more efficient in what they use the application for, so I am keeping this option. But the question now is how best to manage the one session data for the more tabs?
What I thought of, was to have the controller generate a token when it starts the flow and pass this token to each form page which in turn sends it back to identify itself. If another tab requests the same controller action when there is an ongoing flow then generate another token and pass that around.
Basically, I want each flow to have a token and inside the session I won't just keep one set of data but have a set of data for each token and then match requests based on the token.
Now the problem is that this approach will need a lot of rewritings to the application and I was wondering if there is a best practice for managing such a situation or can someone suggest other approaches. I am open to ideas.
Have you encountered this situation? How did you handle it?
This is usually done by assigning a windowId for each tab/window and passing it on each request. Jsf supports this via orchestra. Spring mvc will support it in the next version.
I recently needed this for a simple case, so I implemented it myself. Took half an hour. However, my scope was very limited:
pass a windowId with each request, and return it back for the next request. The first time - generate it.
for any attribute you want to store in the session, put a Map<String, Object> where the key is the windowId
This is exactly what Seam was created to handle. In Seam there's a concept called a Conversation which basically does exactly what you are explaining. Conversations are basically are a way to divide the Session into many pieces that can expire at some timeout. You can look at the source code for org.jboss.seam.core.Manager class to see how it's actually implemented and get inspired ;)
Depending on the complexity of your application, you may want to investigate implementing tabs within your application. This gives you wholesale control over the flow, while still providing users with the functionality they want. I'd argue it's, bugwise, the most robust solution, since you won't have a dependency on the way the browser handles sessions, minimising the number of "known unknowns".
Of course, there'll be potentially a large upfront cost to this, depending on how your application is structured. Without more information about your app, you're the best placed person to decide.
You can also try to wrap your application inside Adobe Air
And then limit your web application to be only accessable from this air. By doing this you dont need to consider the web browser fragmentation and their unique behaviour.
We are currently working on a very simple Webapp, and we would like to "obfuscate" ( what would be the right term? ) or encode somehow the request parameter, so we can reduce the chance an idle user from sending arbitrarily data.
For instance, the url looks like /webapp?user=Oscar&count=3
We would like to have somthing like: /webapp?data=EDZhjgzzkjhGZKJHGZIUYZT and have that value decoded in the server with the real request info.
Before going into implementing something like this ourselves ( and probably doing it wrong ) I would like to know if there is something to do this already?
We have Java on the server and JavaScript on the client.
No, don't do this. If you can build something in your client code to obfuscate the data being transmitted back to the server, then so can a willful hacker. You simply can't trust data being sent to your server, no matter what your official client does. Stick to escaping client data and validating it against a whitelist on the server side. Use SSL, and if you can, put your request parameters in a POST instead of GET.
Expansion edit
Your confusion stems from the goal to block users from tampering with request data, with the need to implementing standard security measures. Standard security measures for web applications involve using a combination of authentication, privilege and session management, audit trails, data validation, and secure communication channels.
Using SSL doesn't prevent the client from tampering with the data, but it does prevent middle-men from seeing or tampering with it. It also instructs well-behaved browsers not to cache sensitive data in the URL history.
It seems you have some sort of simple web application that has no authentication, and passes around request parameters that control it right in the GET, and thus some non-technically savvy people could probably figure out that user=WorkerBee can simply be changed to user=Boss in their browser bar, and thus they can access data they shouldn't see, or do things they shouldn't do. Your desire (or your customer's desire) to obfuscate those parameters is naïve, as it is only going to foil the least-technically savvy person. It is a half-baked measure and the reason you haven't found an existing solution is that it isn't a good approach. You're better off spending time implementing a decent authentication system with an audit trail for good measure (and if this is indeed what you do, mark Gary's answer as correct).
So, to wrap it up:
Security by obfuscation isn't
security at all.
You can't trust
user data, even if it is obscured.
Validate your data.
Using secure communication channels (SSL)
helps block other related threats.
You
should abandon your approach and do
the right thing. The right thing, in
your case, probably means adding an
authentication mechanism with a
privilege system to prevent users
from accessing things they aren't
privileged enough to see - including
things they might try to access by
tampering with GET parameters. Gary
R's answer, as well as Dave and Will's comment hit
this one on the head.
If your goal is to "reduce the chance an idle user from sending arbitrarily data," there's another simpler approach I would try. Make a private encryption key and store it in your application server side. Whenever your application generates a url, create a hash of the url using your private encryption key and put that hash in the query string. Whenever a user requests a page with parameters in the url, recompute the hash and see if it matches. This will give you some certainty that your application computed the url. It will leave your query string parameters readable though. In pseudo-code,
SALT = "so9dnfi3i21nwpsodjf";
function computeUrl(url) {
return url + "&hash=" + md5(url + SALT );
}
function checkUrl(url) {
hash = /&hash=(.+)/.match(url);
oldUrl = url.strip(/&hash=.+/);
return md5(oldUrl + SALT ) == hash;
}
If you're trying to restrict access to data then use some kind of login mechanism with a cookie providing a Single Sign On authentication key. If the client sends the cookie with the key then they can manipulate the data in accordance with the authorities associated with their account (admin, public user etc). Just look at Spring Security, CAS etc for easy to use implementations of this in Java. The tokens provided in the cookie are usually encrypted with the private key of the issuing server and are typically tamper proof.
Alternatively, if you want your public user (unauthenticated) to be able to post some data to your site, then all bets are off. You must validate on the server side. This means restricting access to certain URIs and making sure that all input is cleaned.
The golden rule here is disallow everything, except stuff you know is safe.
If the goal it to prevent "static" URLs from being manipulated, then you can simply encrypt the parameters, or sign them. It's likely "safe enough" to tack on an MD5 of the URL parameters, along with some salt. The salt can be a random string stored in the session, say.
Then you can just:
http://example.com/service?x=123&y=Bob&sig=ABCD1324
This technique exposes the data (i.e. they can "see" that xyz=123), but they can not change the data.
There's is an advantage of "encryption" (and I use that term loosely). This is where you encrypt the entire parameter section of the URL.
Here you can do something like:
http://example.com/service?data=ABC1235ABC
The nice thing about using encryption is two fold.
One it protects the data (they user can never see that xyz=123, for example).
The other feature tho is that it's extensible:
http://example.com/service?data=ABC1235ABC&newparm=123&otherparm=abc
Here, you can decode the original payload, and do a (safe) merge with the new data.
So, requests can ADD data to the request, just not change EXISTING data.
You can do the same via the signing technique, you would just need consolidate the entire request in to a single "blob", and that blob is implicitly signed. That's "effectively" encrypted, just a weak encryption.
Obviously you don't want to do ANY of this on the client. There's no point. If you can do it, "they" can do it and you can't tell the difference, so you may as well not do it at all -- unless you want to "encrypt" data over a normal HTTP port (vs TLS, but then folks will wisely wonder "why bother").
For Java, all this work goes in a Filter, that's the way I did it. The back end is isolated from this.
If you wish, you can make the back end completely isolated from this with an outbound filter that handles the URL encryption/signing on the way out.
That's also what I did.
The down side is that it's very involved to get it right and performant. You need a light weight HTML parser to pull out the URLs (I wrote a streaming parser to do it on the fly so it didn't copy the entire page in to RAM).
The bright side is all of the content side "just works", as they don't know anything about it.
There's also some special handling when dealing with Javascript (as your filter won't easily "know" where there's a URL to encrypt). I resolved this by requiring urls to be signed to be specific "var signedURL='....'", so I can find those easily in the output. Not as crushing a burden on designers as you might think.
The other bright side of the filter is that you can disable it. If you have some "odd behavior" happening, simply turn it off. If the behavior continues, you've found a bug related to encryption. It also let developers work in plain text and leave the encryption for integration testing.
Pain to do, but it's nice overall in the end.
You can encode data using base64 or something similar. I would encode the arguments inself in JSON to serialize them.
Something like jCryption ?
http://www.jcryption.org/examples/
I had written java code for information sent and received for the server in bytes.The issues is how do i differentiate a HTTP Request submitted from a HTML form and a HTTP Request submitted from user. we are trying through refer in HTTP headers, but for the first request the referrer is null. hence this option is not feasible. is there any other API/other approach? Please let me know with a sample code...
thanks,
Ps
I understand the problem better now. The simple answer is no. The more complex answer is kind of, the best you can do is make an informed guess.
If the request does not have a Referrer header(1) then this might mean the user went to the URL directly (via typing it in to the address bar, or selecting a bookmark for instance). The problem here is that you're not guaranteed to receive that header, so you have to hope the browser is behaving.
Next, if the request type is a POST and the mime type is "application/x-www-form-urlencoded" or "multipart/form-data" then that is usually a form submission, i.e. a user has clicked submit, or similar.(2)
It is not (usually) possible for users using a browser to issue POST requests directly.
So that's a couple of basic rules to help you make a best guess, but there are so many things on the browser side that can mess with this logic I honestly don't think you'll find something that'll help you accurately.
Here's the algorithm at a high level:
When generating the HTML form, generate a random number/String/GUID and embed it in the form as a hidden input. Store this random value server-side (in application context, in a LinkedHashMap so you can set a maximum size/MRU cache, in some sort of cache solution, etc.)
When processing the form request, check for the presence of this random token.
If the request contains the random token, then source = HTML form
Else, source = human
You could also set cookies when sending the original HTML form, check for their presence on the postback; put some data in the Session object, etc; these are all variants on the same idea.
If this is for security reasons, then this is not possible. Anything the browsers sends to you, can also be send by the user.
But unclear is what you mean by send by the user.
Like Brindy said. Check the method, if its post check the mime type. It is as accurate as you are going to get. Unless the user is a professional he will not know how to fake a form submission, and most apps that use post to communicate that are not browsers will specify a different mime type.