Automating CAS Single Sign-On with Python and Optical Character Recognition

Workflow Overview

The authentication process involves simulating a standard browser interaction to bypass the Captcha challenge. The core sequence includes accessing the login entry point, retrieving the image-based verification code, processing the image through a external OCR service, and finally submitting the credentials combined with the extracted code.

Environment Prerequisites

  • OS: Windows 11 or Linux/macOS equivalent
  • Runtime: Python 3.10+
  • IDE: PyCharm or VS Code recommended for development
  • Key Libraries: requests, beautifulsoup4, json

Install required packages:

pip install requests beautifulsoup4

API Configuration

To automate this process, you require access to an intelligent cloud OCR service. Configure the following:

  1. Service Account: Register on Baidu Cloud (or similar provider).
  2. Credentials: Generate an Access Key (AK) and Secret Key (SK).
  3. Token Logic: Implement a token caching mechanism. Tokens typically expire after 30 days; ensure logic exists to refresh them when necessary.

Implementation Strategy

Data Structures

Define classes to manage configuration and sensitive data separately from logic.

from pathlib import Path
from typing import Optional, Dict
import requests
from bs4 import BeautifulSoup

class AuthConfig:
    target_base: str = "https://example.com/cas"
    captcha_endpoint: str = "/cas/login?execution=e1s1"
    login_endpoint: str = "/cas/login"
    headers: Dict[str, str] = {
        "User-Agent": "Mozilla/5.0",
        "Accept": "text/html,application/xhtml+xml",
    }

class Credentials:
    username: str
    password: str

    def __init__(self, u: str, p: str):
        self.username = u
        self.password = p

Token Management

Handle the OAuth flow to retrieve the access token for the OCR API. Cache the result to avoid unnecessary network calls during development.

import json
from datetime import datetime

def get_ocr_token(ak: str, sk: str, cache_file: Path) -> str:
    api_url = f"https://aip.baidubce.com/oauth/2.0/token"
    params = {
        "grant_type": "client_credentials",
        "client_id": ak,
        "client_secret": sk
    }
    
    response = requests.get(api_url, params=params)
    token_data = response.json()
    
    if "access_token" not in token_data:
        raise Exception("Failed to retrieve token")
        
    # Write token with timestamp for expiration tracking
    with open(cache_file, "w", encoding="utf-8") as f:
        f.write(json.dumps({
            "token": token_data["access_token"],
            "timestamp": datetime.now().strftime("%Y-%m-%d")
        }))
        
    return token_data["access_token"]

CAPTCHA Processing

Download the generated image from the server endpoint and send it to the OCR service.

def extract_captcha_text(session: requests.Session, cache_dir: Path) -> str:
    # Fetch the image bytes
    img_path = cache_dir / "captcha.jpg"
    with session.get(AuthConfig.captcha_endpoint, stream=True) as resp:
        resp.raise_for_status()
        with open(img_path, "wb") as f:
            f.write(resp.content)
    
    # Encode for API transmission
    with open(img_path, "rb") as f:
        img_base64 = base64.b64encode(f.read()).decode()
        
    # Prepare OCR request payload
    ocr_params = {"image": img_base64}
    ocr_url = "https://aip.baidubce.com/rest/2.0/ocr/v1/accurate_basic"
    
    headers = {"Content-Type": "application/x-www-form-urlencoded"}
    res = session.post(ocr_url, data=ocr_params, headers=headers)
    result = res.json()
    
    return result["words_result"][0]["words"].strip()

Authentication Sequence

Initialize a persistent session to maintain cookies across requetss.

  1. Acquire CSRF/Execution Token: Visit the login page to fetch hidden input values required for submission.
  2. Process Verification: Retrieve and interpret the CAPTCHA image.
  3. Submit Payload: Send credentials along with the recognized text.
from selenium.common.exceptions import *

def login_sequence(config: AuthConfig, creds: Credentials, token_cache_path: Path) -> bool:
    session = requests.Session()
    
    # 1. Initial GET to establish session and capture execution ID
    start_resp = session.get(f"{config.target_base}{config.login_endpoint}", headers=config.headers)
    soup = BeautifulSoup(start_resp.text, "html.parser")
    execution_id = soup.find('input', {'name': 'execution'}).get('value')
    
    # 2. Prepare Login Payload
    payload = {
        "username": creds.username,
        "password": creds.password,
        "captchaCode": extract_captcha_text(session, Path.cwd()),
        "execution": execution_id,
        "_eventId": "submit",
        "geolocation": ""
    }
    
    # 3. POST Request
    final_resp = session.post(
        f"{config.target_base}{config.login_endpoint}", 
        headers=start_resp.request.headers, 
        data=payload
    )
    
    # Verify success by checking URL redirect location
    return config.target_base in final_resp.url

Validation

Post-submission analysis is critical. Success may be indicated by a status code 200, a specific URL redirection to a dashboard, or the presence of a user-profile element in the response body rather than the login form.

Tags: python automation CAS OCR Baidu-API

Posted on Sat, 31 Oct 2026 16:45:59 +0000 by rcatal02