I want to create an application where a web server can get the MAC Address of the clients logging in. The only possible way I could think of was to create a JAVA applet which contains java.net methods to find the mac address
I am using javascript to call the applet methods, but the browser is not allowing those methods to execute. Below is the applet I have created.
import java.applet.*;
import java.awt.*;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.net.UnknownHostException;
public class AppletRunner extends Applet{
// The method that will be automatically called when the applet is started
public void init()
{
// It is required but does not need anything.
}
//This method gets called when the applet is terminated
//That's when the user goes to another page or exits the browser.
public void stop()
{
// no actions needed here now.
}
//The standard method that you have to use to paint things on screen
//This overrides the empty Applet method, you can't called it "display" for example.
public void paint(Graphics g)
{
//method to draw text on screen
// String first, then x and y coordinate.
g.drawString(getMacAddr(),20,20);
g.drawString("Hello World",20,40);
}
public String getMacAddr() {
String macAddr= "";
InetAddress addr;
try {
addr = InetAddress.getLocalHost();
System.out.println(addr.getHostAddress());
NetworkInterface dir = NetworkInterface.getByInetAddress(addr);
byte[] dirMac = dir.getHardwareAddress();
int count=0;
for (int b:dirMac){
if (b<0) b=256+b;
if (b==0) {
macAddr=macAddr.concat("00");
}
if (b>0){
int a=b/16;
if (a==10) macAddr=macAddr.concat("A");
else if (a==11) macAddr=macAddr.concat("B");
else if (a==12) macAddr=macAddr.concat("C");
else if (a==13) macAddr=macAddr.concat("D");
else if (a==14) macAddr=macAddr.concat("E");
else if (a==15) macAddr=macAddr.concat("F");
else macAddr=macAddr.concat(String.valueOf(a));
a = (b%16);
if (a==10) macAddr=macAddr.concat("A");
else if (a==11) macAddr=macAddr.concat("B");
else if (a==12) macAddr=macAddr.concat("C");
else if (a==13) macAddr=macAddr.concat("D");
else if (a==14) macAddr=macAddr.concat("E");
else if (a==15) macAddr=macAddr.concat("F");
else macAddr=macAddr.concat(String.valueOf(a));
}
if (count<dirMac.length-1)macAddr=macAddr.concat("-");
count++;
}
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
macAddr=e.getMessage();
} catch (SocketException e) {
// TODO Auto-generated catch block
macAddr = e.getMessage();
}
return macAddr;
}
}
Applets cannot normally access these functions for security reasons. To avoid these restrictions, you need a signed applet, along with a policy file.
You can then write a policy file which grants your applet access to the functionality it needs. If the user then grants your applet the necessary permissions (it will prompt for them), your applet can use the functions.
In Netbeans, you can sign an application enabling the WebStart:
Access to Your project > properties > Application > WebStart
Check "Enable Web Start". This show a sectin titled signing.
Click the "Customize" button located in the signing section.
Select "self-sign by generated key".
I don't think this will be possible. Web servers communicate with clients several layers above the link layer where MAC addresses live -- it's abstracted away by TCP/IP and there's no reason for the client to send it unless you specifically have client code to do that.
The reason your Java code isn't working is because the Java sandbox's security manager disallows such low-level calls -- which it should! If you ever do find a way to get that thing to work (which I doubt you will) you should promptly report it to Oracle because it shouldn't be happening at all.
I can't see much of a reason why you'd want it either, to be honest.
The Java applet is prevented to access those methods on the client because it runs in a protected sandbox.
It might not be possible within a browser, since it is against the sandboxing paradigm. You might have some luck with browser-specific native code extensions.
However, the important exception is if your web server is in the same local area network (same switch) as the client - then, the MAC address of the client is known to the server because it is still present in the IP packet.
Related
I have a Xamarin.Forms app. It includes a button like this:
<Button x:Name="Buy_Button" Text="Satın Al" FontAttributes="Bold" TextColor="#e2e2e2" BackgroundColor="#2A52BE" FontFamily="Segoe UI" Grid.Column="2" Grid.ColumnSpan="1" Grid.RowSpan="1" CornerRadius="5" VerticalOptions="Start" HorizontalOptions="Center" FontSize="15.667" Grid.Row="0" Margin="0,10,10,0" Clicked="Buy_Button_ClickedAsync" CommandParameter="{Binding Buy_URL}" />
I'm sending a URL link to click event for opening specific web page. Code is:
private async void Buy_Button_ClickedAsync(object sender, EventArgs e)
{
Button btn = (Button)sender; // Coming button from click event handler.
var buylink = btn.CommandParameter.ToString(); // Get the CommandParameter.
// await DisplayAlert("Satın alma linki", buylink, "Anladım"); // Show the link.
try // Uwp & iOS & Android
{
await Browser.OpenAsync(new Uri(buylink), BrowserLaunchMode.SystemPreferred); // Open url in-app browser for iOS & Android- native in UWP
}
catch (NotImplementedInReferenceAssemblyException ex) //Wasm falls here because lack of Xamarin.Essentials.
{
// await DisplayAlert("Hata", ex.Message, "Anladım"); // Show the info about exception.
// Jint - nt is a Javascript interpreter for .NET which provides full ECMA 5.1 compliance and can run on any .NET platform.
//Because it doesn't generate any .NET bytecode nor use the DLR it runs relatively small scripts faster.
//https://github.com/sebastienros/jint
var engine = new Engine();
engine.SetValue("log", new Action<object>(Console.WriteLine));
engine.Execute(#"function openurl() { log('" + buylink + "'); }; openurl(); ");
}
}
In UWP, Xamarin.iOS and Xamarin. Android this code is running via Xamarin.Esssentials:
await Browser.OpenAsync(new Uri(buylink), BrowserLaunchMode.SystemPreferred); // Open url in-app browser for iOS & Android- native in UWP
However, my Xamarin.Forms app projected to WebAssembly code with Uno Platform, so this code block not running. As a result. I install Jint to Xamarin.Forms app. This catch block prints the link to Browser console, but no window.open function track in API reference:
catch (NotImplementedInReferenceAssemblyException ex) //Wasm falls here because lack of Xamarin.Essentials.
{
// await DisplayAlert("Hata", ex.Message, "Anladım"); // Show the info about exception.
// Jint - nt is a Javascript interpreter for .NET which provides full ECMA 5.1 compliance and can run on any .NET platform.
//Because it doesn't generate any .NET bytecode nor use the DLR it runs relatively small scripts faster.
//https://github.com/sebastienros/jint
var engine = new Engine();
engine.SetValue("log", new Action<object>(Console.WriteLine));
engine.Execute(#"function openurl() { log('" + buylink + "'); }; openurl(); ");
}
}
How can I open WebBrowser page on WASM via Javascript form Xamarin.Forms C# code? Thanks.
2 things:
1. Use the browser!
On Wasm, you're running in a webassembly environment, which is running in a javascript virtual machine (that's not totally accurate, but close enough for my point). That means you can directly invoke the javascript of the running environment (browser).
Making a call to native javascript...
WebAssemblyRuntime
.InvokeJS("(function(){location.href=\"https://www.wikipedia.com/\";})();");
In your case, since you want to open a browser window, it's required to use this approach, because Jint can't access anything from the browser itself.
2. You can still call Jint anyway (but not to open a new window)
If you still want to call code using Jint (because you can!!), you need to exclude the Jint.dll assembly from the linking process. Probably because it's using reflection to operate. Again, it won't work to open a window as you're asking, but if you need to call Jint for any other reason, it will work as on other platforms!
Add this to your LinkerConfig.xml (in the Wasm project):
<assembly fullname="Jint" />
Also... You gave me an idea and I did something cool with Jint...
I put the entire solution there: https://github.com/carldebilly/TestJint
It works, even on Wasm:
Interesting code:
https://github.com/carldebilly/TestJint/blob/master/TestJint/TestJint.Shared/MainPage.xaml.cs#L18-L40
private void BtnClick(object sender, RoutedEventArgs e)
{
void Log(object o)
{
output.Text = o?.ToString() ?? "<null>";
}
var engine = new Engine()
.SetValue("log", new Action<object>(Log));
engine.Execute(#"
function hello() {
log('Hello World ' + new Date());
};
hello();
");
#if __WASM__
output2.Text =
WebAssemblyRuntime.InvokeJS("(function(){return 'Hello World ' + new Date();})();");
#else
output2.Text = "Not supported on this platform.";
#endif
}
Final Note
On UWP/WinUI XAML, you can directly put a <Hyperlink /> in your XAML. I'm not familiar enough with Xamarin Forms to know if there's an equivalent.
I am using Device.OpenUri and it works in WASM with Xamarin.Forms
Device.OpenUri(new Uri("https://www.bing.com"));
We have an Outlook VSTO component that adds a panel that contains a WebBrowser component, which in turn opens a web page.
We want to call back from the web page using WebBrowser.ObjectForScripting, but the guidance provided by MS here doesn't work.
So in the C# VSTO we have something like:
[ComVisible(true),
PermissionSet(SecurityAction.Demand, Name="FullTrust")]
public class MyComponent { ...
webBrowser1.ObjectForScripting = this;
webBrowser1.Document.InvokeScript("test");
...
public void HandleResult() { ...
And in the JS we have something like:
function test() {
doSomethingAsync().then(function(result) {
window.external.HandleResult();
});
}
However HandleResult is never called.
I think the issue it due to the PermissionSet being denied permissions in a VSTO add-in that it does get in stand alone Windows Forms apps.
Any idea how to set the appropriate permissions?
I'm building a login page that, upon submitting and validation of the user credentials, opens up a native mobile application. Up till last week, I had this working cross mobile OS by using a custom scheme URI, something like:
function onLoginCallback() {
const redirectUri = 'customscheme:/action?param1=val1¶m2=val2';
window.location.replace(redirectUri);
}
The login page is displayed in an IABT, short for In App Browser Tab.
However, since the release of version 61 of Chrome, this is approach is broken on Android. Chrome blocks the redirect because there's no apparent user action related to the redirect (see here for more information on the matter).
As a consequence, when executing the code above, I'll end up with a warning in the console:
Navigation is blocked: customscheme:/action?param1=val1¶m2=val2
I've also tried updating the custom scheme url to an intent url but to no avail. Googling about this issue doesn't readily provide a clear solution, so I'm hoping anyone on can help me out.
Edit: Tried to reproduce the issue with the following scenario (as close as possible to the real life scenario):
IABT displays a page with a single button
Clicking the button fires an jsonp call to a mock endpoint
The JSONP callback is executed and fires off a custom event
An event handler for the custom event is triggered and redirects the browser to another mock endpoint
That mock endpoint responds with a 302 to the custom deeplink scheme.
Alas, this seems to be working. I would have expected that the inclusion of the jsonp call would cause Chrome to block the final redirect as it would not be able to identify it as a user initiated action.
Edit 2: Managed to get a reproducible scenario. We've set up a dummy endpoint, that upon request simply returns a 302 with the custom scheme in the Location header. This is blocked on all tries, except for the first one. That fact still boggles the mind. We're using the AppAuth for Android application to test the setup.
I'm opening a custom tab to the endpoint as shown below. The code is taken from this answer.
void launchTab(Context context, Uri uri){
final CustomTabsServiceConnection connection = new CustomTabsServiceConnection() {
#Override
public void onCustomTabsServiceConnected(ComponentName componentName, CustomTabsClient client) {
final CustomTabsIntent.Builder builder = new CustomTabsIntent.Builder();
final CustomTabsIntent intent = builder.build();
client.warmup(0L); // This prevents backgrounding after redirection
intent.launchUrl(context, uri);
}
#Override
public void onServiceDisconnected(ComponentName name) {
}
};
CustomTabsClient.bindCustomTabsService(context, "com.android.chrome", connection);
}
We ended up implementing our login and registration forms with a classic post-redirect-get pattern.
The server responds with a 302 to the custom URI scheme. Because in this setup there's no asynchronous execution between the user submitting the form and the browser receiving a redirect, Chrome correctly identifies the chain of actions as trusted and thus will not block the navigation.
I realise this might not be the preferred solution for everyone. A possible alternative to support asynchronous execution flows is the use of universal links as these use regular http(s) schemes, to which redirects were (at the time of posting my question) not considered harmful by Chrome.
For those who use App Auth client and Identity Server:
Startup.cs
services.AddTransient<IAuthorizeResponseGenerator, AuthorizeRG>();
AuthorizeRG.cs
public class AuthorizeRG: AuthorizeResponseGenerator
{
public override async Task<AuthorizeResponse> CreateResponseAsync(ValidatedAuthorizeRequest request)
{
var response = await base.CreateResponseAsync(request);
if (response.RedirectUri != null && request.IsNativeClient())
//this fix chrome navigation blocked on native clients https://bugs.chromium.org/p/chromium/issues/detail?id=738724
response.Request.RedirectUri = $"/native/redirect/{HttpUtility.UrlEncode(response.RedirectUri)}";
return response;
}
}
NativeController.cs
[Route("[controller]")]
public class NativeController : Controller
{
[HttpGet("Redirect/{redirectUri}")]
public IActionResult Redirect([FromRoute] string redirectUri)
{
redirectUri = HttpUtility.UrlDecode(redirectUri);
redirectUri += HttpContext.Request.QueryString.ToUriComponent();
return this.LoadingPage("Redirect", redirectUri);
}
}
Extensions.cs
/// <summary>
/// Checks if the redirect URI is for a native client.
/// </summary>
/// <returns></returns>
public static bool IsNativeClient(this AuthorizationRequest context)
{
return !context.RedirectUri.StartsWith("https", StringComparison.Ordinal)
&& !context.RedirectUri.StartsWith("http", StringComparison.Ordinal);
}
public static bool IsNativeClient(this ValidatedAuthorizeRequest context)
{
return !context.RedirectUri.StartsWith("https", StringComparison.Ordinal)
&& !context.RedirectUri.StartsWith("http", StringComparison.Ordinal);
}
public static IActionResult LoadingPage(this Controller controller, string viewName, string redirectUri)
{
controller.HttpContext.Response.StatusCode = 200;
controller.HttpContext.Response.Headers["Location"] = "";
return controller.View(viewName, new RedirectViewModel { RedirectUrl = redirectUri });
}
This works for me, but please comment if it broke smth in your authorization flow
I am developing web application in Java, and I must print reports, when clicked on button, on client side printer. How to implement? How to show printers from client side???
I use:
PrintService[] printers =
PrintServiceLookup.lookupPrintServices(null, null);
But this is on server side.
As your requirement is not clear. I am not sure about what exactly you want but for print you can use this window.print()
function myFunction() {
window.print();
}
<p>Click To print.</p>
<button onclick="myFunction()">Click</button>
You can read more about this here(simple) and here(explained).
Edit:
And if you want to print a particulate element content you can use this function:
function myPrint(data)
{
var testPage = window.open('', 'Test Page', 'height=500,width=500');
testPage.document.write('<html><head><title>Test Page</title>');
testPage.document.write('</head><body >');
testPage.document.write(data);
testPage.document.write('</body></html>');
testPage.document.close();
testPage.focus();
testPage.print();
testPage.close();
return ;
}
You must use javascript on the client page.
window.print()
https://developer.mozilla.org/en-US/docs/Web/API/Window/print
If you want to try the applet approach give a look at this answer
You cannot do that for security reasons. If you could, applets would
already have become notorious for printing 10+ pages of 'special
offers' when you visit unscrupulous web sites.
OTOH, if the client is willing to accept one prompt at applet
start-up, you could digitally sign the code.
Also it should be possible to achieve a similar result using the PrintService from JNLP API without the need for a signed applet.
Like in the Following example
import javax.jnlp.*;
...
PrintService ps;
try {
ps = (PrintService)ServiceManager.lookup("javax.jnlp.PrintService");
} catch (UnavailableServiceException e) {
ps = null;
}
if (ps != null) {
try {
// get the default PageFormat
PageFormat pf = ps.getDefaultPage();
// ask the user to customize the PageFormat
PageFormat newPf = ps.showPageFormatDialog(pf);
// print the document with the PageFormat above
ps.print(new DocToPrint());
} catch (Exception e) {
e.printStackTrace();
}
}
// Code to construct the Printable Document
class DocToPrint implements Printable {
public int print(Graphics g, PageFormat pageformat, int PageIndex){
// code to generate what you want to print
}
}
So my goal is to have a web portal where our helpdesk users can lookup a user, find their computer(s) and click on the computer name to launch a remote-viewer application locally. I've attempted through, vb .net, javascript/asp, sql, and I'm out of ideas..
Here's some of the code already attempted.
<script type = "text/javascript" >
function go() {
w = new ActiveXObject("WScript.Shell");
w.run("cmd.exe /c C:\\SCCMRemoteView\\Remote\\CmRcViewer.exe ");
return true;
}
</script>
Returns "Unspecified Error"
Also, tried the
Shell, (var remote.exe, "CmRcViewer.exe","C:\SCCMRemote\Remote\","open","1")
Failed...
Dim Rview As New Process
Rview.StartInfo.FileName = ("C:\SCCMRemote\Remote\CmRcViewer.exe ")
Works, but not after its published to the website (I believe because the base code is aspx - not local)
I know the "Security" risks, but only members of our AD group will have access to the page - so it should be fine... Any ideas would be great!
This is not realistically feasible. The only browser that can support ActiveX calls is IE. IE has discontinued support for ActiveX with Windows 8, no matter which browser you use. With Windows 7, you have to run the browser in an elevated privileges mode (opening you up for those security issues you mentioned).
You can try this, but you will have to register the protocol handler to an executable by making Registry entries on each machine. This process is not something that can be automated from the browser. Your users will have to download and execute something to create the handler.
It appears that some browsers will allow you to do the same thing with a browser based protocol handler, but it is not implemented everywhere.
Dim Address As String = Server.MapPath("~") & "\test.exe"
Process.Start("explorer.exe", Address)
try to use exec instead of run like so:
<script>
function Run() {
try {
var objShell = new ActiveXObject("wscript.shell");
objShell.exec("C:\\SCCMRemoteView\\Remote\\CmRcViewer.exe ");
} catch(e) {
alert(e);
}
}
</script>
<input type="button" name="btn01" onclick="Run()" value="click me">
Furthermore you have to change the security settings for YOUR SPECIFIC site in IE Settings->Security. add your site to the trusted sites and set the activex things... you will have to do that for each Computer/IE in which you want to use that activex/remote thing...