Бесплатный урок с нашим репетитором!

Узнать подробнее

Новая Школа - онлайн-школа подготовки к ЕГЭ
При поддержке
Посмотреть все вопросы нейросети
Бесплатный пробный урок с репетитором

Узнай больше про репетиторов Новой Школы и запишись на бесплатный пробный урок. Мы проверим твой уровень знаний и составим план обучения по любому предмету и классу

Вопрос от Анонимного юзера 10 сентября 2025 12:23

Дай мне код авторизации

Ответ нейросети

10 сентября 2025 12:23

Задача понятна: ты хочешь увидеть рабочий пример кода, реализующий процесс авторизации по схеме Authorization Code (OAuth 2.0), чтобы понять, как это работает на практике. Ниже даю минимальный учебный пример на Python (Flask) и пояснения по шагам. Это учебный макет, не для продакшена (нет TLS, полноценных проверок и т.д.).

Цель по твоему запросу: Понять. Я сначала объясню концепцию, затем дам рабочий код и пояснения к каждому фрагменту.

Что мы сделаем

  • Реализуем простой «сервер авторизации» (Authorization Server) с двумя точками:
    • /authorize — клиент перенаправляется сюда, чтобы получить authorization code.
    • /token — клиент обменивает code на access token.
  • Реализуем небольшой «клиент» (CLI), который:
    • открывает браузер для авторизации,
    • после логина пользователя получает authorization code,
    • обменивает код на токен и выводит его.
  • Добавлю дополнительную точку /resource, чтобы проверить защиту токеном.

Установка

  • Убедись, что установлен Python 3.8+.
  • Установи Flask: pip install flask
  • (Опционально) установи requests: pip install requests
  1. Код сервера авторизации (authorization_server.py) Код ниже реализует простой OAuth2-совместимый сервер с двумя конечными точками и базовым хранилищем пользователей и клиентов.
  • Что делает:
    • /authorize: принимает параметры client_id, redirect_uri, response_type=code, state. Если пользователь не авторизован — отправляет форму входа. Если авторизован — создает authorization code и перенаправляет по redirect_uri с code и state.
    • /login: простая форма входа. После входа сохраняет в сессии пользователя и возвращает на исходную страницу.
    • /token: принимает code, client_id, client_secret, redirect_uri и возвращает access_token.
    • /resource: защищенный ресурс, доступный только по Bearer токену.

Код (authorization_server.py):

from flask import Flask, request, redirect, session, render_template_string, jsonify
import secrets, time

app = Flask(__name__)
app.secret_key = 'super_secret_key_for_demo'  # в продакшене хранить в env

# Простые данные пользователей и клиентов (для учебы)
USERS = {
    'alice': 'wonderland',
    'bob': 'builder'
}

CLIENTS = {
    'demo_client': {
        'client_secret': 'demo_secret',
        'redirect_uris': ['http://localhost:8000/callback']
    }
}

# Хранилища кодов и токенов
AUTH_CODES = {}     # code -> {client_id, redirect_uri, username, expires_at}
ACCESS_TOKENS = {}  # access_token -> {username, client_id, expires_at}

def generate_code():
    return secrets.token_urlsafe(32)

def generate_token():
    return secrets.token_urlsafe(48)

@app.route('/authorize')
def authorize():
    client_id = request.args.get('client_id')
    redirect_uri = request.args.get('redirect_uri')
    response_type = request.args.get('response_type')
    state = request.args.get('state')

    if client_id not in CLIENTS:
        return "Unknown client", 400
    if redirect_uri not in CLIENTS[client_id]['redirect_uris']:
        return "Invalid redirect_uri", 400
    if response_type != 'code':
        return "Unsupported response_type", 400

    if 'username' not in session:
        # перенаправим на страницу логина, сохранив исходник в next
        login_next = request.url
        return redirect(f'/login?next={login_next}')

    # пользователь авторизован — создаём authorization code
    code = generate_code()
    AUTH_CODES[code] = {
        'client_id': client_id,
        'redirect_uri': redirect_uri,
        'username': session['username'],
        'expires_at': time.time() + 300  # код действует 5 минут
    }

    # перенаправляем обратно к client с кодом
    redirect_with_code = f'{redirect_uri}?code={code}'
    if state:
        redirect_with_code += f'&state={state}'
    return redirect(redirect_with_code)

@app.route('/login', methods=['GET','POST'])
def login():
    if request.method == 'GET':
        next_url = request.args.get('next', '/')
        return render_template_string('''
            <h2>Login</h2>
            <form method="post">
              <input name="username" placeholder="Username"/><br/>
              <input type="password" name="password" placeholder="Password"/><br/>
              <input type="hidden" name="next" value="{{ next_url }}">
              <button type="submit">Login</button>
            </form>
        ''', next_url=next_url)

    username = request.form.get('username')
    password = request.form.get('password')
    next_url = request.form.get('next') or '/'

    if not username or USERS.get(username) != password:
        return "Invalid credentials", 401

    session['username'] = username
    return redirect(next_url)

@app.route('/token', methods=['POST'])
def token():
    grant_type = request.form.get('grant_type')
    code = request.form.get('code')
    redirect_uri = request.form.get('redirect_uri')
    client_id = request.form.get('client_id')
    client_secret = request.form.get('client_secret')

    if grant_type != 'authorization_code':
        return jsonify({'error':'unsupported_grant_type'}), 400
    if client_id not in CLIENTS:
        return jsonify({'error':'invalid_client'}), 401
    if CLIENTS[client_id]['client_secret'] != client_secret:
        return jsonify({'error':'invalid_client'}), 401
    if code not in AUTH_CODES:
        return jsonify({'error':'invalid_grant'}), 400

    code_entry = AUTH_CODES.pop(code)
    if code_entry['client_id'] != client_id:
        return jsonify({'error':'invalid_grant'}), 400
    if code_entry['redirect_uri'] != redirect_uri:
        return jsonify({'error':'invalid_grant'}), 400
    if time.time() > code_entry['expires_at']:
        return jsonify({'error':'invalid_grant'}), 400

    access_token = generate_token()
    ACCESS_TOKENS[access_token] = {
        'username': code_entry['username'],
        'client_id': client_id,
        'expires_at': time.time() + 3600
    }
    return jsonify({
        'access_token': access_token,
        'token_type': 'Bearer',
        'expires_in': 3600
    })

@app.route('/resource')
def resource():
    auth_header = request.headers.get('Authorization')
    if not auth_header or not auth_header.startswith('Bearer '):
        return jsonify({'error':'unauthorized'}), 401
    token = auth_header.split()[1]
    token_entry = ACCESS_TOKENS.get(token)
    if not token_entry or token_entry['expires_at'] < time.time():
        return jsonify({'error':'invalid_token'}), 401

    username = token_entry['username']
    return jsonify({'data': f'Hello, {username}! This is protected data.'})

if __name__ == '__main__':
    app.run(debug=True, port=5000)
  1. Клиентская часть (CLI-демонстрация) (oauth_client.py) Этот клиент демонстрирует как получить authorization code через браузер, а затем обменять его на access token. Для упрощения не пишем локальный обработчик редиректа — пользователь вручную копирует URL с кодом и вставляет в консоль.
  • Что делает:
    • формирует URL авторизации и открывает в браузере
    • после логина пользователь копирует полный redirect URL из адресной строки и вставляет в консоль
    • извлекает code и отправляет запрос на /token
    • выводит access_token и пример запроса к защищенному ресурсу

Код (oauth_client.py):

import requests
import webbrowser
import urllib.parse
from urllib.parse import urlparse, parse_qs

SERVER = 'http://127.0.0.1:5000'
CLIENT_ID = 'demo_client'
CLIENT_SECRET = 'demo_secret'
REDIRECT_URI = 'http://localhost:8000/callback'  # произвольный заглушечный URL для примера

def main():
    # Шаг 1: построить URL авторизации
    authorize_url = (
        f"{SERVER}/authorize"
        f"?response_type=code&client_id={CLIENT_ID}"
        f"&redirect_uri={urllib.parse.quote(REDIRECT_URI)}"
        f"&state=xyz"
    )
    print("Откройте этот URL в браузере для авторизации (браузер откроется автоматически):")
    print(authorize_url)
    webbrowser.open(authorize_url)

    # Шаг 2: пользователь логинится на сервере авторизации,
    # затем копирует полный redirect URL из адресной строки и вставляет сюда
    redirected = input("Вставьте полный Redirect URL после авторизации: ").strip()
    parsed = urlparse(redirected)
    code = parse_qs(parsed.query).get('code')
    if not code:
        print("Не найден параметр code в redirect URL.")
        return
    code = code[0]

    # Шаг 3: обменяем code на access_token
    token_resp = requests.post(
        f"{SERVER}/token",
        data={
            'grant_type': 'authorization_code',
            'code': code,
            'redirect_uri': REDIRECT_URI,
            'client_id': CLIENT_ID,
            'client_secret': CLIENT_SECRET
        }
    )
    if token_resp.status_code != 200:
        print("Ошибка обмена кода на токен:", token_resp.text)
        return

    token_data = token_resp.json()
    access_token = token_data['access_token']
    print("Получен access_token:", access_token)

    # Шаг 4: пример доступа к защищенному ресурсу
    resp = requests.get(
        f"{SERVER}/resource",
        headers={'Authorization': f"Bearer {access_token}"}
    )
    print("Ответ ресурса:", resp.status_code, resp.text)

if __name__ == '__main__':
    main()

Как запустить и поэтапно проверить

  • Запусти сервер авторизации:
  • Открой клиентскую часть:
    • Убедись, что в редирект URI клиента добавлен http://localhost:8000/callback в настройках клиента (в нашем примере это сделано в коде).
    • python oauth_client.py
    • Скрипт откроет браузер для авторизации. Введи учетку из USERS (alice/wonderland или bob/builder).
    • После входа в браузере адресная строка покажет редирект с параметрами code и state. Скопируй полный URL и вставь в консоль там, где просит программа.
    • Клиент обменяет code на токен и попытается обратиться к /resource, получив защищенные данные.

Пояснения по шагам

  • Что такое authorization_code?
    • Это одноразовый код, выданный пользователю после успешной аутентификации клиента и одобрения запрашиваемого доступа. Он служит временным мостом между сервером авторизации и клиентом.
  • Зачем нужен redirect_uri и state?
    • redirect_uri гарантирует, что код возвращается именно к нашему клиенту. state — дополнительный параметр защиты от CSRF; он можно использовать для валидации возвращенного запроса.
  • Как работают token и access_token?
    • После обмена кода на токен клиент получает access_token, который можно использовать для доступа к защищенным ресурсам. В реальной системе токен обычно JWT или opaque token и имеет срок жизни (expires_in).

Замечания и безопасность

  • Этот пример рассчитан на учебные цели. Он не включает HTTPS, полноценные проверки, защиту от CSRF, хранение секретов в безопасном месте и пр.
  • В продакшене обязательно используйте HTTPS, валидируйте все параметры, храните клиентские секреты в безопасном месте (например, секреты окружения), реализуйте дополнительные проверки и мониторинг.

Если хочешь, могу адаптировать пример под:

  • другой язык/фреймворк (Node.js, Django, FastAPI и т.д.)
  • полноценную oauth2-систему с поддержкой рефреш-токенов
  • упрощенную версию без Authorization Server (любой другой сценарий)

Хочешь, чтобы я адаптировал под конкретный язык или добавил UI для авторизации?

Задай свой вопрос

Напиши любую задачу или вопрос, а нейросеть её решит

Похожие вопросы 15

Бесплатно Мобильное приложение ГДЗ
Мобильное приложение ГДЗ

Задавай вопросы искуcственному интеллекту текстом или фотографиями в приложении на iPhone или Android

qr-codegoogle-playapp-store

Саша — ассистент в телеграмме

дай мне код авторизации
Задача понятна: ты хочешь увидеть рабочий пример кода, реализующий процесс авторизации по схеме Authorization Code (OAuth 2.0), чтобы понять, как это работает на практике. Ниже даю минимальный учебный пример на Python (Flask) и пояснения по шагам. Это учебный макет, не для продакшена (нет TLS, полноценных проверок и т.д.). Цель по твоему запросу: Понять. Я сначала объясню концепцию, затем дам рабочий код и пояснения к каждому фрагменту. Что мы сделаем - Реализуем простой «сервер авторизации» (Authorization Server) с двумя точками: - /authorize — клиент перенаправляется сюда, чтобы получить authorization code. - /token — клиент обменивает code на access token. - Реализуем небольшой «клиент» (CLI), который: - открывает браузер для авторизации, - после логина пользователя получает authorization code, - обменивает код на токен и выводит его. - Добавлю дополнительную точку /resource, чтобы проверить защиту токеном. Установка - Убедись, что установлен Python 3.8+. - Установи Flask: pip install flask - (Опционально) установи requests: pip install requests 1) Код сервера авторизации (authorization_server.py) Код ниже реализует простой OAuth2-совместимый сервер с двумя конечными точками и базовым хранилищем пользователей и клиентов. - Что делает: - /authorize: принимает параметры client_id, redirect_uri, response_type=code, state. Если пользователь не авторизован — отправляет форму входа. Если авторизован — создает authorization code и перенаправляет по redirect_uri с code и state. - /login: простая форма входа. После входа сохраняет в сессии пользователя и возвращает на исходную страницу. - /token: принимает code, client_id, client_secret, redirect_uri и возвращает access_token. - /resource: защищенный ресурс, доступный только по Bearer токену. Код (authorization_server.py): ```python from flask import Flask, request, redirect, session, render_template_string, jsonify import secrets, time app = Flask(__name__) app.secret_key = 'super_secret_key_for_demo' # в продакшене хранить в env # Простые данные пользователей и клиентов (для учебы) USERS = { 'alice': 'wonderland', 'bob': 'builder' } CLIENTS = { 'demo_client': { 'client_secret': 'demo_secret', 'redirect_uris': ['http://localhost:8000/callback'] } } # Хранилища кодов и токенов AUTH_CODES = {} # code -> {client_id, redirect_uri, username, expires_at} ACCESS_TOKENS = {} # access_token -> {username, client_id, expires_at} def generate_code(): return secrets.token_urlsafe(32) def generate_token(): return secrets.token_urlsafe(48) @app.route('/authorize') def authorize(): client_id = request.args.get('client_id') redirect_uri = request.args.get('redirect_uri') response_type = request.args.get('response_type') state = request.args.get('state') if client_id not in CLIENTS: return "Unknown client", 400 if redirect_uri not in CLIENTS[client_id]['redirect_uris']: return "Invalid redirect_uri", 400 if response_type != 'code': return "Unsupported response_type", 400 if 'username' not in session: # перенаправим на страницу логина, сохранив исходник в next login_next = request.url return redirect(f'/login?next={login_next}') # пользователь авторизован — создаём authorization code code = generate_code() AUTH_CODES[code] = { 'client_id': client_id, 'redirect_uri': redirect_uri, 'username': session['username'], 'expires_at': time.time() + 300 # код действует 5 минут } # перенаправляем обратно к client с кодом redirect_with_code = f'{redirect_uri}?code={code}' if state: redirect_with_code += f'&state={state}' return redirect(redirect_with_code) @app.route('/login', methods=['GET','POST']) def login(): if request.method == 'GET': next_url = request.args.get('next', '/') return render_template_string('''

Login



''', next_url=next_url) username = request.form.get('username') password = request.form.get('password') next_url = request.form.get('next') or '/' if not username or USERS.get(username) != password: return "Invalid credentials", 401 session['username'] = username return redirect(next_url) @app.route('/token', methods=['POST']) def token(): grant_type = request.form.get('grant_type') code = request.form.get('code') redirect_uri = request.form.get('redirect_uri') client_id = request.form.get('client_id') client_secret = request.form.get('client_secret') if grant_type != 'authorization_code': return jsonify({'error':'unsupported_grant_type'}), 400 if client_id not in CLIENTS: return jsonify({'error':'invalid_client'}), 401 if CLIENTS[client_id]['client_secret'] != client_secret: return jsonify({'error':'invalid_client'}), 401 if code not in AUTH_CODES: return jsonify({'error':'invalid_grant'}), 400 code_entry = AUTH_CODES.pop(code) if code_entry['client_id'] != client_id: return jsonify({'error':'invalid_grant'}), 400 if code_entry['redirect_uri'] != redirect_uri: return jsonify({'error':'invalid_grant'}), 400 if time.time() > code_entry['expires_at']: return jsonify({'error':'invalid_grant'}), 400 access_token = generate_token() ACCESS_TOKENS[access_token] = { 'username': code_entry['username'], 'client_id': client_id, 'expires_at': time.time() + 3600 } return jsonify({ 'access_token': access_token, 'token_type': 'Bearer', 'expires_in': 3600 }) @app.route('/resource') def resource(): auth_header = request.headers.get('Authorization') if not auth_header or not auth_header.startswith('Bearer '): return jsonify({'error':'unauthorized'}), 401 token = auth_header.split()[1] token_entry = ACCESS_TOKENS.get(token) if not token_entry or token_entry['expires_at'] < time.time(): return jsonify({'error':'invalid_token'}), 401 username = token_entry['username'] return jsonify({'data': f'Hello, {username}! This is protected data.'}) if __name__ == '__main__': app.run(debug=True, port=5000) ``` 2) Клиентская часть (CLI-демонстрация) (oauth_client.py) Этот клиент демонстрирует как получить authorization code через браузер, а затем обменять его на access token. Для упрощения не пишем локальный обработчик редиректа — пользователь вручную копирует URL с кодом и вставляет в консоль. - Что делает: - формирует URL авторизации и открывает в браузере - после логина пользователь копирует полный redirect URL из адресной строки и вставляет в консоль - извлекает code и отправляет запрос на /token - выводит access_token и пример запроса к защищенному ресурсу Код (oauth_client.py): ```python import requests import webbrowser import urllib.parse from urllib.parse import urlparse, parse_qs SERVER = 'http://127.0.0.1:5000' CLIENT_ID = 'demo_client' CLIENT_SECRET = 'demo_secret' REDIRECT_URI = 'http://localhost:8000/callback' # произвольный заглушечный URL для примера def main(): # Шаг 1: построить URL авторизации authorize_url = ( f"{SERVER}/authorize" f"?response_type=code&client_id={CLIENT_ID}" f"&redirect_uri={urllib.parse.quote(REDIRECT_URI)}" f"&state=xyz" ) print("Откройте этот URL в браузере для авторизации (браузер откроется автоматически):") print(authorize_url) webbrowser.open(authorize_url) # Шаг 2: пользователь логинится на сервере авторизации, # затем копирует полный redirect URL из адресной строки и вставляет сюда redirected = input("Вставьте полный Redirect URL после авторизации: ").strip() parsed = urlparse(redirected) code = parse_qs(parsed.query).get('code') if not code: print("Не найден параметр code в redirect URL.") return code = code[0] # Шаг 3: обменяем code на access_token token_resp = requests.post( f"{SERVER}/token", data={ 'grant_type': 'authorization_code', 'code': code, 'redirect_uri': REDIRECT_URI, 'client_id': CLIENT_ID, 'client_secret': CLIENT_SECRET } ) if token_resp.status_code != 200: print("Ошибка обмена кода на токен:", token_resp.text) return token_data = token_resp.json() access_token = token_data['access_token'] print("Получен access_token:", access_token) # Шаг 4: пример доступа к защищенному ресурсу resp = requests.get( f"{SERVER}/resource", headers={'Authorization': f"Bearer {access_token}"} ) print("Ответ ресурса:", resp.status_code, resp.text) if __name__ == '__main__': main() ``` Как запустить и поэтапно проверить - Запусти сервер авторизации: - python authorization_server.py - Он будет слушать на http://127.0.0.1:5000 - Открой клиентскую часть: - Убедись, что в редирект URI клиента добавлен http://localhost:8000/callback в настройках клиента (в нашем примере это сделано в коде). - python oauth_client.py - Скрипт откроет браузер для авторизации. Введи учетку из USERS (alice/wonderland или bob/builder). - После входа в браузере адресная строка покажет редирект с параметрами code и state. Скопируй полный URL и вставь в консоль там, где просит программа. - Клиент обменяет code на токен и попытается обратиться к /resource, получив защищенные данные. Пояснения по шагам - Что такое authorization_code? - Это одноразовый код, выданный пользователю после успешной аутентификации клиента и одобрения запрашиваемого доступа. Он служит временным мостом между сервером авторизации и клиентом. - Зачем нужен redirect_uri и state? - redirect_uri гарантирует, что код возвращается именно к нашему клиенту. state — дополнительный параметр защиты от CSRF; он можно использовать для валидации возвращенного запроса. - Как работают token и access_token? - После обмена кода на токен клиент получает access_token, который можно использовать для доступа к защищенным ресурсам. В реальной системе токен обычно JWT или opaque token и имеет срок жизни (expires_in). Замечания и безопасность - Этот пример рассчитан на учебные цели. Он не включает HTTPS, полноценные проверки, защиту от CSRF, хранение секретов в безопасном месте и пр. - В продакшене обязательно используйте HTTPS, валидируйте все параметры, храните клиентские секреты в безопасном месте (например, секреты окружения), реализуйте дополнительные проверки и мониторинг. Если хочешь, могу адаптировать пример под: - другой язык/фреймворк (Node.js, Django, FastAPI и т.д.) - полноценную oauth2-систему с поддержкой рефреш-токенов - упрощенную версию без Authorization Server (любой другой сценарий) Хочешь, чтобы я адаптировал под конкретный язык или добавил UI для авторизации?