0Pricing
AI Engineering Academy · บทเรียน

ความปลอดภัยและการยืนยันตัวตนของ MCP

เพิ่มการยืนยันตัวตนให้เซิร์ฟเวอร์ MCP ด้วยโทเค็น OAuth 2.0 ตรวจสอบข้อมูลนำเข้าเพื่อป้องกันการโจมตีแบบฉีดคำสั่ง และใช้หลักสิทธิ์เท่าที่จำเป็นกับสิทธิ์ของเครื่องมือ

ความปลอดภัยและการยืนยันตัวตนของ MCP เป็นบทเรียน AI Engineering Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน AI Engineering Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส AI Engineering Academy มีบทเรียนทั้งหมด 4 บทเรียน

เหตุผลที่ความปลอดภัยของ MCP สำคัญ

เซิร์ฟเวอร์ MCP คือประตูเข้าสู่ระบบต่าง ๆ ของคุณ หากไม่มีการรักษาความปลอดภัยที่เหมาะสม ไคลเอ็นต์ AI ที่ถูกบุกรุกหรือ Prompt ที่เป็นอันตรายอาจอ่านข้อมูลละเอียดอ่อน เรียกใช้การดำเนินการที่ทำลายข้อมูล หรือดึงข้อมูลออกผ่านช่องทางการเรียกใช้เครื่องมือได้ ความปลอดภัยสำหรับเซิร์ฟเวอร์ MCP ต้องใช้ การป้องกันเชิงลึกหลายชั้น ได้แก่ การตรวจสอบสิทธิ์ที่ชั้นการส่งข้อมูล การอนุญาตที่ระดับเครื่องมือ และการตรวจสอบข้อมูลนำเข้าในการเรียกใช้ทุกครั้ง

ความปลอดภัยของเซิร์ฟเวอร์ภายในเครื่องเทียบกับเซิร์ฟเวอร์ระยะไกล

การส่งข้อมูลผ่าน stdio ซึ่ง Claude Desktop ใช้ มีความปลอดภัยในตัว: เซิร์ฟเวอร์ทำงานเป็นโพรเซสภายในเครื่องและเข้าถึงได้เฉพาะผู้ใช้ที่เริ่มการทำงาน เครือข่ายที่เปิดเผยเซิร์ฟเวอร์ MCP ซึ่งใช้ HTTP/SSE ต้องเผชิญกับภัยคุกคามด้านความปลอดภัยบนเว็บอย่างเต็มรูปแบบ เช่น การข้ามการตรวจสอบสิทธิ์ การโจมตีแบบแทรกคำสั่ง และการเข้าถึงโดยไม่ได้รับอนุญาต ข้อกำหนดด้านความปลอดภัยจะแตกต่างกันอย่างมากตามรูปแบบการนำไปใช้งาน

  • stdio ภายในเครื่อง: เชื่อถือผู้ใช้ภายในเครื่อง และมุ่งเน้นการตรวจสอบข้อมูลนำเข้า
  • HTTP/SSE ระยะไกล: ใช้การตรวจสอบสิทธิ์ TLS การจำกัดอัตราการเรียกใช้ และการทำความสะอาดข้อมูลนำเข้าอย่างครบถ้วน

การตรวจสอบสิทธิ์ด้วยคีย์ API สำหรับเซิร์ฟเวอร์ระยะไกล

วิธีตรวจสอบสิทธิ์ที่ง่ายที่สุดสำหรับเซิร์ฟเวอร์ MCP ระยะไกลคือการตรวจสอบคีย์ API ผ่านส่วนหัว HTTP ตรวจสอบส่วนหัว Authorization: Bearer <token> ในคำขอขาเข้าทุกครั้ง และปฏิเสธคำขอที่ไม่ได้ผ่านการตรวจสอบสิทธิ์ด้วย HTTP 401 เก็บคีย์ API ที่ใช้ได้ไว้ในฐานข้อมูลพร้อมข้อมูลเมตาของผู้ใช้ เพื่อให้คุณเพิกถอนคีย์แต่ละรายการได้

# For HTTP/SSE MCP servers using FastAPI or similar:
from fastapi import FastAPI, HTTPException, Depends, Header
from typing import Optional
import secrets

app_http = FastAPI()

# In production: store in database with user_id, created_at, last_used
VALID_KEYS = {'sk-mcp-abc123': {'user': 'alice', 'scopes': ['read']},
              'sk-mcp-def456': {'user': 'bob', 'scopes': ['read', 'write']}}

async def verify_api_key(authorization: Optional[str] = Header(None)) -> dict:
    if not authorization or not authorization.startswith('Bearer '):
        raise HTTPException(status_code=401, detail='Missing API key')
    key = authorization.removeprefix('Bearer ')
    if key not in VALID_KEYS:
        raise HTTPException(status_code=401, detail='Invalid API key')
    return VALID_KEYS[key]  # Returns user context

# Use in route handlers:
# @app_http.get('/sse')
# async def sse_endpoint(user=Depends(verify_api_key)):

OAuth 2.0 สำหรับเซิร์ฟเวอร์ MCP ระดับองค์กร

สำหรับการนำไปใช้งานในองค์กร ให้ใช้ OAuth 2.0 เพื่อให้ผู้ใช้ตรวจสอบสิทธิ์ด้วยผู้ให้บริการข้อมูลประจำตัวขององค์กร เช่น Okta, Azure AD และ Google Workspace ไคลเอ็นต์ MCP จะรับโทเค็นการเข้าถึง OAuth แล้วใส่โทเค็นนี้ในคำขอเรียกใช้เครื่องมือ เซิร์ฟเวอร์ของคุณจะตรวจสอบลายเซ็นโทเค็นกับคีย์สาธารณะของผู้ให้บริการข้อมูลประจำตัวโดยใช้ python-jose หรือ authlib

from jose import jwt, JWTError
import httpx

AUTH_DOMAIN = 'your-tenant.auth0.com'
AUDIENCE = 'https://api.your-mcp-server.com'

async def get_jwks():
    async with httpx.AsyncClient() as client:
        resp = await client.get(f'https://{AUTH_DOMAIN}/.well-known/jwks.json')
        return resp.json()

async def verify_oauth_token(token: str) -> dict:
    jwks = await get_jwks()
    try:
        payload = jwt.decode(
            token,
            jwks,
            algorithms=['RS256'],
            audience=AUDIENCE,
            issuer=f'https://{AUTH_DOMAIN}/'
        )
        return payload  # Contains sub (user ID), scope, exp, etc.
    except JWTError as e:
        raise ValueError(f'Invalid token: {e}')

การอนุญาตตามขอบเขต

ไม่ควรให้ผู้ใช้ทุกคนใช้เครื่องมือ MCP ได้ทั้งหมด ใช้ ขอบเขต OAuth หรือข้อมูลบทบาทในโทเค็น JWT เพื่อกำหนดว่าเครื่องมือใดที่ผู้ใช้ซึ่งผ่านการตรวจสอบสิทธิ์แล้วสามารถเรียกใช้ได้ ตรวจสอบการอนุญาตตั้งแต่เริ่มต้นการเรียกใช้เครื่องมือทุกครั้ง ก่อนดำเนินการเรียกฐานข้อมูลหรือ API ใด ๆ

TOOL_REQUIRED_SCOPES = {
    'list_products': ['read:products'],
    'search_products': ['read:products'],
    'create_order': ['write:orders'],
    'delete_order': ['admin:orders']
}

def check_authorization(tool_name: str, token_payload: dict):
    '''Raise ValueError if user lacks required scope for the tool.'''
    required = TOOL_REQUIRED_SCOPES.get(tool_name, [])
    if not required:
        return  # No scope required

    user_scopes = set(token_payload.get('scope', '').split())
    missing = [s for s in required if s not in user_scopes]
    if missing:
        raise ValueError(
            f'Access denied. Tool "{tool_name}" requires scopes: {missing}. '
            f'Your token has: {list(user_scopes)}'
        )

# In call_tool handler:
# check_authorization(name, current_user_token)
# ... then execute the tool

การตรวจสอบข้อมูลนำเข้าและการป้องกันการแทรกคำสั่ง

ข้อมูลนำเข้าของเครื่องมือทั้งหมดท้ายที่สุดแล้วเป็นสตริงที่สร้างโดย LLM ให้ถือว่าข้อมูลเหล่านี้ไม่น่าเชื่อถือ ตรวจสอบข้อมูลนำเข้าทุกค่ากับชนิดและรูปแบบที่คาดไว้ก่อนใช้งาน โดยเฉพาะอย่างยิ่ง ให้ป้องกัน SQL injection ด้วยการใช้คำค้นแบบมีพารามิเตอร์และไม่ใช้ SQL ที่แทรกสตริงโดยตรง ป้องกัน command injection โดยไม่ส่งข้อมูลนำเข้าของผู้ใช้ไปยังคำสั่งเชลล์ และป้องกัน path traversal ด้วยการปรับรูปแบบและตรวจสอบเส้นทางไฟล์

import re
from pathlib import Path

BASE_DATA_DIR = Path('/data/mcp-files')

def safe_file_path(user_input: str) -> Path:
    '''Validate and normalize a file path to prevent traversal attacks.'''
    # Remove any path traversal sequences
    clean = re.sub(r'\.\./', '', user_input)
    clean = re.sub(r'\.\.\\\\', '', clean)
    path = (BASE_DATA_DIR / clean).resolve()

    # Ensure the resolved path is still within the allowed base directory
    if not str(path).startswith(str(BASE_DATA_DIR)):
        raise ValueError(f'Path traversal detected: {user_input}')

    return path

def safe_identifier(value: str) -> str:
    '''Validate a database identifier (table/column name).'''
    if not re.match(r'^[a-z_][a-z0-9_]{0,63}$', value, re.IGNORECASE):
        raise ValueError(f'Invalid identifier: {value}')
    return value

การจำกัดอัตราการเรียกใช้เครื่องมือ

เอเจนต์ LLM ที่ทำงานเป็นลูปอาจเรียกใช้เครื่องมือที่มีค่าใช้จ่ายสูงหลายร้อยครั้งต่อนาที จนทำให้การเชื่อมต่อฐานข้อมูล โควตา API ของบุคคลที่สาม หรืองบประมาณการประมวลผลหมดลง ใช้การจำกัดอัตราการเรียกใช้แยกตามผู้ใช้ด้วยอัลกอริทึมถังโทเค็นใน Redis ปฏิเสธการเรียกใช้เครื่องมือที่เกินขีดจำกัดพร้อมข้อผิดพลาดที่อธิบายชัดเจน เพื่อให้เอเจนต์ทราบว่าควรรอ

import redis
import time

r = redis.Redis.from_url('redis://localhost:6379')

def check_rate_limit(user_id: str, tool_name: str, limit: int = 60, window: int = 60) -> None:
    '''Allow at most `limit` calls per `window` seconds per user per tool.'''
    key = f'rate:{user_id}:{tool_name}'
    pipe = r.pipeline()
    pipe.incr(key)
    pipe.expire(key, window)
    count, _ = pipe.execute()

    if count > limit:
        retry_after = r.ttl(key)
        raise ValueError(
            f'Rate limit exceeded for {tool_name}. '
            f'Limit: {limit} calls/{window}s. '
            f'Retry after {retry_after} seconds.'
        )

หลักการให้สิทธิ์เท่าที่จำเป็น

ใช้ หลักการให้สิทธิ์เท่าที่จำเป็น ในทุกชั้นของเซิร์ฟเวอร์ MCP ผู้ใช้ฐานข้อมูลควรมีสิทธิ์ SELECT เท่านั้นสำหรับตารางที่เซิร์ฟเวอร์ต้องใช้ โพรเซสเซิร์ฟเวอร์ควรทำงานในฐานะผู้ใช้ OS ที่ไม่ใช่ root เครื่องมือควรขอเฉพาะสิทธิ์ที่จำเป็น คีย์ API ควรมีขอบเขตต่ำที่สุดตามวัตถุประสงค์ ทุกสิทธิ์ที่คุณไม่มอบให้คือการโจมตีที่อาจเกิดขึ้นและไม่สามารถประสบความสำเร็จได้

-- PostgreSQL: Create a dedicated read-only database user for your MCP server
CREATE ROLE mcp_reader LOGIN PASSWORD 'strong_random_password';

-- Grant SELECT on only the tables the server needs
GRANT SELECT ON products, categories, public_content TO mcp_reader;

-- Explicitly deny access to sensitive tables
REVOKE ALL ON users, api_keys, payment_methods FROM mcp_reader;

-- Never grant: INSERT, UPDATE, DELETE, TRUNCATE, or DDL permissions

TLS และความปลอดภัยของการส่งข้อมูล

เซิร์ฟเวอร์ MCP ระยะไกลต้องใช้ TLS เพื่อปกป้องข้อมูลระหว่างการส่งข้อมูล กำหนดค่าเซิร์ฟเวอร์ให้ยอมรับเฉพาะการเชื่อมต่อ HTTPS ในระบบจริง ให้ใช้พร็อกซีย้อนกลับ เช่น nginx หรือ Caddy เพื่อจัดการการสิ้นสุด TLS และอัปเดตใบรับรองให้เป็นปัจจุบันด้วยการต่ออายุอัตโนมัติ เช่น Let's Encrypt ผ่าน Certbot หรือการรองรับ ACME ในตัวของ Caddy

# Example Caddyfile for TLS-terminating MCP server at a subdomain:
#
# mcp.yourcompany.com {
#     reverse_proxy localhost:8080
#     encode gzip
#     tls internal  # Use Let's Encrypt in production
#     header {
#         Strict-Transport-Security 'max-age=31536000; includeSubDomains'
#         X-Content-Type-Options nosniff
#         X-Frame-Options DENY
#     }
# }

Prompt Injection ผ่าน Resource ของ MCP

ช่องทางการโจมตีที่แยบยลคือ เมื่อเซิร์ฟเวอร์ MCP อ่านเนื้อหาจากแหล่งข้อมูลภายนอก เช่น หน้าเว็บ ไฟล์ที่ผู้ใช้อัปโหลด หรือฐานข้อมูลที่ไม่น่าเชื่อถือ แล้วส่งคืนเนื้อหานั้นเป็นผลลัพธ์ของเครื่องมือ ผู้โจมตีอาจฝังคำสั่งที่เป็นปฏิปักษ์ไว้ในเนื้อหา โมเดลอาจทำตามคำสั่งที่ซ่อนอยู่ในข้อมูลที่ดึงมา ซึ่งเรียกว่า การแทรก Prompt ทางอ้อม ให้ทำความสะอาดเนื้อหาที่ดึงมา และอย่าส่งคืนข้อความดิบที่ไม่น่าเชื่อถือโดยตรงเป็นผลลัพธ์ของเครื่องมือ

import re

def sanitize_for_mcp_output(text: str) -> str:
    '''Remove patterns that look like instructions to the LLM.'''
    # Remove common injection patterns
    dangerous_patterns = [
        r'ignore previous instructions',
        r'ignore all prior instructions',
        r'system:',
        r'<\|.*?\|>',  # Special tokens
        r'\[INST\]',
        r'<s>',
    ]
    for pattern in dangerous_patterns:
        text = re.sub(pattern, '[FILTERED]', text, flags=re.IGNORECASE)
    return text[:10000]  # Also cap length to prevent context stuffing

การตรวจสอบและติดตามความปลอดภัย

บันทึกเหตุการณ์ทั้งหมดที่เกี่ยวข้องกับความปลอดภัย ได้แก่ การยืนยันตัวตนที่สำเร็จและล้มเหลว การละเมิดขีดจำกัดอัตรา การปฏิเสธสิทธิ์ การตรวจสอบความถูกต้องที่ผิดพลาด และรูปแบบการเข้าถึงที่ผิดปกติ ตั้งค่าการแจ้งเตือนสำหรับกรณีต่อไปนี้: การพยายามยืนยันตัวตนที่ล้มเหลวหลายครั้ง (การโจมตีแบบเดารหัสผ่าน), ผู้ใช้รายเดียวเรียกใช้เครื่องมือที่ทำลายข้อมูลอย่างรวดเร็ว และการเรียกใช้เครื่องมือใด ๆ ที่มีข้อมูลนำเข้าขนาดใหญ่มาก ตรวจสอบบันทึกการตรวจสอบเป็นประจำ และทำให้การตรวจจับความผิดปกติทำงานโดยอัตโนมัติ

ตรวจสอบความเข้าใจอย่างรวดเร็ว

ทดสอบความเข้าใจเกี่ยวกับแนวคิดด้านความปลอดภัยและการยืนยันตัวตนของ MCP

สรุปบทเรียน

ในบทเรียนนี้ คุณได้เรียนรู้ว่า เซิร์ฟเวอร์ MCP ระยะไกลต้องใช้การยืนยันตัวตนด้วย OAuth 2.0 หรือคีย์ API ในทุกคำขอ การให้สิทธิ์ตามขอบเขตจะควบคุมว่าเครื่องมือใดที่ผู้ใช้แต่ละรายซึ่งยืนยันตัวตนแล้วสามารถเรียกใช้ได้ และ ข้อมูลนำเข้าของเครื่องมือทั้งหมดต้องผ่านการตรวจสอบความถูกต้องเพื่อป้องกันการโจมตีแบบแทรกคำสั่งและการไล่ย้อนเส้นทาง บทนี้เป็นตอนจบของโมดูล MCP — บทถัดไปเราจะสำรวจกลยุทธ์การแบ่งส่วนขั้นสูงสำหรับการค้นคืน RAG ที่มีความแม่นยำสูง

คำถามที่พบบ่อย

บทเรียน “ความปลอดภัยและการยืนยันตัวตนของ MCP” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “ความปลอดภัยและการยืนยันตัวตนของ MCP” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส AI Engineering Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส AI Engineering Academy มีบทเรียนทั้งหมด 4 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “ความปลอดภัยและการยืนยันตัวตนของ MCP”

เพิ่มการยืนยันตัวตนให้เซิร์ฟเวอร์ MCP ด้วยโทเค็น OAuth 2.0 ตรวจสอบข้อมูลนำเข้าเพื่อป้องกันการโจมตีแบบฉีดคำสั่ง และใช้หลักสิทธิ์เท่าที่จำเป็นกับสิทธิ์ของเครื่องมือ คุณปฏิบัติ AI Engineering Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน AI Engineering Academy หรือไม่

ไม่จำเป็นต้องมีประสบการณ์มาก่อน AI Engineering Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน

บทเรียน “ความปลอดภัยและการยืนยันตัวตนของ MCP” ใช้เวลานานแค่ไหน

บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย

ฉันเขียนและรันโค้ดในบทเรียน AI Engineering Academy นี้ได้ไหม

ได้ บทเรียน AI Engineering Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. MCP คืออะไรและสำคัญอย่างไร
  2. การสร้างเซิร์ฟเวอร์ MCP แรกของคุณ
  3. การเปิดให้เข้าถึงทรัพยากรฐานข้อมูลผ่าน MCP
  4. ความปลอดภัยและการยืนยันตัวตนของ MCP
← กลับไปที่ AI Engineering Academy