Create your own Captcha for Security on Login Page

Oracle Application Express is a rapid development tool for Web applications on the Oracle database.
Post Reply
admin
Posts: 2115
Joined: Fri Mar 31, 2006 12:59 am
Location: Pakistan
Contact:

Create your own Captcha for Security on Login Page

Post by admin »

Providing Captcha on your Oracle APEX login page is a security requirement which any public application must have to handle automated logins.

Captcha1.png
Best practices for CAPTCHA
  • Generate the code
  • Use a random string for the CAPTCHA Mix letters and numbers (avoid ambiguous characters like 0 vs O or 1 vs l).
  • Store the CAPTCHA value in a hidden page item
  • Redraw on demand (refresh icon) User can request a new CAPTCHA if the current one is hard to read.
  • Validate before login processing In a Before Header or Page Process, check if the user-entered value matches the stored CAPTCHA. Reject login if it doesn’t match.
  • Use image distortions and noise Makes it harder for automated bots to read the text.
  1. Create a new application in Oracle APEX or open exisiting login page P9999.
  2. Create following

    a. Static Content Region
    b. :P9999_CAPTCHA
    c. :P9999_SECRET_CAPTCHA << It will be hidden and Value Protected off.
    Captcha2.png
  3. Now click page and copy paste following code in Function and Global Variable Declaration

    Code: Select all

    // Draw CAPTCHA on canvas
    function drawCaptcha(rawText) {
      const canvas = document.getElementById("captcha");
      const ctx = canvas.getContext("2d");
      const colors = ["#e53935","#1e88e5","#43a047","#fb8c00","#8e24aa","#00897b"];
    
      ctx.clearRect(0, 0, canvas.width, canvas.height);
    
      // Background
      const bg = ctx.createLinearGradient(0,0,canvas.width,canvas.height);
      bg.addColorStop(0,"#ffffff");
      bg.addColorStop(1,"#eaeaea");
      ctx.fillStyle = bg;
      ctx.fillRect(0,0,canvas.width,canvas.height);
    
      // Random curves
      for (let i=0;i<8;i++) {
        ctx.strokeStyle = colors[Math.floor(Math.random()*colors.length)] + "80";
        ctx.lineWidth = 3;
        ctx.beginPath();
        ctx.moveTo(0, Math.random()*canvas.height);
        ctx.bezierCurveTo(
          canvas.width*0.3, Math.random()*canvas.height,
          canvas.width*0.6, Math.random()*canvas.height,
          canvas.width, Math.random()*canvas.height
        );
        ctx.stroke();
      }
    
      // Draw letters
      ctx.font = "50px Arial";
      ctx.textAlign = "center";
      ctx.textBaseline = "middle";
      const gap = 42;
      const totalWidth = (rawText.length - 1) * gap;
      const centerX = canvas.width/2 - totalWidth/2;
    
      for (let i=0;i<rawText.length;i++) {
        ctx.save();
        ctx.translate(centerX + i*gap, canvas.height/2 + (Math.random()*16 - 8));
        ctx.rotate((Math.random()*40-20) * Math.PI/180);
        const grad = ctx.createLinearGradient(-20,-30,20,30);
        grad.addColorStop(0,"#e53935");
        grad.addColorStop(0.5,"#1e88e5");
        grad.addColorStop(1,"#43a047");
        ctx.fillStyle = grad;
        ctx.fillText(rawText[i],0,0);
        ctx.restore();
      }
    
      // Noise dots
      for (let i=0;i<250;i++){
        ctx.fillStyle = colors[Math.floor(Math.random()*colors.length)] + "99";
        ctx.fillRect(Math.random()*canvas.width, Math.random()*canvas.height, 2, 2);
      }
    
      // Noise lines
      for (let i=0;i<10;i++){
        ctx.strokeStyle = colors[Math.floor(Math.random()*colors.length)] + "aa";
        ctx.lineWidth = 1;
        ctx.beginPath();
        ctx.moveTo(Math.random()*canvas.width, Math.random()*canvas.height);
        ctx.lineTo(Math.random()*canvas.width, Math.random()*canvas.height);
        ctx.stroke();
      }
    }
    
    // Generate random CAPTCHA code
    function generateCaptcha(length=6) {
      const chars = 'ABCDEFGHJKLMNPQRSTUVWXYZ23456789abcdefghijklmnpqrstuvwxyz';
      let code = '';
      for(let i=0;i<length;i++){
        code += chars[Math.floor(Math.random()*chars.length)];
      }
    
      // Draw and update hidden item
      drawCaptcha(code);
      $s("P9999_SECRET_CAPTCHA", code);
      $s("P9999_CAPTCHA", "");
    }
    
    // Initial draw on page load
    document.addEventListener("DOMContentLoaded", function(){
      generateCaptcha();
    
      // Attach refresh click handler
      const refreshIcon = document.getElementById("captchaRefresh");
      if(refreshIcon){
        refreshIcon.addEventListener("click", function(){
          generateCaptcha();
        });
      }
    });
    
  4. Create a dynamic action and set its eent to Page Load. In true action select Excecute Java Code and copy paste following code.

    Code: Select all

    document.addEventListener("DOMContentLoaded", function() {
      generateCaptcha(); 
    });
    
    captcha3.png
  5. Create a validation and enter following code and provide yoru error message to display.

    Code: Select all

    BEGIN
        IF :P9999_CAPTCHA IS NOT NULL THEN
            IF :P9999_CAPTCHA!= :P9999_SECRET_CAPTCHA THEN
                RETURN FALSE;
            ELSE
                RETURN TRUE;
            END IF;
        ELSE
            RETURN FALSE;
        END IF;
    END;
    captcha4.png
  6. Now test by entering wrong captcha and then correct. Here I generated captcha on client side to avoid slite delay while generate using plsql on server side.
    Captch5.png
You do not have the required permissions to view the files attached to this post.
Malik Sikandar Hayat
Oracle ACE Pro
info@erpstuff.com
Post Reply

Who is online

Users browsing this forum: Google Adsense [Bot] and 7 guests