Fetch application port without access to request object - java

I have a back end process which is initiated on server startup. After completion of this process I send an email to users. I need access to application port in order to construct the complete URL of a web report running on same instance. Is there a way to fetch the port without access to request object ?

I need access to application port in order to construct the complete URL of a web report running on same instance. Is there a way to fetch the port without access to request object ?
Why don't you store this as a property in a configuration file to your back-end process? The code will turn out to be much simpler if just need just the port (or even a website URL fragment that doesn't change) that needs to be embedded in an email.
Besides, the administrators in question have better things to do than change port numbers on a periodic basis.
Related questions (but not quite the same)
Root URl of the servlet
Finding your application's URL with only a ServletContext
Both of them provide reasons, why the path seen by a servlet container, need not be the same as the one seen by an end user. Even if both are the same, there is no way, one can access this information without
reading the server configuration files. In this case, it would be $JETTY_HOME/etc/jetty.xml, which has the necessary info in the Connectors elements.
obtaining a reference to a ServletRequest object, which might not be a valid answer to this question.

If you have at least one http request call in your application, you could get port from it:
int portNumber = request.getServerPort();
Maybe your startup script can make such call.
More details: http://www.kodejava.org/examples/211.html

Related

Sharing session data between two war files

I have two war files such as war1 and war2
If am login the application, the session will be created in war1 and from that if am navigate to war2, there i need the same session data.
I tried crossContext=true in context.xml of server from that i can access the data by storing it in servletContext.
But the issue is once i logined the screen in chrome the session data will be stored in servletContext and the data will maintain till the application is running.
If am giving the same URL in another browser like IE here also, i can get the servletContext data so instead of navigate to login page the corresponding screen will be opened
Kindly suggest me how can i overcome this issue in java?
Is there any way to findout browser switching or incognito window mode of the browser in java?
Note: am using tomcat server
I have never dealt with your exact configuration problem, but even if you can make this work on a single Tomcat instance, you might have problems should your two web applications ever be distributed across multiple Tomcat instances.
So, I am going to suggest that you actually use a database to store state which needs to be passed between the two applications in a safe and reliable way. Note that the database approach also scales nicely in a distributed environment, so long as you have a single logical database.
While session replication indeed can be done in Tomcat (see here) I really suggest you to avoid this type of issues by eliminating the session altogether.
This session replication is an approach that was somewhat common before ~15-10 years, but nowadays when we have a lot of servers running in parallel to serve user requests and have elastic clusters, this approach is not good enough because basically it doesn't scale well.
There are many ways to achieve what you want, though:
Use a shared database to store the session information. Add some session Id to the response and require the client to pass this id back into all subsequent request along the session. Then execute a query to the Database by this Id and retrieve all the session information.
This solution also doesnt really scale well, but then you can shard the session information if the db permits to do so...
Use Redis/Aerospike to save the session information of the currently connected user. somewhat like DB approach, but since redis run in-memory it will be much faster. In general, this approach can be used in conjunction with 1 where redis is an in-memory cache.
Encrypt the session information or even just sign cryptographically and send back to client. Client will have to supply this information along with the request without knowing which server will actually serve this request.
Without delving into cryptography I'll just state that encryption can be done if you don't want client to see the session information (despite the fact that this is the user whose information is supplied) and signature is used to prevent tempering the data (while sending it back to server).
The data can be supplied to server from client via Header or cookie for instance.

Software integration and shared database for a master application

I have 4 separate software systems which implemented separately using java EE, Spring,hibernate etc.I want to integrate all of them and build a master application. I want to have a single login as well. Now they have their own databases and I want to have a shared single database as well because they have some common information.
What is the best method which can be used to achieve this task with having minimum changes to currently implemented systems?
Do I have to implement a new service layer( eg: using JAX-RS) or something on top of new db to access the new shared database and provide all db access services with business logic to above software systems??
For DataBase:
Spring/hibernate applications support connecting to one database by default. If you want to connect to multiple databases (own db + common db) then you will have to take care of database objects (Jdbc connection + pools + lifecycle/transaction management + other db initialisations) by yourself.
In my opinion DB connection+lifecycle initialisation yourself can be a huge pain and will take away your focus from solving real business cases. I would suggest using a single DB for the applications if possible. Most databases allow you to use file-per-table and even distribute the table files across multiple machines/servers (this is an optimisation).
Code Unification
For Unifying the code base into one (I assume you want to unify the codebases), you can make each application a separate module each with its own resource path. For example if you have Service1, Service2 and Service3 then in your new code base all your Service1 resources will be hosted inside /service1 path, Service2 resources inside /service2 path and so on. To do this you will simply need to modify the Path specifiers in your resource files (usually an #Path annotation).
Q: How to change all the api calls to these services since their path changed?
A: Now if you already pickup the paths to api call for these services from a config file then its great, just change the paths in your config file. Else you can actually start using this config approach, and specify something as below:
In your config file:
api-paths: {
service1: /service1/
service2: /service2/
...
}
Config Unification
You can put all your configs in a single file which most frameworks support. Another option to look at is putting separate config files for each service. For 2nd option take a look at TypeSafe Config Lib. It allows you to use multiple config files with overrides.
Note: In case codebase unification is not needed then use a reverse proxy like nginx. Its just how huge websites like google/fb work. You see a single domain which hides all the microservices behind layers of reverse proxies and a CDN.
For Auth/Login
You can do this in a servlet filter. In your config have an exclusion list, these excluded paths can be accessed without login. For example the /login path must in exclusion list so people can access the login page without login first. Now your servlet filter can implement a simple client cookie + server side session store based auth. You will need a password store as well.
The login flow will be like:
User open /login page
User enters username+password (credentials)
Server receives request for login with credentials. Server checks credentials against its own credential/password store.
If successful then server sends response back to client to set a cookie with some expiry time. If failed then send Http Unauthorised response.
Server stores the cookie in its session store as well (cookies will be stored per-client, user1+chrome=1 cookie, user1+firefox=another cookie, user2+any=another set of cookies)
In further requests the client sends the cookie and server (the servlet filter) verifies against its session store. If verification passes then server allows the api call to work.
If cookie expired or no cookie in request then redirect user to /login. Continue from step-1.
Note: Always hash your credentials on client end before sending on network. On server side store only hashed credentials, no raw text passwords. Also if security is paramount then look at salting your credentials as well.
I think a good aproach for this is to have a Look at netflix technology Stack. There is a project called zuul which Acts as reverse proxy. This proxy can route incoming requests to your underlying Services. This proxy can be the frontdoor to your services where every request only can pass throu if it is authenticated.
Hope this will help a bit.

how to set the parameter targetURi dynamically in HTTP Proxy Servlet

Good morning, I decided to create a http proxy servlet because I'm in a network where almost all pages are blocked, there is a firewall that blocks almost all called fortinet.
My idea is to use a server that I have which is not blocked, but on that server only have installed an archive of web applications (glassfish) and want to create a web application that serves me as an intermediary between the pages you wish to visit and my pc and thus navigate freely without restrictions.
So far I have used the HTTP-Proxy-Servlet project
The problem is: apparently only connects to a single web that previously we configure the web.xml file with the parameter targetUri
<init-param>
<param-name>targetUri</param-name>
<param-value>http://solrserver:8983/solr</param-value>
</init-param>
How to change this parameter dynamically and navigate as a common and current online proxy?
To implement a "real" proxy (not just a "fixed URL" one), you need to use the getRequestURL method to get the real URL which was requested.
For example, in HTTP-Proxy-Servlet, when he writes:
String proxyRequestUri = rewriteUrlFromRequest(servletRequest);
You can write:
String proxyRequestUri = servletRequest.getRequestURL().toString();
I'm not saying that's the only change you'll have to make, but it's a start.
Alternatively, you could reconstruct the URL using the other getters from the request:
getScheme (http, https etc)
getServerName
getServerPort (which might be 80)
getRequestURI
getQueryString or getParameterNames / getParameterValues
(For some reason, when you type "java proxy servlet" into Google, the first result that comes up is HTTP-Proxy-Servlet. However it's not actually that useful IMO, because it only directs to a fixed URL as you mentioned.)

Explicitly set JSESSIONID

So, I'm in the middle of building an application where I want the user to be able to send a link to another user and work on the same data. There is little need to persist the data for more than 15 minutes and I want the application to not have to rely on a database.
I have a few variables which I am currently storing in a HttpSession.
Ideally I'd like to be able to set a parameter "sid" in the URL, and use that to set the session ID on the second client's browser - the one that's received a link with the SID.
Unfortunately, there seems to be no way to change the SID of a current session once it's been set up.
The only solution I've come up with so far is referring to the doGet() with a HttpPost.setHeader("Cookie", "JSESSIONID="+ getSessionId()) method, and getting the data with a specific session that way, but this seems pretty clunky.
Any suggestions?
EDIT
This has seemingly turned into a discussion about the wisdom of setting two users up to have the same session so session vars may be kept the same. Note that a non-db, ie light weight solution was what I was looking for. PHP allows you to arbitrarily set a session ID to do this, but I'm deploying to Tomcat in this instance. Something which allows lightweight sharing of a few parameters, that's it...
What I've done, then, is to set context vars using context.setAttribute(). Ugly as sin, but all I can come up with, unless anyone has any better ideas.
This approach has some security issues because you are simulating [session hijacking] with it 1:
In computer science, session hijacking, sometimes also known as cookie
hijacking is the exploitation of a valid computer session—sometimes
also called a session key—to gain unauthorized access to information
or services in a computer system. In particular, it is used to refer
to the theft of a magic cookie used to authenticate a user to a remote
server. It has particular relevance to web developers, as the HTTP
cookies used to maintain a session on many web sites can be easily
stolen by an attacker using an intermediary computer or with access to
the saved cookies on the victim's computer (see HTTP cookie theft).
Better approach is to set your data in a way that both users can approach it from their sessions. If you are using single server you can do that with some global data within a server. In clustered or cloud environments you'll need some common storage for that (ie. database, global cache, etc.)
EDIT
You are on a right track to share data among two users with different sessions.
There is one context per "web application" per Java Virtual Machine
where an attribute allows a servlet container to give the servlet
additional information.
Attributes are meant to be used to share data inside container among servlets of the same web application.
For clusters:
In the case of a web application marked "distributed" in its
deployment descriptor, there will be one context instance for each
virtual machine. In this situation, the context cannot be used as a
location to share global information (because the information won't be
truly global). Use an external resource like a database instead.

How to transfer session from one Tomcat server to another?

We have a Tomcat server for a web shop, and we need to transfer the user to another (secure) server when he/she logs in. Here's a detailed explanation:
1) We have two Tomcat servers: one 'regular' (HTTP) and one secure (HTTPS)
2) Users initially visit the regular server
3) When they log in, we need to get their log in data, as well as the information about what page they were currently on (or were trying to see), pass it to the secure server and do the actual login; for instance, a non-logged in user sees a list of products, clicks 'BUY' and a popup is displayed, asking the user to log in; the user enters his/hers credentials and these, as well as the information about what product he wants to buy, are passed to the secure server; the secure server receives these, performs the login and displays the requested product to the user
How could this be done? Please note the following:
1) We've tried doing it with cookies, but we've decided not to go that way
2) Persisting the session to a database and then having the secure server fetch it is also not an option
Are there any other ways? We were thinking about creating an object and then passing it as a HTTP POST parameter, but I'm not sure how this could be done (I've been given the task to finish it).
For what it's worth, the technologies we use are Tomcat server, Wicket, Spring, iBatis and MySQL.
Thanks in advance :)
If you want to share the session between different Tomcat instances, you could configure them to work as a cluster with session replication: http://tomcat.apache.org/tomcat-7.0-doc/cluster-howto.html
Then, you could configure an Apache HTTP Server to work as a load balancer, making sure that HTTP requests go to server 1 and HTTPS requests go to server 2.
But, you could also have only one Tomcat instance (or N identical instances) configured to handle both HTTP and HTTPS, and ensure the secure access with standard (...<transport-guarantee>CONFIDENTIAL</transport-guarantee>... in web.xml) or framework-specific configuration.
Not sure if I'm getting the gist of what you want but you could have the "pop-up" be a page served from the secure application to a protected URL. That would cause the authentication to occur at the secure server and you could go from there. For example, if the unsecured product page is on www.domain.com/browse/id1, then the "buy" button would open a pop-up to secure.domain.com/buy/id1, causing the authentication while transmitting the product id on the URL.

Categories

Resources