HttpClient 4.3 set source port - apache-httpclient-4.x

I am using HttpClient 4.3. I would like to set source port (or local port) for each request. I didn't see any method on HttpClient or HttpGet class. On the Server side, we have written security code (kind of whitelist IP with port number) to check incoming request ip and port number (this is all within intranet with static ips).

RequestConfig requestConfig = RequestConfig.custom()
.setLocalAddress(InetAddress.getByAddress(new byte[] {127, 0, 0, 1}))
.build();
HttpGet httpGet = new HttpGet("/");
httpGet.setConfig(requestConfig);
Correction:
Explicit setting of local ports is not supported by HttpClien 4.x

Related

Apache HttpClient 5.1 bypass SSL Verification

I have configured CloseableHttpAsyncClient as mentioned below
public CloseableHttpAsyncClient closeableHttpAsyncClient(){
HttpAsyncClientBuilder clientBuilder = HttpAsyncClients.custom();
final PoolingAsyncClientConnectionManager connManager = new PoolingAsyncClientConnectionManager();
connManager.setMaxTotal(10);
clientBuilder.setConnectionManager(connManager);
clientBuilder.setRedirectStrategy(DefaultRedirectStrategy.INSTANCE);
CloseableHttpAsyncClient closeableHttpAsyncClient = clientBuilder.build();
return closeableHttpAsyncClient;
}
I want to bypass SSL verification. I have tried to check different configurations but didn't find the solution for the same.
One can set up a custom TLS context and use it with the default TLS strategy as described here:
https://github.com/apache/httpcomponents-client/blob/5.1.x/httpclient5/src/test/java/org/apache/hc/client5/http/examples/AsyncClientCustomSSL.java
In this particular example the connection manager has been configured to trust all certificates with the CN equal to httpbin.org in addition to standard CAs. One can choose a different stratefgy or trust all certificates indiscriminately, though the latter is STONGLY discouraged.
final SSLContext sslcontext = SSLContexts.custom()
.loadTrustMaterial(new TrustStrategy() {
#Override
public boolean isTrusted(
final X509Certificate[] chain,
final String authType) throws CertificateException {
// Trust all certs with CN equal `httpbin.org`
final X509Certificate cert = chain[0];
return "CN=httpbin.org".equalsIgnoreCase(cert.getSubjectDN().getName());
}
})
.build();
final TlsStrategy tlsStrategy = ClientTlsStrategyBuilder.create()
.setSslContext(sslcontext)
.build();
final PoolingAsyncClientConnectionManager cm = PoolingAsyncClientConnectionManagerBuilder.create()
.setTlsStrategy(tlsStrategy)
.build();

java.net.ConnectException: Connection refused: connect. Data Grip [duplicate]

I'm trying to implement a TCP connection, everything works fine from the server's side but when I run the client program (from client computer) I get the following error:
java.net.ConnectException: Connection refused
at java.net.PlainSocketImpl.socketConnect(Native Method)
at java.net.PlainSocketImpl.doConnect(PlainSocketImpl.java:351)
at java.net.PlainSocketImpl.connectToAddress(PlainSocketImpl.java:213)
at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:200)
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:432)
at java.net.Socket.connect(Socket.java:529)
at java.net.Socket.connect(Socket.java:478)
at java.net.Socket.<init>(Socket.java:375)
at java.net.Socket.<init>(Socket.java:189)
at TCPClient.main(TCPClient.java:13)
I tried changing the socket number in case it was in use but to no avail, does anyone know what is causing this error & how to fix it.
The Server Code:
//TCPServer.java
import java.io.*;
import java.net.*;
class TCPServer {
public static void main(String argv[]) throws Exception {
String fromclient;
String toclient;
ServerSocket Server = new ServerSocket(5000);
System.out.println("TCPServer Waiting for client on port 5000");
while (true) {
Socket connected = Server.accept();
System.out.println(" THE CLIENT" + " " + connected.getInetAddress()
+ ":" + connected.getPort() + " IS CONNECTED ");
BufferedReader inFromUser = new BufferedReader(
new InputStreamReader(System.in));
BufferedReader inFromClient = new BufferedReader(
new InputStreamReader(connected.getInputStream()));
PrintWriter outToClient = new PrintWriter(
connected.getOutputStream(), true);
while (true) {
System.out.println("SEND(Type Q or q to Quit):");
toclient = inFromUser.readLine();
if (toclient.equals("q") || toclient.equals("Q")) {
outToClient.println(toclient);
connected.close();
break;
} else {
outToClient.println(toclient);
}
fromclient = inFromClient.readLine();
if (fromclient.equals("q") || fromclient.equals("Q")) {
connected.close();
break;
} else {
System.out.println("RECIEVED:" + fromclient);
}
}
}
}
}
The Client Code:
//TCPClient.java
import java.io.*;
import java.net.*;
class TCPClient {
public static void main(String argv[]) throws Exception {
String FromServer;
String ToServer;
Socket clientSocket = new Socket("localhost", 5000);
BufferedReader inFromUser = new BufferedReader(new InputStreamReader(
System.in));
PrintWriter outToServer = new PrintWriter(
clientSocket.getOutputStream(), true);
BufferedReader inFromServer = new BufferedReader(new InputStreamReader(
clientSocket.getInputStream()));
while (true) {
FromServer = inFromServer.readLine();
if (FromServer.equals("q") || FromServer.equals("Q")) {
clientSocket.close();
break;
} else {
System.out.println("RECIEVED:" + FromServer);
System.out.println("SEND(Type Q or q to Quit):");
ToServer = inFromUser.readLine();
if (ToServer.equals("Q") || ToServer.equals("q")) {
outToServer.println(ToServer);
clientSocket.close();
break;
} else {
outToServer.println(ToServer);
}
}
}
}
}
This exception means that there is no service listening on the IP/port you are trying to connect to:
You are trying to connect to the wrong IP/Host or port.
You have not started your server.
Your server is not listening for connections.
On Windows servers, the listen backlog queue is full.
I would check:
Host name and port you're trying to connect to
The server side has managed to start listening correctly
There's no firewall blocking the connection
The simplest starting point is probably to try to connect manually from the client machine using telnet or Putty. If that succeeds, then the problem is in your client code. If it doesn't, you need to work out why it hasn't. Wireshark may help you on this front.
You have to connect your client socket to the remote ServerSocket. Instead of
Socket clientSocket = new Socket("localhost", 5000);
do
Socket clientSocket = new Socket(serverName, 5000);
The client must connect to serverName which should match the name or IP of the box on which your ServerSocket was instantiated (the name must be reachable from the client machine). BTW: It's not the name that is important, it's all about IP addresses...
I had the same problem, but running the Server before running the Client fixed it.
One point that I would like to add to the answers above is my experience-
"I hosted on my server on localhost and was trying to connect to it through an android emulator by specifying proper URL like http://localhost/my_api/login.php . And I was getting connection refused error"
Point to note - When I just went to browser on the PC and use the same URL (http://localhost/my_api/login.php) I was getting correct response
so the Problem in my case was the term localhost which I replaced with the IP for my server (as your server is hosted on your machine) which made it reachable from my emulator on the same PC.
To get IP for your local machine, you can use ipconfig command on cmd
you will get IPv4 something like 192.68.xx.yy
Voila ..that's your machine's IP where you have your server hosted.
use it then instead of localhost
http://192.168.72.66/my_api/login.php
Note - you won't be able to reach this private IP from any node outside this computer. (In case you need ,you can use Ngnix for that)
I had the same problem with Mqtt broker called vernemq.but solved it by adding the following.
$ sudo vmq-admin listener show
to show the list o allowed ips and ports for vernemq
$ sudo vmq-admin listener start port=1885 -a 0.0.0.0 --mountpoint /appname --nr_of_acceptors=10 --max_connections=20000
to add any ip and your new port. now u should be able to connect without any problem.
Hope it solves your problem.
Hope my experience may be useful to someone. I faced the problem with the same exception stack trace and I couldn't understand what the issue was. The Database server which I was trying to connect was running and the port was open and was accepting connections.
The issue was with internet connection. The internet connection that I was using was not allowed to connect to the corresponding server. When I changed the connection details, the issue got resolved.
In my case, I gave the socket the name of the server (in my case "raspberrypi"), and instead an IPv4 address made it, or to specify, IPv6 was broken (the name resolved to an IPv6)
In my case, I had to put a check mark near Expose daemon on tcp://localhost:2375 without TLS in docker setting (on the right side of the task bar, right click on docker, select setting)
i got this error because I closed ServerSocket inside a for loop that try to accept number of clients inside it (I did not finished accepting all clints)
so be careful where to close your Socket
I had same problem and the problem was that I was not closing socket object.After using socket.close(); problem solved.
This code works for me.
ClientDemo.java
public class ClientDemo {
public static void main(String[] args) throws UnknownHostException,
IOException {
Socket socket = new Socket("127.0.0.1", 55286);
OutputStreamWriter os = new OutputStreamWriter(socket.getOutputStream());
os.write("Santosh Karna");
os.flush();
socket.close();
}
}
and
ServerDemo.java
public class ServerDemo {
public static void main(String[] args) throws IOException {
System.out.println("server is started");
ServerSocket serverSocket= new ServerSocket(55286);
System.out.println("server is waiting");
Socket socket=serverSocket.accept();
System.out.println("Client connected");
BufferedReader reader=new BufferedReader(new InputStreamReader(socket.getInputStream()));
String str=reader.readLine();
System.out.println("Client data: "+str);
socket.close();
serverSocket.close();
}
}
I changed my DNS network and it fixed the problem
You probably didn't initialize the server or client is trying to connect to wrong ip/port.
Change local host to your ip address
localhost
//to you local ip
192.168.xxxx
I saw the same error message ""java.net.ConnectException: Connection refused" in SQuirreLSQL when it was trying to connect to a postgresql database through an ssh tunnel.
Example of opening tunel:
Example of error in Squirrel with Postgresql:
It was trying to connect to the wrong port. After entering the correct port, the process execution was successful.
See more options to fix this error at: https://stackoverflow.com/a/6876306/5857023
In my case, with server written in c# and client written in Java, I resolved it by specifying hostname as 'localhost' in the server, and '[::1]' in the client. I don't know why that is, but specifying 'localhost' in the client did not work.
Supposedly these are synonyms in many ways, but apparently, not not a 100% match. Hope it helps someone avoid a headache.
For those who are experiencing the same problem and use Spring framework, I would suggest to check an http connection provider configuration. I mean RestTemplate, WebClient, etc.
In my case there was a problem with configured RestTemplate (it's just an example):
public RestTemplate localRestTemplate() {
Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("localhost", <some port>));
SimpleClientHttpRequestFactory clientHttpReq = new SimpleClientHttpRequestFactory();
clientHttpReq.setProxy(proxy);
return new RestTemplate(clientHttpReq);
}
I just simplified configuration to:
public RestTemplate restTemplate() {
return new RestTemplate(new SimpleClientHttpRequestFactory());
}
And it started to work properly.
There is a service called MySQL80 that should be running to connect to the database
for windows you can access it by searching for services than look for MySQL80 service and make sure it is running
It could be that there is a previous instance of the client still running and listening on port 5000.

enforce https request on a non https website - Mixed Content error in chrome

This might be a weird case, and feel free to let me know if there is better way in general.
So I have an application with a load balancer. The load balancer takes in HTTPs only traffic. So far so good.
The load balancer then sends it as HTTP to my asp.netcore.
What it implies :
Although the access to the website is in Https, the asp.netcore app doesn't know about it.
I only specify it as HTTPs in Development environment as I have my cookies in HTTPS only
But that gives me this problem :
Mixed Content: The page at 'pagePath' was loaded over HTTPS, but
requested an insecure manifest 'path/site.webmanifest'. This request
has been blocked; the content must be served over HTTPS.
Here is my startup
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseHttpsRedirection();
}
else
{
app.UseHsts();
}
app.UseStaticFiles();
app.UseCookiePolicy();
app.UseAuthentication();
app.UseExceptionHandler("/error/500");
app.UseMiddleware<WebRequestLoggerMiddleWare>();
app.UseMiddleware<UserTimeZoneMiddleWare>();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
}
And my cookie policy, still in statup.cs
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie(options =>
{
options.LoginPath = new PathString("/account/login/");
options.AccessDeniedPath = new PathString("/account/forbidden/");
options.SlidingExpiration = true;
options.ExpireTimeSpan = TimeSpan.FromHours(cookieSettings.CookieExpirationInHours);
options.Cookie.SecurePolicy = CookieSecurePolicy.Always;
options.Cookie.HttpOnly = true;
});
What would be the best way to make sure the webmanifest is requested through HTTPS ?
Should I just force the whole website to be HTTPS and route traffic from the LB as https? That's one way, but it shouldn't be necessary...
The traffic between your reverse proxy and your ASP.NET Core application doesn't have to be encrypted via https, but two conditions have to be met so your ASP.NET Core application knows if the original HTTP Request was came over https or http.
Your reverse proxy has to Send the correct headers with the original protocol and IP of the original host. The default headers for that are X-Forwarded-For for the remote IP and X-Forwarded-Proto for the protocol
The forwarded headers middleware is set up by default when running on IIS and (according to the docs) needs to be enabled for other hosting scenarios.
The documentation can be read under Configure ASP.NET Core to work with proxy servers and load balancers.
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.Configure<ForwardedHeadersOptions>(options =>
{
options.ForwardedHeaders =
ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
});
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseForwardedHeaders();
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
}
app.UseStaticFiles();
// In ASP.NET Core 1.x, replace the following line with: app.UseIdentity();
app.UseAuthentication();
app.UseMvc();
}
If your proxy names headers differently than X-Forwarded-For, X-Forwarded-Proto and X-Forwarded-Host, you can use the ForwardedForHeaderName, ForwardedProtoHeaderName and ForwardedHostHeaderName properties on ForwardedHeadersOptions to change it.
Additionally your Startup class should look like this
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseHsts();
}
// redirect to Https
app.UseHttpsRedirection();
as per official examples and to ensure the user is redirected to http on his/her first visit, HSTS should handle consecutive requests

authentication AWS method Rest DSL

I have a question regarding Restful services
I need to upload CSV files to an AWS server. I am registered with account.
First I need to obtain an access token and use that to upload the files. I have not coded anything yet, trying to understand the best approach, I so hope to use Camel-Rest-DSL. It is required to communicate with JSON. But, the authentication part has me stuck, I’m pretty sure it uses OAuth2 auth, RestFul web service and JSON, this should just be a client, I was looking at WSS4J for JAX-RS OAuth2 but I don’t know.
I’ve done it with postman, this is the scenario. The username and password are fictional
*Get Access Token
uses POST verb
requires Token Request URL
uses Basic Auth requires Username = Client ID of tenant ( needs to be encoded base64 )
HEADER parm Content-Type = x-www-form-urlencoded
Content-Type': 'application/x-www-form-urlencoded',
'Authorization': 'Basic ' + encoded Client ID
Access Token body - grant_type, username, password
Body = username = 5c0642fe-a495-44db-93f7-67034556fa2c061_ingestor
password = 154f0252d166f27b5e21ef171b03212a79f41a0daf3
grant_type = password
#returns the access_token as JSON
POST or upload files
uses POST verb
requires Ingestion URL UploadURL
UploadURL=https://apm-ts-query-svc-prd.app-api.aws-usw02-pr.something.io/v2/time_series/
UploadFolder=upload
headers =
key Authentication "Bearer + access Token" (from request access token above)
key Tenant = TenantUUID
key X-GE-CsvFormat = ODB
# Body
form-data
key file=file
# POST DATA
headers content-type application/json
authorization: "" + token
tenant: "" + tenant
My environment
Jboss Fuse 6.3-310
Karaf version 2.4.0.redhat-630310
JVM
Java Virtual Machine Java HotSpot(TM) 64-Bit Server VM version 25.162-
b12
Version 1.8.0_162
Vendor Oracle Corporation
Operating system
Name Linux version 2.6.32-696.20.1.el6.x86_64
I can't use OAuth2/SAML assertions so I will simply request a token and cache it and use it later. this is my test code
#Override
public void configure() throws Exception {
//Configure the Rest Web Service Component transport to use a REST implementation
restConfiguration() //Configures the REST DSL to use a specific REST implementation
.component("jetty") //Specifies the Camel component to use as the REST transport
.host("localhost") //The hostname to use for exposing the REST service
.port("8282") //The port number to use for exposing the REST service JMX tooling
.scheme("https") //The protocol to use for exposing the REST service
.contextPath("/oauth/token") //Sets a leading context path for the REST services
.bindingMode(RestBindingMode.json) //Enables binding mode for JSON
.jsonDataFormat("json-jackson") //Specifies the component that Camel uses to implement the JSON data format
.dataFormatProperty("prettyPrint", "true"); //set arbitrary properties on the underlying data format component
//Configure the Rest Endpoint
rest("/oauth") //Defines a service using the REST DSL. Each of the verb clauses are terminated by a to() keyword,
//which forwards the incoming message to an endpoint
.post("/token")
.produces("application/json")
.consumes("application/json")
.type(TokenEntities.class)
.route()
.routeId("Get Auth Token Route")
.autoStartup(true)
.id("Get Auth Token Service")
.description("Get Authorization Token")
.process(new UAARequestTokenProcessor())
.to("https://d1e53858-2903-4c21-86c0-95edc7a5cef2.pager-uaa.run.aws-usw02-pr.ice.pager.io/oauth/token")
.to("log:logger?showBody=true")
.to("direct:accessToken")
.endRest();
//Define the Route - from() Defines a regular Camel route.
from("direct:accessToken").to("log:logger?showBody=true"); }
public class UAARequestTokenProcessor implements Processor {
private static final Logger LOG = LoggerFactory.getLogger(UAARequestTokenProcessor.class);
private String clientId = "myClientID";
private String userName = "myUserName";
private String password = "myPassword";
#Override
public void process(Exchange exchange) throws Exception {
LOG.info("Processing UAA token request for " + clientId + " and " + userName);
Message msg = exchange.getOut(); //create outbound message exchange
StringBuilder authHeader = new StringBuilder("Basic ");
authHeader.append(Base64.getEncoder().encodeToString((clientId + ":").getBytes("UTF_8")));
String body = String.format("grant_type=password&username=%s&password=%s",
URLEncoder.encode(userName, "UTF-8"), //Translates a string into x-www-form-urlencoded format
URLEncoder.encode(password, "UTF-8"));
msg.setHeader(Exchange.CONTENT_TYPE, "MediaType.APPLICATION_FORM_URLENCODE");
msg.setHeader("Authorization", authHeader.toString());
msg.setBody(body);
}
}

JavaMail SMTPSendFailedException

I am writing a bulk email program using the JavaMail api. I have a Microsoft Exhange server which I am trying to send the emails in to. When I run my program I get the following error:
**com.sun.mail.smtp.SMTPTransport.issueSendCommand(SMTPTransport.java:2057)
at com.sun.mail.smtp.SMTPTransport.finishData(SMTPTransport.java:1862)
at com.sun.mail.smtp.SMTPTransport.sendMessage(SMTPTransport.java:1100)
at javax.mail.Transport.send0(Transport.java:195)
at javax.mail.Transport.send(Transport.java:124)
at SendEmail.postMail(SendEmail.java:100)
at EmailGenerator.main(EmailGenerator.java:52)**
The part of my code trying to send the message is as follows:
Properties props = new Properties();
props.put("mail.smtp.host", email_server);
props.put("mail.transport.protocol", "smtp");
props.put("mail.smtp.auth", true);
class EmailAuthenticator extends Authenticator {
String user;
String pw;
EmailAuthenticator (String FROM, String PASSWORD)
{
super();
this.user = FROM;
this.pw = PASSWORD;
}
public PasswordAuthentication getPasswordAuthentication()
{
return new PasswordAuthentication(user, pw);
}
}
Session session = Session.getInstance(props, new EmailAuthenticator(USER, PASSWORD));
session.setDebug(debug);
System.out.println("Session created");
.. CREATED MESSAGE HERE...
Transport transport = session.getTransport("smtp");
transport.connect(exchange_server,user,password);
transport.send(msg);
transport.close();
I wonder am I missing some configuration on the Exchange server side, or is an issue with my code?
OK I figured out where I was going wrong here and am posting up the answer incase anybody else can get some value out of it. I had the following line of code:
props.put("mail.smtp.auth", true);
This was telling my application that it needed to authenticate to the SMTP server, when in fact it didnt. This was causing my application from logging into the SMTP server and sending the email and thus producing the error message. Setting this property to false or not having this line of code fixed the issue for me. This line of code is only necessary for SMTP servers that require you to login, which my Exchange server didnt.