I have a web-based application which makes use of remote EJBs for its business logic. Some of these EJBs are also exposed as Web Services. I need to keep a small state for some of these calls in order to allow subsequent calls to function correctly. Which of the following would you recommend?
Stateful EJBs (will this work with Web Services?)
Return the state to the client (what if I want to prevent the client from altering the state?)
Reload the state from the DB on each method (should I worry about the overhead?)
All three proposed solutions can be made to work, but the best solution will depend on the details of your application.
I don't use Stateful Session Beans (SFSBs) at all. SFSBs are designed to keep session state, but using them via a Web Service raises questions about what exactly is a session? If you have a complicated deployment environment or users use multiple instances of the application then this could be a fragile solution.
Returning state - as the question indicates, there could be security issues unless you are certain that the server can trust its clients. You could use encryption techniques to verify that the state object had not been modified, but it is much safer not to give sensitive data to a potentially hostile client. Another situation where this might be useful is if the client is permitted to alter the state, or if no harm can be done if the client does so. If client access to the system is always through a web-tier, this is a good place to store session state. The web-tier and application-tier can safely exchange state objects.
Reloading the state from the database is probably the most generally applicable approach. If you use an entity bean or an Object Relational Mapping library then the server should be able to reduce the number of database queries.
The only option you have is to store appropriate information associated with a certain UserId in the DB.
You can't expose Statefull bean as Webservice.
In case of exposing your Beans as Webservices you could try to send additional information back and forth by putting in the SOAP header to prevent modifications in the body. But in this case clients will be able to alter it.
Related
I have an RMI server which uses JAAS as authentication mechanism and exposes several business objects (MBeans). The JAAS login module contains multiple credentials each associated with different permissions, e.g. READ-ONLY, READ-WRITE, DEV etc. MBeans in turn are to rely on those permissions in order to allow/reject certain method calls.
I have spent a good few days researching/experimenting and so far could not find a mechanism which would allow MBeans to determine the authenticated RMI user when a call is invoked on them.
First of all I am aware that there is RemoteServer::getClientHost(), but identifying a client by IP is not suitable since multiple processes could potentially connect from a single IP.
So far, my findings are:
When an RMI connection is established the user is authenticated and a new RMIConnectionImpl instance is created
RMIConnectionImpl contains authentication subject/principals as well as what looks like a unique connection id
None of the identifying information of RMIConnectionImpl is available/retrievable when remote calls are made
Since it seems to be impossible to figure out which RMIConnectionImpl the call is coming from I have initially tried to use the thread which was attempting JAAS authentication as identifier. That plan didn't work since, naturally, RMI uses thread pools and subsequent remote method invocations were not guaranteed to be carried out by the same thread.
Another idea I contemplated was to use AspectJ LTW to intercept RMIConnectionImpl::invoke(..) and to associate a user with a thread through some global ThreadLocal. But there is a world of pain to get it all working, plus it does feel like a massive overkill.
Surely there must be a simpler solution to this really common use case. Hence I am quite puzzled and worried I might be missing something big here.
Any help/suggestions would be much appreciated.
Can anyone give me an example of truly stateless RESTful endpoints? a simple question, if server is completely stateless, how do we invalidate previous tokens? I consider saving state to DB as bad practice. lets say there are hundreds of requests per second, that would mean hundreds of queries to DB per second (if you save state to DB) and that's bad news. if you save state to server, you'll run into session transfer problem when using multiple servers and load balancers.
Well one example of course would be endpoints that don't need authenticating, and dependent on your structure there are others. For example if you are using something like AngularJS you don't need to have authorization in the same way as you would use it with something like a developer API - you can use session variables which can be signed and stateless.
If you are worried about performance of performing database queries on simple state things like this, it is worth looking at some solutions like Redis, which you can send hundreds of queries to with very little strain.
Stateless restful endpoints by definition wouldn't use tokens (having a lifetime) or state. If you need those, then you don't have a truly stateless restful endpoint.
As an answer to your question, a web server without authentication or a similar mechanism could be considered truly stateless rest endpoint. It would just deliver a file from disk on GET request to anyone requesting it.
Also, if authentication is hardcoded basic auth or similar mechanism sending login details on every request, it would be still stateless. When you start adding tokens that expire you definitely already have state.
For details on doing authentication in a stateless REST manner you can read up on this discussion.
I have a Java web application which is deployed on two VMs. and NLB (Network Load Balancing) is set for these VMs. My Application uses sessions. I am confused that how the user session is managed in both VMs. i.e. For Example- If I make a request that goes to VM1 and create a user session. Now the second time I make request and it goes to VM2 and want to access the session data. How would it find the session which has been created in VM1.
Please Help me to clear this confusion.
There are several solutions:
configure the load balancer to be sticky: i.e. requests belonging to the same session would always go to the same VM. The advantage is that this solution is simple. The disadvantage is that if one VM fails, half of the users lose their session
configure the servers to use persistent sessions. If sessions are saved to a central database and loaded from this central database, then both VMs will see the same data in the session. You might still want to have sticky sessions to avoid concurrent accesses to the same session
configure the servers in a cluster, and to distribute/replicate the sessions on all the nodes of the cluster
avoid using sessions, and just use an signed cookie to identify the users (and possibly contain a few additional information). A JSON web token could be a good solution. Get everything else from the database when you need it. This ensures scalability and failover, and, IMO, often makes things simpler on the server instead of making it more complicated.
You'll have to look in the documentation of your server to see what is possible with that server, or use a third-party solution.
We can use distributed Redis to store the session and that could solve this problem.
Is there a best-practice for scalable http session management?
Problem space:
Shopping cart kind of use case. User shops around the site, eventually checking out; session must be preserved.
Multiple data centers
Multiple web servers in each data center
Java, linux
I know there are tons of ways doing that, and I can always come up with my own specific solution, but I was wondering whether stackoverflow's wisdom of crowd can help me focus on best-practices
In general there seem to be a few approaches:
Don't keep sessions; Always run stateless, religiously [doesn't work for me...]
Use j2ee, ejb and the rest of that gang
use a database to store sessions. I suppose there are tools to make that easier so I don't have to craft all by myself
Use memcached for storing sessions (or other kind of intermediate, semi persistent storage)
Use key-value DB. "more persistent" than memcached
Use "client side sessions", meaning all session info lives in hidden form fields, and passed forward and backward from client to server. Nothing is stored on the server.
Any suggestions?
Thanks
I would go with some standard distributed cache solution.
Could be your application server provided, could be memcached, could be terracotta
Probably doesn't matter too much which one you choose, as long as you are using something sufficiently popular (so you know most of the bugs are already hunted down).
As for your other ideas:
Don't keep session - as you said not possible
Client Side Session - too unsecure - suppose someone hacks the cookie to put discount prices in the shopping cart
Use database - databases are usually the hardest bottleneck to solve, don't put any more there than you absolutely have to.
Those are my 2 cents :)
Regarding multiple data centers - you will want to have some affinity of the session to the data center it started on. I don't think there are any solutions for distributed cache that can work between different data centers.
You seem to have missed out vanilla replicated http sessions from your list. Any servlet container worth its salt supports replication of sessions across the cluster. As long as the items you put into the session aren't huge, and are serializable, then it's very easy to make it work.
http://tomcat.apache.org/tomcat-6.0-doc/cluster-howto.html
edit: It seems, however, that tomcat session replication doesn't scale well to large clusters. For that, I would suggest using JBoss+Tomcat, which gives the idea of "buddy replication":
http://www.jboss.org/community/wiki/BuddyReplicationandSessionData
I personally haven't managed such clusters, but when I took a J2EE course at the university the lecturer said to store sessions in a database and don't try to cache it. (You can't meaningfully cache dynamic pages anyway.) Http sessions are client-side by the definition, as the session-id is a cookie. If the client refuses to store cookies (e.g. he's paranoid about tracking), then he can't have a session.
You can get this id by calling HttpSession.getId().
Of course database is a bottleneck, so you'll end up with two clusters: an application server cluster and a database cluster.
As far as I know, both stateful message beans and regular servlet http sessions exist only in memory without load balancing built in.
Btw. I wouldn't store e-mail address or usernames in a hidden field, but maybe the content of the cart isn't that sensitive data.
I would rather move away from storing user application state in an HTTP session, but that would require a different way of thinking how the application works and use a RESTful stateless architecture. This normally involves dropping support for earlier versions of browsers that do not support MVWW architectures on the client side.
The shopping cart isn't a user application state it is an application state which means it would be stored on a database and managed as such. There can be an association table that would link the user to one or many shopping carts assuming the sharing of carts is possible.
Your biggest hurdle would likely be how to authenticate the user for every request if it is stateless. BASIC auth is the simplest approach that does not involve sessions, FORM-auth will require sessions regardless. A JASPIC implementation (like HTTP Headers or OAuth) will be able to mitigate your authentication concerns elsewhere, in which case a cookie can be used to manage your authentication token (like FORM-auth) or HTTP header like SiteMinder or Client Side Certificates with Apache.
The more expensive databases like DB2 have High Availability and Disaster Recovery features that work across multiple data centers. Note that it is not meant for load balancing the database, since there'd be a large impact due to network traffic.
I've got a Java client that needs to access a remote database. It is the goal to hide database credentials from the user and not hardcode any credentials within the code. Therefore, the database access will probably have to be on the server side.
I'm restricted to use Ibatis as a data abstraction framework. Apart from that I have JBoss running on the webserver, allowing me to use data sources.
How would you design the remote database access and data serialization/deserialization. would you prefer web services of some kind of data stream over a socket? How would you realize either of both?
Build a Service Layer and expose it over RMI - possibly as EJB3 stateless session beans as you have JBoss, possibly as pure RMI. I wouldn't bother with web services unless you have a specific need. RMI will take case of serialisation for you.
Your service layer needs to expose a method to authenticate users using their credentials entered on startup of the Swing app. All calls for data go through the service layer. No SQL exists in the Swing app.
There are other benfits of this arrangment other than just hiding the database credentials. Not only do you end up with a layered architecture, but you gain efficiencies from sharing prepared statements amongst all your clients by having a single data source on the server.
So you want users to be able to access the database without knowing the credentials? Your only option is server-side database access. Unfortunately there is no way of hiding the username and password in Java -- if you put it into a properties file and encrypt it, a determined attacker could still attach a debugger and see what values are being held in your code.
Also, unless you're connecting to the DB over a secure connection someone could run a packet sniffer such as tcpdump and get the credentials there.
You say that you're running a JBoss server, what might be best is to set up remote EJBs so that your client application doesn't access the database directly - it has to go via your EJB methods. (It doesn't have to be EJB, by the way, you could do something such as web services if you prefer).
The point is, your server talks to the databas directly, and your client's only access is via a limited set of interfaces you define on the server.
As has been already said, you have to connect to a server which handles the database connection. There is no way to effectively prevent someone from breaking your security, with 30 minutes of effort.
If the clients are connecting somewhat locally, within an intranet, using EJB's on your appserver is probably the best choice... though you probably want stateless session beans, i wouldnt necessarily discount message driven beans.
For longer distances where the traffic is coming from the outside, I would use webservices over HTTPS
In any event, most appservers have mechanisms to expose their EJB's as webservices, with the WSDL; and there are about a hundred utilities to generate clients, to call the webservice, from a WSDL (axis's wsdl2java works well enough)