0

The application is configured to use HTTPS. We want to be able to make calls from the client to a printer on their local network that exposes a simple api that uses HTTP. So from our javascript code we do a POST with a "text/plain" payload to send commands to the printer. When we send this request we get the following error.

jquery-3.3.1.min.js:2 Mixed Content: The page at 'https://...' was loaded over HTTPS, but requested an insecure XMLHttpRequest endpoint 'http://.../pstprnt'. This request has been blocked; the content must be served over HTTPS.

Is there a way to configure CORS in such a way that only this traffic from and to a printer can be done using HTTP while the rest of the application uses HTTPS, without specifying the target IN startup.cs ? ( this is because the printers should be able to be expanded at runtime, so basically just 'allow all orgins', so that its not restricted to the ones specified in Startup.cs)

I have tried multiple guides online, but I'm guessing there is something wrong with our Startup.cs file structure.

The request to the printer looks like this:

$.ajax({
    type: "POST",
    url: "http://<printer-ip>/pstprnt",
    data: 'some ZPL',
    contentType: 'text/plain'
}).done((res) => {
    console.log("second success");
}).fail((e) => {
    alert(e);
})

Here is a snippet our Startup file.

CONFIGURE SERVICES

        public void ConfigureServices(IServiceCollection services)
        {
            // Add Cors
            services.AddCors();

            services.Configure<CookiePolicyOptions>(options =>
            {
                // This lambda determines whether user consent for non-essential cookies is needed for a given request.
                options.CheckConsentNeeded = context => true;
                options.MinimumSameSitePolicy = SameSiteMode.None;
            });

            services.AddDbContext<ApplicationDbContext>(options =>
              options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
            /* (Verification/password reset) email sender */
            //services.AddTransient<IEmailSender, EmailSender>();
            //services.Configure<AuthMessageSenderOptions>(Configuration);

            Task.Run(() => {
                var options = new DbContextOptionsBuilder<ApplicationDbContext>().UseSqlServer(Configuration.GetConnectionString("DefaultConnection")).Options;
                using (var dbContext = new ApplicationDbContext(options)) {
                    var model = dbContext.AankoopProduct;
                  
                }
            });



            services.AddLocalization();
            /*
               I commented this out because I am using UseEndpoints, Am I doing this correctly?

            services.AddMvc()
                .AddViewLocalization(LanguageViewLocationExpanderFormat.Suffix)
                .AddDataAnnotationsLocalization().AddNewtonsoftJson(options =>
            options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore);
            */
          
            services.AddIdentity<Gebruiker, IdentityRole>(options =>
            {
                options.Lockout.MaxFailedAccessAttempts = 5;
                options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(15);
                options.SignIn.RequireConfirmedEmail = true;
            }).AddEntityFrameworkStores<ApplicationDbContext>()
              .AddDefaultTokenProviders();

            services.Configure<IdentityOptions>(options =>
            {
                // Password settings.
                options.Password.RequireDigit = true;
                options.Password.RequireLowercase = true;
                options.Password.RequireNonAlphanumeric = false;
                options.Password.RequireUppercase = true;
                options.Password.RequiredLength = 6;
                options.Password.RequiredUniqueChars = 1;
            });

            services.AddControllersWithViews().AddNewtonsoftJson(options =>
            options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore);

            // .cshtml views & .razor components 
            services.AddRazorPages();

            //SignalR for Websockets
            services.AddSignalR();

            // reload views after changing JS 
#if DEBUG
            var mvcBuilder = services.AddControllersWithViews();
            mvcBuilder.AddRazorRuntimeCompilation();
            #endif


            services.ConfigureApplicationCookie(opts => opts.LoginPath = "/Account/Login");

            /* Breadcrumbs */
            services.AddBreadcrumbs(GetType().Assembly, options =>
            {
                options.TagName = "nav";
                options.TagClasses = "";
                options.OlClasses = "breadcrumb breadcrumb--transparent m-0";
                options.LiClasses = "breadcrumb-item";
                options.ActiveLiClasses = "breadcrumb-item active";
                //options.SeparatorElement = "<li class=\"separator\">/</li>";
            });
            /* Repositories */
            services.RegisterRepositories();

            services.AddSession();
        }


CONFIGURE

   public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IVerkoopProductXMLRepository rep)
        {
            //app.ApplicationServices.GetService<IInkomendeBestellingTrackerSingleton>();


            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();

            }
            else
            {
                app.UseExceptionHandler("/Home/Error");
                app.UseHsts();
            }

            #region Auth
            var supportedCultures = new[]
            {
                new CultureInfo("nl-BE")
            };

            app.UseRequestLocalization(new RequestLocalizationOptions
            {
                DefaultRequestCulture = new RequestCulture("nl-BE"),
                // Formatting numbers, dates, etc.
                SupportedCultures = supportedCultures,
                // UI strings that we have localized.
                SupportedUICultures = supportedCultures
            });

            var cultureInfo = new CultureInfo("nl-BE");
            cultureInfo.NumberFormat.CurrencySymbol = "€";
            cultureInfo.NumberFormat.NumberDecimalSeparator = ".";

            CultureInfo.DefaultThreadCurrentCulture = cultureInfo;
            CultureInfo.DefaultThreadCurrentUICulture = cultureInfo;
            Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo("nl-BE");
            Thread.CurrentThread.CurrentCulture = CultureInfo.GetCultureInfo("nl-BE");


            // To configure external authentication, 
            // see: http://go.microsoft.com/fwlink/?LinkID=532715

            #endregion

            app.UseHttpsRedirection();
            app.UseStaticFiles();
            app.UseStatusCodePages();
            app.UseRouting();
            app.UseSession();

            // Enable Cors
            app.UseCors();
            /*
              I commented this out because I am using UseEndpoints() , Am I doing this correctly?
            app.UseMvc(routes =>
            {
                routes.MapRoute(
                    name: "default",
                    template: "{controller=Home}/{action=UserSelection}/{id?}");
            });
            */
            app.UseCookiePolicy();
            app.UseAuthentication();
            app.UseAuthorization();
            app.UseEndpoints(endpoints => {
                endpoints.MapControllerRoute(
                    name: "default",
                    pattern: "{controller=Account}/{action=Login}/{id?}");
            });

 }


sideshowbarker
  • 81,827
  • 26
  • 193
  • 197
  • this has what to do with javascript? – Jaromanda X Sep 16 '20 at 15:19
  • I will add the Javascript snippet :-) – Project Contributor Sep 16 '20 at 15:23
  • 2
    Why do you think this has to do with CORS? As far as I can tell, this is a [browser security feature](https://developer.mozilla.org/en-US/docs/Web/Security/Mixed_content/How_to_fix_website_with_mixed_content) unrelated to CORS. – Kevin Christopher Henry Sep 16 '20 at 15:25
  • @KevinChristopherHenry I thought it was a CORS issue because the error made me think this way, maybe the error misled me? – Project Contributor Sep 16 '20 at 15:38
  • @KevinChristopherHenry The printer I am using only supports HTTP traffic, it is a ZebraGK420d – Project Contributor Sep 16 '20 at 15:43
  • @ProjectContributor [HTTP Ajax Request via HTTPS Page](https://stackoverflow.com/questions/4032104/http-ajax-request-via-https-page) might help. Otherwise, you could make an https-capable print server using, e.g., a Raspberry Pi, and connect it to the printer's USB port. Which would also enable the client to use purely Gigabit Ethernet, if the 10/100 printers were holding them back. – Andrew Morton Sep 16 '20 at 16:13
  • @AndrewMorton I thought about using a rpi for each workspace but this is hardly scalable. – Project Contributor Sep 16 '20 at 16:18
  • @ProjectContributor It's as scalable as the physical printers - it only needs one RPi per printer. I'm surprised Zebra don't have a solution (or do they)? – Andrew Morton Sep 16 '20 at 16:22
  • 1
    @AndrewMorton I had them on the phone today for half an hour but the technical department was "afraid they couldn't help" – Project Contributor Sep 16 '20 at 16:32
  • @AndrewMorton Per the comments on my answer, they've got ~200 printers. That's a _lot_ of Pi's. – DylanSp Sep 16 '20 at 16:41
  • I am currently able to print when using HTTP, but unfortunately I cannot put this on production, as the customers will feel / notice the app is 'insecure' – Project Contributor Sep 16 '20 at 17:14
  • @ProjectContributor Are all the printers on the same domain, or are they each on different domains? – DylanSp Sep 16 '20 at 17:23
  • @ProjectContributor Did you see the answers which use http from my earlier link? – Andrew Morton Sep 16 '20 at 19:24
  • Proxy the request through your backend. Make an endpoint on your backend like `https://your-backend-server-url/pstprnt` and have the behavior of that endpoint be that it makes the request to the `http:///pstprnt` URL and then consumes the response and returns it to your frontend code. – sideshowbarker Sep 16 '20 at 23:01
  • @DylanSp The printers are connected LAN of the clients. There are about 200. The application will run on our server. – Project Contributor Sep 17 '20 at 07:50
  • @AndrewMorton Thanks for the proposal Andrew. We decided to make a RPi print server for each client network that exposes an API for remote printing :) – Project Contributor Sep 17 '20 at 07:54

1 Answers1

0

This doesn't relate to your ASP.NET CORS configuration, because you're making a request directly from the client (the browser) to the printer; CORS would come into play if you were making cross-domain requests to the ASP.NET API.

What you could do is make the request to the printer from the server, instead, assuming your network topology permits it. Make an AJAX request from your JS to a new endpoint on the server, which then makes a plain HTTP request to the printer.

DylanSp
  • 1,379
  • 13
  • 27
  • Dear Dylan, I cannot do this from the server, because this would require our server to know the IP addresses for every client we have ( ~ 200 ), also it would be a mess to connect to their domain and use that printer. Instead , I would like them to add their label printers' IP address to a table so that they can print to it whever, from the client, using JavaScript – Project Contributor Sep 16 '20 at 15:40
  • Having to connect to the domain is a problem, unfortunately; you might be out of luck. Discovering the printer IPs wouldn't be a problem, you could have the JS send the IP as part of the request to the server. – DylanSp Sep 16 '20 at 15:55