How to use proxies library in flutter? - flutter

I want to create an Android app that connects to a proxy by button clicked and I'd like to know what should do to make this event?
My proxy needs(password, username, host, port).
I would be appreciated if you help me with this problem .

Add DIO settings like this
String proxy = '<IP>:<PORT>'; //eg 192.168.1.1:8080
var credentials = HttpClientBasicCredentials(<USERNAME>, <PASSWORD>);
bool isProxyChecked = true;
(dio.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate =
(client) {
client.badCertificateCallback = (X509Certificate cert, String host, int port) {
return isProxyChecked && Platform.isAndroid;
};
client.findProxy = (url) {
return isProxyChecked ? 'PROXY $proxy' : 'DIRECT';
};
client.addProxyCredentials(<PROXY_IP>, <PORT>, 'main', credentials);
};

Related

Inspect WebSocket packages with Charles proxy in Flutter app

I'm developing mobile application using Flutter/Dart. What I need is to debug/test my application's network traffic with Charles proxy/Fiddler. It's easy to inspect http requests/responses in dart/flutter using Charles proxy. We only need to tell HttpClient an address of proxy server (IP address of machine where Charles is installed) like this:
final client = HttpClient();
client.findProxy = (uri) {
String proxy = '1.2.3.4:8888';
return "PROXY $proxy;";
};
client.badCertificateCallback =
((X509Certificate cert, String host, int port) => Platform.isAndroid);
But how can I debug WebSocket traffic created via
WebSocket.connect('wss://server_address');? WebSocket doesn't have any api for setting proxy settings and I couldn't find anything on forums.
That being said, I already did such things in the past in another mobile app written on C# and it was pretty easy.
Figured it out. There are actually multiple ways to do that:
Global Proxy settings:
class ProxiedHttpOverrides extends HttpOverrides {
String _proxy;
ProxiedHttpOverrides(this. _proxy);
#override
HttpClient createHttpClient(SecurityContext? context) {
return super.createHttpClient(context)
..findProxy = (uri) {
return _proxy.isNotEmpty ? "PROXY $_proxy;" : 'DIRECT';
}
..badCertificateCallback = (X509Certificate cert, String host, int port) => Platform.isAndroid;
}
}
void main() {
String proxy = '1.2.3.4:8888';
HttpOverrides.global = new ProxiedHttpOverrides(proxy);
runApp(MyApp());
}
Custom HttpClient passed into WebSocket.connect
HttpClient client = HttpClient();
client.findProxy = (uri) => "PROXY $proxy;";
client.badCertificateCallback = (X509Certificate cert, String host, int port) => Platform.isAndroid;
WebSocket.connect(url, customClient: client);
Manual way: We need to upgrade to WebSocket using simple HttpClient with specified proxy settings. In that case we will be able to inspect WebSocket traffic in Charles/Fiddler.
Future<WebSocket> createProxySocket() async {
String url = 'https://echo.websocket.org:443';//address must start from http(s)://, not from ws(s)://, as we are connecting using http
String proxy = '1.2.3.4:8888';//your machine address (or localhost if debugging on the same machine)
Random r = new Random();
String key = base64.encode(List<int>.generate(8, (_) => r.nextInt(255)));
HttpClient client = HttpClient();
client.findProxy = (uri) => "PROXY $proxy;";
client.badCertificateCallback = (X509Certificate cert, String host, int port) => Platform.isAndroid;
Uri uri = Uri.parse(url);
HttpClientRequest request = await client.getUrl(uri);
request.headers.add('Connection', 'upgrade');
request.headers.add('Upgrade', 'websocket');
request.headers.add('Sec-WebSocket-Version', '13');
request.headers.add('Sec-WebSocket-Key', key);
HttpClientResponse response = await request.close();
Socket socket = await response.detachSocket();
return WebSocket.fromUpgradedSocket(socket, serverSide: false);
}

MQTTNET connection

I have written this application to use mqttnet library but connection failed.
How is it possible to get mqttnet with a trace?
Do you notice something wrong with the connection?
Here my code
var mqttClient = new MqttFactory(new MQTTnet.Diagnostics.MqttNetLogger("MyCustomId")).CreateMqttClient();
var caCert = X509Certificate.CreateFromCertFile("C:\\ca.crt");
var clientCert = new X509Certificate2("C:\\certificate.pfx", "uno");
var options = new MqttClientOptionsBuilder()
.WithCredentials("ut", "pwd")
.WithTcpServer("mydns", 8883)
.WithTls(new MqttClientOptionsBuilderTlsParameters
{
UseTls = true,
SslProtocol = System.Security.Authentication.SslProtocols.Tls13,
Certificates = new List<X509Certificate>()
{
caCert, clientCert
},
CertificateValidationCallback = (X509Certificate x, X509Chain y, SslPolicyErrors z, IMqttClientOptions o) =>
{
return true;
}
})
.Build();
MQTTnet.Client.Connecting.MqttClientAuthenticateResult r=await mqttClient.ConnectAsync(options, CancellationToken.None);
Thank you
any help would be appreciated
I have replaced "CreateMqttClient" with "CreateManagedMqttClient" and modified the subsequent part of the code and all has worked

MQTT certificate-based authentication in flutter web and mobile

I am trying to use MQTT in a Flutter project to test the prototype. And I am using custom certificate-based authentication.
I am using mqtt_client package.
before connect SecurityContext giving this error in web Unsupported operation: default SecurityContext getter
below is my sample code
try {
SecurityContext securityContext =
SecurityContext(withTrustedRoots: false);
securityContext.setTrustedCertificatesBytes(caCertificate);
securityContext.useCertificateChainBytes(caCertificate);
securityContext.setClientAuthoritiesBytes(clientCertificate,
password: String.fromCharCodes(privateKey));
} catch (e) {
print(e);
}
_client = MqttClient('m.test.com', _identifier);
_client.port = 8883;
_client.keepAlivePeriod = 20;
_client.onDisconnected = onDisconnected;
_client.secure = true;
//_client.securityContext = securityContext;
_client.onBadCertificate = ((X509Certificate cert) => false);
_client.logging(on: true);```
this worked for me but I don't understand what (dynamic a) is doing ... perhaps someone can explain it in more detail ?
void initializeMQTTClient() async {
_client = MqttServerClient(_host, _identifier);
_client.port = 8883; //1883
_client.keepAlivePeriod = 20;
_client.onDisconnected = onDisconnected;
_client.secure = true; // false
_client.logging(on: true);
_client.securityContext = SecurityContext.defaultContext;
// _client.useWebSocket = false;
/// Add the successful connection callback
_client.onConnected = onConnected;
_client.onSubscribed = onSubscribed;
_client.onBadCertificate = (dynamic a) => true;

trust failure when trying to access my Kestrel-based REST server

I'm experimenting with a Xamarin app, which should access a .NET Core REST server.
I ran into this issue when switching to https; I can access the api from Chrome no problem, but if I try so from within my app, I get a System.Net.WebException saying
'Error: TrustFailure (A call to SSPI failed, see inner exception.)'.
I setup my server like this:
public static IWebHostBuilder CreateWebHostBuilder(string[] args)
{
var host = WebHost.CreateDefaultBuilder(args)
.UseUrls("https://*:5000")
.UseContentRoot(Directory.GetCurrentDirectory())
.UseStartup<Startup>();
return host as IWebHostBuilder;
}
and in my app, I do something like this:
public bool addUser(User user)
{
var request = WebRequest.Create("https://192.168.1.79:5000/api/users");
request.ContentType = "application/json";
request.Method = "POST";
try
{
var json = JsonConvert.SerializeObject(user);
var data = Encoding.UTF8.GetBytes(json);
using (var stream = request.GetRequestStream())
{
stream.Write(data, 0, data.Length);
}
using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
{
return response.StatusCode == HttpStatusCode.Created;
}
}
catch(Exception ecx)
{
var what = ecx.Message;
return false;
}
}
Thanks so much for any help!

How to Access using Xamarin.Forms local Web API with Emulator for Visual Studio?

I've created .NET Framework API which contains authentication, I launch the Web API using Jetbrains Rider and I run my Xamarin.Forms application using Visual Studio and I can't access any data from my Web API nor post any.
The Webservice class:
private readonly HttpClient _client;
public AccountService()
{
_client = new HttpClient
{
MaxResponseContentBufferSize = 256000
};
}
public async Task RegisterAsync(string email, string password, string confirmPassword)
{
var url = "http://169.254.80.80:61348/api/Account/Register";
var model = new RegisterBindingModel()
{
Email = email,
Password = password,
ConfirmPassword = confirmPassword
};
var json = JsonConvert.SerializeObject(model);
HttpContent content = new StringContent(json);
content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
var response = await _client.PostAsync(url, content);
}
The initiation of the registration
private async void Register()
{
try
{
using (UserDialogs.Instance.Loading())
{
await _accountServices.RegisterAsync
(Email, Password, ConfirmPassword);
}
UserDialogs.Instance.Alert("Register Successful");
await _navigation.PushAsync(new LoginPage());
}
catch
{
UserDialogs.Instance.Alert("Something wrong happened, Try again");
}
}
I've tried to access the localhost through Emulator using these IPs:
10.0.3.2
10.0.2.2
169.254.80.80
And I've tried my default gateways and my local IP address with and without ports, in regardless using postman i can work with my api flawlessly.
I don't get errors but the connection status code is not successful and I don't get any data and the newly registered account won't be posted to the api.
EDIT:
As for the answers I've changed my method to this:
public async Task<string> RegisterAsync(string email, string password, string confirmPassword)
{
var client = new HttpClient()
{
BaseAddress = new Uri("http://169.254.80.80:61348/")
};
var postData = new List<KeyValuePair<string, string>>();
var nvc = new List<KeyValuePair<string, string>>();
nvc.Add(new KeyValuePair<string, string>("email", email));
nvc.Add(new KeyValuePair<string, string>("password", password));
nvc.Add(new KeyValuePair<string, string>("confirmPassword", confirmPassword));
var req = new HttpRequestMessage(HttpMethod.Post, "api/Account/Register") { Content = new FormUrlEncodedContent(nvc) };
var res = await client.SendAsync(req);
if (res.IsSuccessStatusCode)
{
string result = await res.Content.ReadAsStringAsync();
string test = JsonConvert.DeserializeObject<string>(result);
return test;
}
return null;
}
and i call the web api using postman like this:
http://localhost:61348/api/Account/Register
I always prefer Newtonsoft Json.NET to carry out web request here is the code I have implemented in my case and it works great for me.
public static async Task<string> ResgisterUser(string email, string password, string confirmPassword)
{
var client = new HttpClient(new NativeMessageHandler());
client.BaseAddress = new Uri("http://192.168.101.119:8475/");
var postData = new List<KeyValuePair<string, string>>();
var nvc = new List<KeyValuePair<string, string>>();
nvc.Add(new KeyValuePair<string, string>("email", email));
nvc.Add(new KeyValuePair<string, string>("password", password));
nvc.Add(new KeyValuePair<string, string>("confirmPassword",confirmPassword));
var req = new HttpRequestMessage(HttpMethod.Post, "api/Vendor/Register") { Content = new FormUrlEncodedContent(nvc) };
var res = await client.SendAsync(req);
if (res.IsSuccessStatusCode)
{
string result = await res.Content.ReadAsStringAsync();
string test= JsonConvert.DeserializeObject<string>(result);
return test;
}
}
Hope it works for you.