Archive for the ‘Web Technologies’ Category

Testing Simultaneous HTTP Requests using cURL

Tuesday, February 27th, 2024

Testing Simultaneous HTTP Requests in Parallel using cURL

If you're developing a web application and are worried that a similar HTTP request could come in multiple times from different users (or clients) exactly at the same time, you can see how your application will behave by using cURL (on modern versions of Linux) to create this rare (if almost impossible) circumstance:

curl --parallel --parallel-immediate --parallel-max 3 --header "Content-Type: application/json" --request POST --data '{STRINGIFIED_JSON_PAYLOAD}' --config urls.txt

The urls.txt file will contain the URL to your API endpoint you're testing the same number of times as the –parallel-max parameter.  So in our case, it would contain:

url = "https://pathtoapiendpoint"
url = "https://pathtoapiendpoint"
url = "https://pathtoapiendpoint"

Check how your application behaves and make appropriate changes to maintain concurrency if you're worried about this happening.  There are various approaches you can use to make sure concurrency is maintained such as appending the old value of the database record into your where clause when updating to see if the data has already been changed within the timeframe of the request being processed. 

Or, you can use persistent virtual columns like this:

https://stackoverflow.com/questions/54338201/mysql-prevent-insertion-of-record-if-id-and-timestamp-unique-combo-constraint 

Changing Servers for a Website – Redirect Traffic to New IP for No Downtime While DNS Propagates

Wednesday, December 20th, 2023

Moving a Website to Another Server – Redirect Traffic to the New Server While DNS Propagates (for No Downtime)

If you're migrating a website from one server to another and have updated the DNS for the domain to point to the new server, some traffic will still be directed to the old server due to DNS caching.  So, while the DNS changes propagate over the internet (can take up to three days), you can still redirect traffic to the new server from the old server so that you won't suffer any downtime. 

On the old server, run these commands to redirect web traffic on port 80 (http) and port 443 (https) to the new server (adjust the {DESTINATION_IP_ADDRESS} variable accordingly):

echo 1 >/proc/sys/net/ipv4/ip_forward
iptables -t nat -A PREROUTING -p tcp --dport 80 -j DNAT --to-destination {DESTINATION_IP_ADDRESS}:80
iptables -t nat -A PREROUTING -p tcp --dport 443 -j DNAT --to-destination {DESTINATION_IP_ADDRESS}:443
iptables -t nat -A POSTROUTING -p tcp -d {DESTINATION_IP_ADDRESS} --dport 80 -j MASQUERADE
iptables -t nat -A POSTROUTING -p tcp -d {DESTINATION_IP_ADDRESS} --dport 443 -j MASQUERADE

Reference:  https://serverfault.com/questions/371833/changing-servers-redirect-to-new-ip-no-downtime#371870

Creating SSL PFX Certificate for IIS Windows

Thursday, December 7th, 2023

Creating SSL PFX Certificate for IIS Windows

To create a PFX certificate file you can import into IIS on Windows from an openssl private key and certificate file on Linux, use the below command:

openssl pkcs12 -export -legacy -out iis_certificate.pfx -inkey your_private_key.key -in your_cert.crt -certfile your_chain.crt

 

OpenVPN Expired CRL – VPN Won’t Connect

Wednesday, December 7th, 2022

OpenVPN Expired CRL – VPN Won't Connect

Recently, I ran into an issue where OpenVPN was no longer working for existing clients.  After looking at the OpenVPN log in /var/log/openvpn.log, I found the following:

VERIFY ERROR: depth=0, error=CRL has expired:

If you see an OpenVPN error about an expired certificate revocation list (CRL), here's how to generate a new CRL:

cd /etc/openvpn/easy-rsa
EASYRSA_CRL_DAYS=3650 ./easyrsa gen-crl
cp /etc/openvpn/easy-rsa/pki/crl.pem /etc/openvpn/crl.pem
chown nobody:nogroup /etc/openvpn/crl.pem
service openvpn restart

Problem solved!

ASP.NET CORE – Smart Way to Prevent Cross-Site Request Forgery (CSRF) Attempts – Protect AJAX XHR Requests

Thursday, August 18th, 2022

ASP.NET CORE MVC – Protect AJAX Requests from CSRF Attempts

This is a follow-up post related to https://blog.eamster.tk/asp-net-mvc-smart-way-to-prevent-cross-site-request-forgery-csrf-attempts-webapi-ajax-xhr-and-normal-post-operations/

I've modified the code from the linked post above so that it works with ASP.NET CORE.  Below is the code that can protect all AJAX requests from CSRF (Cross-Site Request Forgery) attempts.  For normal <form> POST requests, you should still use and validate against a CSRF token, but if your application is separated into multiple pieces (for example a node.js React front-end application and a .NET CORE based API), this is an easy way to help prevent CSRF attacks without the use of tokens.

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;

namespace AnalyticsAPI.Filters
{
    public class CSRFAjaxRequestMitigation : IAuthorizationFilter
    {
        public void OnAuthorization(AuthorizationFilterContext filterContext)
        {
            IServiceProvider services = filterContext.HttpContext.RequestServices;
            IConfiguration Configuration = services.GetService<IConfiguration>();

            string validOrigins = Configuration.GetValue<string>("AllowedEnvironments"); // Example in appsettings.json "AllowedEnvironments": "https://testurl.com:4443,https://testurl.com,https://testurl2.com", 
            bool skipCheck = false;

            if(Configuration.GetValue<string>("ENVIRONMENT") == "LOCAL")
            {
                skipCheck = true;
            }

            // In AJAX requests, the origin header is always sent (UNLESS IT'S COMING FROM THE SAME ORIGIN), so we can validate that it comes from a trusted location to prevent CSRF attacks - but if one isn't sent, we won't do anything (assume trusted)
            // In which case, we don't need to do any token checking either
            if (!skipCheck && !string.IsNullOrEmpty(validOrigins))
            {
                List<string> validOriginURLs = validOrigins.Split(',').ToList();
                if (!string.IsNullOrEmpty(filterContext.HttpContext.Request.Headers["Origin"].ToString()))
                {
                    string origin = filterContext.HttpContext.Request.Headers["Origin"];
                    if (!validOriginURLs.Contains(origin, StringComparer.OrdinalIgnoreCase))
                    {
                        filterContext.Result = new UnauthorizedResult();
                    }
                }
            }
        }
    }

    public class CSRFMitigationAttribute : TypeFilterAttribute
    {
        public CSRFMitigationAttribute()
            : base(typeof(CSRFAjaxRequestMitigation))
        {
            Arguments = new object[] {};
        }
    }
} 

 

Using JQuery Color Picker and Cookie Plugins to Change Element Background Colors Dynamically Based on User Preference

Sunday, April 21st, 2013

Changing Website Element Colors Dynamically Based on User Preferences

Wouldn't it be cool to dynamically style a website or webpage based on a user's favorite color?  Thanks to several JQuery plugins, it is now possible to do so!  The JQuery Color Picker plugin allows users to select a color based on a color pallete / color wheel similar to those found within photo editing software such as Adobe Photoshop or Corel PaintShop Pro.  The JQuery Color Plugin can darken, lighten, add, multiply, subtract, find color hues, change rgb values, and manipulate colors in all sorts of ways you probably never imagined possible.  The final piece to dynamically styling a page based on a user selected color is to save the picked color's value in a cookie using the JQuery-Cookie Plugin.  When any page loads, you will need to use the document.ready JQuery function to read the cookie and restyle elements as necessary.  If a cookie is not set, the default color can also be specified here. 

Here's a screenshot of the JQuery Color Picker in action:

To load / use the color picker, place this function within the document.ready function:

// Color Picker Loader
    $('#colorpicker').ColorPicker({
    
       color: defaultColor,
         onShow: function (colpkr) {
              $(colpkr).fadeIn(500);
              return false;
         },
         onHide: function (colpkr) {
              $(colpkr).fadeOut(500);
              return false;
         },
         onChange: function (hsb, hex, rgb) {
          var origColor = '#' + hex;
       
          // Set the main div background colors to what was selected in the color picker
              $('#colorpicker').css('backgroundColor', origColor);
          $('#origColor').css('backgroundColor', origColor);
          
          // Set the cookie
          $.cookie("color", '#' + hex, { path: '/' });
          
          // Set the dark and light colors (multi-iterations)
          darkColor = $.xcolor.darken('#' + hex).getHex();
          for (var i = 0; i < iterations; i++) {
            darkColor = $.xcolor.darken(darkColor).getHex();
          }
            
          lightColor = $.xcolor.lighten('#' + hex).getHex();
          for (var i = 0; i < iterations; i++) {
            lightColor = $.xcolor.lighten(lightColor).getHex();
          }
          
          
          // Set the light and dark divs
          $('#darkColor').css('backgroundColor', darkColor);
          $('#lightColor').css('backgroundColor', lightColor);
          
          // Change class attributes
          $('.light').css('backgroundColor', lightColor);
          $('.dark').css('backgroundColor', darkColor);
          $('.pad').css('backgroundColor', origColor);
          
          // Set the border
          $('#colorpicker').css('border-color', darkColor);
          
          
         }
    }); 

Assign a DIV element the ID of "colorpicker" in your HTML file to activate the color picker.    Don't change the "onShow" or "onHide" JQuery sub-functions of the ColorPicker.  When a user chooses a color from the color picker, the color picker "onChange" function is called.  This is where you need to define what should be done with the color the user has picked.  In my example, I call the $.xcolor.lighten and $.xcolor.darken Color Plugin functions to generate a lighter and darker color.  I use then use the color selected, a lighter variant of that color, and a darker variant of that color to style elements appropriately to keep text readable while offering a new color scheme.  As you can see from the code above, I mainly change the css attributes of certain classes, which the elements have been assigned.  What is changed is the backgroundColor and border-color of certain classes based on the three colors that were generated.

To see what other cool things you can do with all of these plugins, check out the links in the first paragraph.  Click here to see a live demonstration of all three plugins in action and download the source for how it all works based on the example discussed above.  The only Javascript file that needs to be changed to experiment with this sample is the "main.js" file within the "js" folder.

I hope this guide helps.  The plugin websites did not provide all of the code needed for a working sample, but luckily, I did the combination work for you.  Go ahead and use my source for anything!  Please comment if you have questions.