Java HttpServletRequest Issue - java

I have a web service hosted for sharing transaction details. There are two clients connected with my web service.
User setup at my end is like below
KEJESTORE ==== 201.XXX.XX.XX
MARIOBROS ==== 81.XX.XX.XX
I get their Username and ip address of the client server for security reasons using the below method in each time when they call transaction method;
MessageContext msgCtxt = wsCtxt.getMessageContext();
HttpServletRequest req = (HttpServletRequest) msgCtxt.get(MessageContext.SERVLET_REQUEST);
String clientIp = req.getRemoteAddr();
String user = wsCtxt.getUserPrincipal().getName();
But I get results like below some times (This happens very rarely).
KEJESTORE === 81.XX.XX.XX
MARIOBROS === 201.XXX.XX.XX
I can not figure out if there is any problem with my above code which i'm using for this purpose.
Please advice.
Edit:
Method
public TranResponse sendTransaction(WebServiceContext wsCtxt, Transaction tran){
MessageContext msgCtxt = wsCtxt.getMessageContext();
HttpServletRequest req = (HttpServletRequest) msgCtxt.get(MessageContext.SERVLET_REQUEST);
String clientIp = req.getRemoteAddr();
String user = wsCtxt.getUserPrincipal().getName();
// more code
}

Related

How to change Remot Ip address from jsoup request?

I have Jsoup code and successfully send request.Also this code work fine in hide/change 'X-Forwarded-For' Header data, but i cant hide/change Remote/System Ip Address.
Client Side Code:
Document doc = Jsoup.connect("http://192.168.XX.XX:XXXX/microFin/XXXX")
.header("X-Forwarded-For", "192.168.0.1").get();
Server Side Code:
#Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String authCredentials = request.getHeader("Authorization");
String pathInfo = request.getServletPath();/////api/auth
String ip = request.getHeader("X-Forwarded-For");
String ip11 = request.getRemoteAddr();
if (ip == null) {
ip = request.getRemoteAddr();
}
System.out.println("IP-ADDRESS::" + ip);//192.168.0.1
System.out.println("IP-ADDRESS::" + ip11);//actual ip ???
If any solution for change System Ip then please help me.
You can use a VPN service to hide the IP address of the client machine. There are several software ranging from premium to paid.
My software of preference is: TunnelBear Link

session times out despite activity in an app built with Spring boot and embedded jetty

We have the following:
Java 8 web app developed with Spring Boot and embedded Jetty.
The UI for the app is built using react.
The backend exposes multiple REST APIs via Jersey.
The authentication is done using SAML with Okta as the IDP. We use spring-security-saml-core for SAML authentication.
The Java app is fronted by Nginx for SSL termination but this issue is reproducible without Nginx too.
The issue we have been noticing is that the user session times-out after the session timeout time despite user activity. Following is an excerpt of the application.properties related to session and JSESSIONID cookie:
# Session #
server.session.cookie.domain=domain.example.com
server.session.cookie.http-only=true
server.session.cookie.max-age=-1
server.session.cookie.name=JSESSIONID
server.session.cookie.path=/
server.session.cookie.secure=true
server.session.persistent=false
server.session.timeout=900
server.session.tracking-modes=cookie
# Custom #
auth.cookie-max-age=900
The cookie-mag-age above dictates the lifespan of other cookies we create to store other user details, e.g user id. Following code gets called when Okta sends back the assertion on valid auth. This is a custom class extended from SavedRequestAwareAuthenticationSuccessHandler
#Override
public void onAuthenticationSuccess(
final HttpServletRequest request,
final HttpServletResponse response,
final Authentication authentication)
throws ServletException, IOException {
HttpSession session = request.getSession(true);
Object credentials = authentication.getCredentials();
if (credentials instanceof SAMLCredential) {
SAMLCredential samlCredential = (SAMLCredential) credentials;
NameID nameId = samlCredential.getNameID();
if (nameId != null) {
String nameIdValue = nameId.getValue();
UserDetail userDetail = userManager.getUserByName(nameIdValue, false);
if(userDetail != null) {
session.setAttribute(Constants.SESSION_USERID_FIELD, userDetail.getId());
String token = csrfTokenManager.getTokenFromSession(request);
if(token == null) {
token = csrfTokenManager.generateAndSaveToken(request, response);
response.addHeader(CsrfTokenManager.TOKEN_HEADER_NAME, token);
}
Cookie idCookie = AuthUtil.createCookie(
Constants.SESSION_USERID_FIELD,
userDetail.getId(),
appConfig.getCookieMaxAge(), true);
response.addCookie(idCookie);
}
}
}
getRedirectStrategy().sendRedirect(request, response,
appConfig.getAuthSuccessRedirectUrl());
}
We call the REST APIs from Javascript using isomorphic fetch as follows:
export const fetchAllProjects = () => {
return dispatch => {
dispatch(requestAllProjects())
return fetch(`/rest/private/v1/projects`, {
credentials: 'same-origin'
})
.then(errorMessageUtil.handleErrors)
.then(response => response.json())
.then(json => dispatch(receiveAllProjects(json)))
.catch(error => errorMessageUtil.dispatchError(error, dispatch, appActions.displayBadRequestMessage))
}
}
The credentials: 'same-origin', sends all the cookies to the backend including the JESESSIONID and the other cookies set above. We have an authentication filter that checks for valid session and not sends 401
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
HttpServletResponse httpServletResponse = (HttpServletResponse) response;
HttpSession session = httpServletRequest.getSession(false);
if(session == null) {
this.sendUnauthorizedResponse(httpServletResponse);
} else {
String userIdFromCookie = null;
Cookie[] cookies = httpServletRequest.getCookies();
for(Cookie cookie : cookies) {
if(Constants.SESSION_USERID_FIELD.equals(cookie.getName())) {
userIdFromCookie = cookie.getValue();
break;
}
}
String userId = (String)session.getAttribute(Constants.SESSION_USERID_FIELD);
if(userIdFromCookie != null && userId != null
&& userId.equals(userIdFromCookie)) {
HeaderMapRequestWrapper requestWrapper = new HeaderMapRequestWrapper(httpServletRequest);
requestWrapper.addHeader(Constants.USERID_HEADER_NAME, userId);
chain.doFilter(requestWrapper, httpServletResponse);
} else {
this.sendUnauthorizedResponse(httpServletResponse);
}
}
}
I am sure, we are not doing something right because the timeout time for the session is for the inactivity.
One other question is, do calls to the REST APIs qualify as valid activity for session time-out to extend?
Found the problem with my logic. The code above tries to get the userId from the cookie and the userId from the session and then compare and if not matched, redirect the user to login.
The issue was the timeout time for the session and the cookie expiry time, auth.cookie-max-age=900, were same so even though the session was active because of activity, the cookie was getting expired and userId values didn't match.
My approach is to increase the max age of the cookie to a bigger value, so UI can keep sending the cookies with valid values and if the session really expires due to inactivity, its the userId value from the session that will be null and the user will need to re-login.

Why is the HttpServletRequest null in the MessageContext?

I am trying to get the IP Address of the client of my JAX-WS SOAP Web Service (an alternative solution is appreciated).
I am using the following code, which works on another project, however this project (integrating with Spring 3.2.4) is returning a null HttpServletRequest when I fetch it from the javax.xml.ws.WebServiceContext (the WebServiceContext is not null):
#Resource
WebServiceContext wsContext;
private String getRemoteIpAddress()
{
MessageContext context = this.wsContext.getMessageContext();
HttpServletRequest httpRequest = (HttpServletRequest) context.get(MessageContext.SERVLET_REQUEST);
String remoteIpAddress = httpRequest.getRemoteAddr();
For further clarity, this is this Web Service class looks like:
#WebService(name = "PService", targetNamespace = "http://server.ps/")
#SOAPBinding(parameterStyle = SOAPBinding.ParameterStyle.WRAPPED)
public class PSystemServiceEndpoint extends SpringBeanAutowiringSupport
Important to note, the application is running as a standalone Java application and includes a Jetty Embeeded Server.
I also use Spring WS and when I need to get IP from remote client I use this function
private String getIpRequest(){
String result = "none";
TransportContext context = TransportContextHolder.getTransportContext();
if(context != null){
HttpServletConnection connection = (HttpServletConnection)context.getConnection();
if(connection != null){
HttpServletRequest request = connection.getHttpServletRequest();
if(request != null){
result = request.getRemoteAddr();
}
}
}
return result;
}
As you can see I don't use WebServiceContext, instead I use WebServiceTemplate so I am not sure if this code is right for you, but I hope it helps.

Solrj Authentication Fails On Write Operation

Just password protected solr on Jetty server. I am able to read/access data from solr using solrj :->
HttpSolrServer solr = new HttpSolrServer("http://111.111.111:8983/solr/mysolr");
HttpClientUtil.setBasicAuth((DefaultHttpClient) solr.getHttpClient(), "admin", "akshaybhatt");
but it gives me I/O Exception as below. There are other examples on SO about authentication but I have no idea how do I use authentication in Solrj. The below error comes only when I try to update a record (and possibly add a record, not tested yet)
org.apache.solr.client.solrj.SolrServerException: IOException occured when talking to server at: http://111.111.111.138:8983/solr/mysolrcore
at org.apache.solr.client.solrj.impl.HttpSolrServer.request(HttpSolrServer.java:507)
at org.apache.solr.client.solrj.impl.HttpSolrServer.request(HttpSolrServer.java:199)
at org.apache.solr.client.solrj.request.AbstractUpdateRequest.process(AbstractUpdateRequest.java:118)
at org.apache.solr.client.solrj.SolrServer.add(SolrServer.java:116)
at org.apache.solr.client.solrj.SolrServer.add(SolrServer.java:102)
at UpdateSolrTesting.AddToSolr(UpdateSolrTesting.java:228)
at UpdateSolrTesting.performaction(UpdateSolrTesting.java:141)
at UpdateSolrTesting.main(UpdateSolrTesting.java:101)
Caused by: org.apache.http.client.ClientProtocolException
at org.apache.http.impl.client.AbstractHttpClient.doExecute(AbstractHttpClient.java:867)
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:82)
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:106)
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:57)
at org.apache.solr.client.solrj.impl.HttpSolrServer.request(HttpSolrServer.java:395)
... 7 more
Caused by: org.apache.http.client.NonRepeatableRequestException: Cannot retry request with a non-repeatable request entity.
at org.apache.http.impl.client.DefaultRequestDirector.tryExecute(DefaultRequestDirector.java:660)
at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:486)
at org.apache.http.impl.client.AbstractHttpClient.doExecute(AbstractHttpClient.java:863)
... 11 more
It is happening only because authentication parameter is not being sent while doing POST or DELETE calls, so so solution is you need to fix that in your http client
I am using solr 6.2.0 and its corresponding java client
So i created a new SolrHttp client which looks like below
public class TEHttpSolrClient extends HttpSolrClient {
private static final String UTF_8 = StandardCharsets.UTF_8.name();
public TEHttpSolrClient(String baseURL) {
super(baseURL);
}
#Override
public NamedList<Object> request(final SolrRequest request, String collection) throws SolrServerException, IOException {
ResponseParser responseParser = request.getResponseParser();
if (responseParser == null) {
responseParser = parser;
}
return request(request, responseParser, collection);
}
public NamedList<Object> request(final SolrRequest request, final ResponseParser processor, String collection)
throws SolrServerException, IOException {
HttpRequestBase method = createMethod(request, collection);
String userPass = "<username>:<password>";
String encoded = Base64.byteArrayToBase64(userPass.getBytes(UTF_8));
// below line will make sure that it sends authorization token every time in all your requests
method.setHeader(new BasicHeader("Authorization", "Basic " + encoded));
return executeMethod(method, processor);
}
}
Also to call the client you should call it like below
private static SolrClient solr = new TEHttpSolrClient.Builder("<solr core url>").build();
What you need is called "preemptive authentication". This tells the http client to authenticate on the first call to the url. The default behaviour is to send two request, when basic authentication is used. This might fail, as in your case, when the entity in the http call is not reusable.
Luckyly solr allready has a build in way to enable preemptive authentication by using a different client building factory for SolrHttpClientBuilder.
String userName = "someUserName";
String password = "secretPassword";
ModifiableSolrParams params = new ModifiableSolrParams();
params.set(HttpClientUtil.PROP_BASIC_AUTH_USER, userName);
params.set(HttpClientUtil.PROP_BASIC_AUTH_PASS, password);
// set the params for authentication here
PreemptiveBasicAuthClientBuilderFactory.setDefaultSolrParams(params);
PreemptiveBasicAuthClientBuilderFactory preemptiveBasicAuthClientBuilderFactory = new PreemptiveBasicAuthClientBuilderFactory();
// create a new client builder from the preemptive client builder factory
SolrHttpClientBuilder httpClientBuilder = preemptiveBasicAuthClientBuilderFactory
.getHttpClientBuilder(Optional.empty());
// set the client builder to be used by the clientUtil
HttpClientUtil.setHttpClientBuilder(httpClientBuilder);
// the params need to be passed here too
CloseableHttpClient httpAuthClient = HttpClientUtil.createClient(params);
// now build the solr client with the special http client
Builder solrClientBuilder = new HttpSolrClient.Builder(solrClientConfig.getSolrUrl()).withHttpClient(httpAuthClient);
// create solr client
SolrClient client = solrClientBuilder.build();
Remember not to set the authorization params at the request level, otherwise the preemptive auth won't work.
Similar question asked already, you can look at the below links to get some idea.
Solr - instantiate HttpSolrServer with Httpclient
Solr Change CommonsHttpSolrServer To HttpSolrServer

logging out old session and and continuing in new session with same user ID and Password in Java Web Apps

Suppose a person is logged in with user id and password in an app. Now with same user id and password he is trying to log without logging out from first session. I want to make it that it willlog out from and first session and continue with new one automatically.
Struts2, JSP , Java are technologies , i m using for my apps.
Problems facing
IE 8 giving same session id in same machine if we open in new tab or window. Not able to differentiate between different login from same machine.
How to set own session id?
Banking application like SBI sites and all works like that only , how does it work real time?
I want to replicate same thing like SBI bank sites work on online transaction. Send message session out in first window if you open again in new window
Please let me know how does this logging part in details.
Thanks.
This is my filter
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
System.out.println("FirstFilter : In filter doFilter before doFilter...");
HttpServletRequest req = (HttpServletRequest) request ;
HttpServletResponse res = (HttpServletResponse) response ;
HttpSession session = req.getSession(false);
String userId=req.getParameter("username");
String password=req.getParameter("password");
System.out.println(" : : " + req.getParameter("username")) ;
System.out.println(" : " + req.getServletPath());
LoggedInUserVO userProfVOSession = null ;
if(session != null) {
String sessionId=session.getId();
userProfVOSession = (LoggedInUserVO)session.getAttribute("LoggedInUser") ;
//check for login id password and session for single user sign in
if(null!=userProfVOSession){
if(userProfVOSession.getUserName().equalsIgnoreCase(userId) && userProfVOSession.getUserPassword().equals(password) && userProfVOSession.getSessionId().equals(sessionId)){
//do nothing
}
else{
System.out.println("in duplicate");
}
}
}
if(userProfVOSession == null) {
if("/populatelogin.action".equals(req.getServletPath()) || "/login.action".equals(req.getServletPath())||"/images/Twalk-Logo-4-green.png".equals (req.getServletPath())||"css/twalk.css".equals( req.getServletPath() )) {
chain.doFilter(req, res) ;
} else {
req.getRequestDispatcher("Entryindex.jsp").forward(req, res) ;
}
} else {
chain.doFilter(req, res) ;
}
Basically your requirement leads to web security vulnerability.If a person is already logged in, then his session must be active.Now the scenario is like this:
If you tries to login again with the same credentials, he wll be automatically logged in.
If you want to kill the old session for every login, then what you need to do is , you need to get a new session every time when you login, so your old session will be expired.You can achieve this by just writing a filter.In this filter check whether the user is already associated with a session or not, if yes, then invalidate his current session and start new one.This will solve the issue of multiple login attempts.
Remember that when a session is initiated, then the server is sending a cookie back to the user.Henceforth for every subsequent request made, this cookie will be transmitted to the server. Even if that if you open multiple tabs in browsers, this same cookie only is sent back to the server.
Hope I understood this.

Categories