{"id":38471,"date":"2026-01-31T21:40:49","date_gmt":"2026-01-31T18:40:49","guid":{"rendered":"https:\/\/fatihsoysal.com\/blog\/?p=38471"},"modified":"2026-01-31T21:40:49","modified_gmt":"2026-01-31T18:40:49","slug":"digitalocean-uzerinde-kimlik-dogrulamali-bir-api-olusturma","status":"publish","type":"post","link":"https:\/\/fatihsoysal.com\/blog\/digitalocean-uzerinde-kimlik-dogrulamali-bir-api-olusturma\/","title":{"rendered":"DigitalOcean \u00dczerinde Kimlik Do\u011frulamal\u0131 Bir API Olu\u015fturma"},"content":{"rendered":"<p><body><\/p>\n<h2>DigitalOcean \u00dczerinde Kimlik Do\u011frulamal\u0131 Bir API Olu\u015fturma<\/h2>\n<p>DigitalOcean, geli\u015ftiricilere bulut tabanl\u0131 sanal sunucular (Droplets), y\u00f6netilen veritabanlar\u0131, depolama ve daha bir\u00e7ok hizmet sunarak uygulamalar\u0131n h\u0131zl\u0131 ve g\u00fcvenilir bir \u015fekilde da\u011f\u0131t\u0131lmas\u0131na olanak tan\u0131yan pop\u00fcler bir bulut sa\u011flay\u0131c\u0131s\u0131d\u0131r. G\u00fcn\u00fcm\u00fcz\u00fcn modern uygulamalar\u0131 genellikle farkl\u0131 servisler aras\u0131nda veri al\u0131\u015fveri\u015fi yapmak i\u00e7in API&#8217;leri (Uygulama Programlama Aray\u00fczleri) kullan\u0131r. Ancak, bir API&#8217;nin g\u00fcvende olmas\u0131, hassas verilerin korunmas\u0131 ve yetkisiz eri\u015fimin engellenmesi a\u00e7\u0131s\u0131ndan kritik \u00f6neme sahiptir. Bu makale, DigitalOcean altyap\u0131s\u0131n\u0131 kullanarak kimlik do\u011frulamal\u0131 (authenticated) bir API&#8217;nin nas\u0131l olu\u015fturulaca\u011f\u0131n\u0131 detayl\u0131 bir \u015fekilde ele alacakt\u0131r.<\/p>\n<h3>Giri\u015f: API ve Kimlik Do\u011frulaman\u0131n \u00d6nemi<\/h3>\n<p>API&#8217;ler, farkl\u0131 yaz\u0131l\u0131m sistemlerinin birbiriyle ileti\u015fim kurmas\u0131n\u0131 sa\u011flayan bir dizi kural ve protokol b\u00fct\u00fcn\u00fcd\u00fcr. Bir mobil uygulaman\u0131n bir sunucudan veri \u00e7ekmesi, bir web sitesinin \u00fc\u00e7\u00fcnc\u00fc taraf bir \u00f6deme ge\u00e7idiyle entegre olmas\u0131 veya mikro hizmetlerin birbirleriyle konu\u015fmas\u0131 gibi senaryolarda API&#8217;ler temel bir rol oynar. RESTful API&#8217;ler, HTTP protokol\u00fcn\u00fc kullanarak kaynaklar \u00fczerinde CRUD (Create, Read, Update, Delete) i\u015flemleri ger\u00e7ekle\u015ftiren yayg\u0131n bir API t\u00fcr\u00fcd\u00fcr.<\/p>\n<p>Bir API&#8217;nin herkese a\u00e7\u0131k olmas\u0131, g\u00fcvenlik risklerini beraberinde getirir. Yetkisiz kullan\u0131c\u0131lar hassas verilere eri\u015febilir, sistemin k\u00f6t\u00fcye kullan\u0131lmas\u0131na neden olabilir veya hizmet kesintileri yaratabilir. Bu nedenle, API&#8217;lerin kimlik do\u011frulamas\u0131 ve yetkilendirme mekanizmalar\u0131 ile korunmas\u0131 zorunludur. Kimlik do\u011frulama (Authentication), bir kullan\u0131c\u0131n\u0131n veya servisin kimli\u011fini do\u011frulamak anlam\u0131na gelirken, yetkilendirme (Authorization) ise kimli\u011fi do\u011frulanm\u0131\u015f bu kullan\u0131c\u0131n\u0131n hangi kaynaklara eri\u015febilece\u011fini veya hangi i\u015flemleri yapabilece\u011fini belirler. DigitalOcean&#8217;\u0131n esnek altyap\u0131s\u0131, bu t\u00fcr g\u00fcvenli API&#8217;leri geli\u015ftirmek ve da\u011f\u0131tmak i\u00e7in ideal bir ortam sunar.<\/p>\n<h3>Temel Kavramlar<\/h3>\n<p>G\u00fcvenli bir API olu\u015fturmadan \u00f6nce, ilgili temel kavramlar\u0131 anlamak \u00f6nemlidir.<\/p>\n<h4>API Nedir?<\/h4>\n<p>API (Application Programming Interface), farkl\u0131 yaz\u0131l\u0131m bile\u015fenlerinin veya uygulamalar\u0131n birbiriyle etkile\u015fim kurmas\u0131n\u0131 sa\u011flayan bir aray\u00fczd\u00fcr. RESTful API&#8217;ler, HTTP metodlar\u0131n\u0131 (GET, POST, PUT, DELETE) kullanarak kaynaklar \u00fczerinde i\u015flem yapar ve genellikle JSON veya XML format\u0131nda veri al\u0131\u015fveri\u015fi yapar.<\/p>\n<h4>Kimlik Do\u011frulama Neden Gerekli?<\/h4>\n<p>Kimlik do\u011frulama, bir API&#8217;yi kullanan istemcinin (kullan\u0131c\u0131, ba\u015fka bir uygulama) kimli\u011fini kan\u0131tlamas\u0131 s\u00fcrecidir. Bu, a\u015fa\u011f\u0131daki nedenlerle hayati \u00f6neme sahiptir:<\/p>\n<p>*   <strong>Veri G\u00fcvenli\u011fi:<\/strong> Hassas bilgilerin yetkisiz eri\u015fime kar\u015f\u0131 korunmas\u0131.<br \/>\n*   <strong>Yetkilendirme:<\/strong> Kimli\u011fi do\u011frulanm\u0131\u015f kullan\u0131c\u0131lara belirli eri\u015fim haklar\u0131 tan\u0131mlanmas\u0131.<br \/>\n*   <strong>\u0130zlenebilirlik:<\/strong> API \u00e7a\u011fr\u0131lar\u0131n\u0131n kim taraf\u0131ndan yap\u0131ld\u0131\u011f\u0131n\u0131 takip edebilme.<br \/>\n*   <strong>Hizmet Kalitesi:<\/strong> K\u00f6t\u00fc niyetli veya a\u015f\u0131r\u0131 y\u00fcklenmelerden kaynaklanan hizmet kesintilerini \u00f6nleme.<\/p>\n<h4>Yayg\u0131n Kimlik Do\u011frulama Y\u00f6ntemleri<\/h4>\n<p>API&#8217;ler i\u00e7in \u00e7e\u015fitli kimlik do\u011frulama y\u00f6ntemleri bulunmaktad\u0131r. Her birinin kendine g\u00f6re avantajlar\u0131 ve dezavantajlar\u0131 vard\u0131r:<\/p>\n<p>*   <strong>API Anahtarlar\u0131 (API Keys):<\/strong> Genellikle uzun, rastgele dizelerden olu\u015fan anahtarlard\u0131r. \u0130stek ba\u015fl\u0131\u011f\u0131na veya sorgu parametresi olarak eklenir. Basit uygulamalar i\u00e7in yeterli olabilir ancak anahtar\u0131n \u00e7al\u0131nmas\u0131 durumunda g\u00fcvenlik zafiyeti olu\u015fturabilir. Genellikle sadece uygulaman\u0131n kimli\u011fini do\u011frulamak i\u00e7in kullan\u0131l\u0131r, son kullan\u0131c\u0131 kimli\u011fi i\u00e7in uygun de\u011fildir.<br \/>\n*   <strong>Temel Kimlik Do\u011frulama (Basic Auth):<\/strong> Kullan\u0131c\u0131 ad\u0131 ve \u015fifrenin Base64 ile kodlanarak HTTP <code>Authorization<\/code> ba\u015fl\u0131\u011f\u0131na eklenmesidir. \u015eifreleme sa\u011flamad\u0131\u011f\u0131 i\u00e7in HTTPS ile birlikte kullan\u0131lmal\u0131d\u0131r. G\u00fcvenlik a\u00e7\u0131s\u0131ndan modern uygulamalar i\u00e7in \u00f6nerilmez.<br \/>\n*   <strong>OAuth 2.0:<\/strong> Genellikle \u00fc\u00e7\u00fcnc\u00fc taraf uygulamalar\u0131n kullan\u0131c\u0131 ad\u0131na ba\u015fka bir servise eri\u015fim izni almas\u0131n\u0131 sa\u011flayan bir yetkilendirme \u00e7er\u00e7evesidir. Kimlik do\u011frulama de\u011fil, yetkilendirme mekanizmas\u0131d\u0131r. Facebook, Google gibi platformlarda yayg\u0131n olarak kullan\u0131l\u0131r. Daha karma\u015f\u0131k senaryolar i\u00e7in uygundur.<br \/>\n*   <strong>JSON Web Tokens (JWT):<\/strong> Bu makalede ana odak noktam\u0131z olacak y\u00f6ntemdir. Kullan\u0131c\u0131 kimlik bilgileri sunucu taraf\u0131ndan do\u011frulan\u0131r ve sunucu, istemciye dijital olarak imzalanm\u0131\u015f bir JWT g\u00f6nderir. \u0130stemci, sonraki t\u00fcm isteklerinde bu token&#8217;\u0131 g\u00f6ndererek kimli\u011fini kan\u0131tlar. Durumsuz (stateless) yap\u0131s\u0131 ve \u00f6l\u00e7eklenebilirli\u011fi sayesinde modern API&#8217;lerde olduk\u00e7a pop\u00fclerdir.<\/p>\n<h4>Yetkilendirme Nedir?<\/h4>\n<p>Kimlik do\u011frulama, &#8220;Sen kimsin?&#8221; sorusuna cevap verirken, yetkilendirme &#8220;Ne yapmana izin var?&#8221; sorusuna cevap verir. Bir kullan\u0131c\u0131 ba\u015far\u0131l\u0131 bir \u015fekilde kimli\u011fini do\u011frulad\u0131ktan sonra, yetkilendirme mekanizmalar\u0131 devreye girer ve kullan\u0131c\u0131n\u0131n belirli kaynaklara eri\u015fim veya belirli i\u015flemleri ger\u00e7ekle\u015ftirme hakk\u0131 olup olmad\u0131\u011f\u0131n\u0131 kontrol eder. \u00d6rne\u011fin, bir &#8220;y\u00f6netici&#8221; kullan\u0131c\u0131s\u0131n\u0131n t\u00fcm verilere eri\u015fimi varken, &#8220;normal kullan\u0131c\u0131&#8221; sadece kendi verilerine eri\u015febilir.<\/p>\n<h3>Teknoloji Se\u00e7imi ve Geli\u015ftirme Ortam\u0131<\/h3>\n<p>Kimlik do\u011frulamal\u0131 API&#8217;mizi olu\u015fturmak i\u00e7in pop\u00fcler ve DigitalOcean ile uyumlu teknolojileri se\u00e7ece\u011fiz.<\/p>\n<h4>Programlama Dili ve \u00c7er\u00e7eve<\/h4>\n<p>Bu makalede Python programlama dilini ve Flask mikro web \u00e7er\u00e7evesini kullanaca\u011f\u0131z. Flask, hafif yap\u0131s\u0131 ve esnekli\u011fi ile API geli\u015ftirmek i\u00e7in olduk\u00e7a uygun bir se\u00e7enektir. Ayr\u0131ca, JWT entegrasyonu i\u00e7in gerekli k\u00fct\u00fcphaneler de mevcuttur. Alternatif olarak Node.js (Express), Go (Gin\/Echo) veya PHP (Laravel\/Symfony) gibi diller ve \u00e7er\u00e7eveler de kullan\u0131labilir.<\/p>\n<h4>Veritaban\u0131<\/h4>\n<p>Kullan\u0131c\u0131 bilgilerini ve API verilerini depolamak i\u00e7in bir veritaban\u0131na ihtiyac\u0131m\u0131z olacak. DigitalOcean, y\u00f6netilen PostgreSQL, MySQL ve Redis veritabanlar\u0131 sunar. Bu hizmetler, veritaban\u0131 y\u00f6netimi (yedekleme, \u00f6l\u00e7ekleme, g\u00fcvenlik) y\u00fck\u00fcn\u00fc \u00fczerinizden alarak geli\u015ftirme s\u00fcrecine odaklanman\u0131z\u0131 sa\u011flar. Bu \u00f6rnekte PostgreSQL kullanaca\u011f\u0131z.<\/p>\n<h4>DigitalOcean Servisleri<\/h4>\n<p>*   <strong>Droplet (Sanal Sunucu):<\/strong> API uygulamam\u0131z\u0131 bar\u0131nd\u0131rmak i\u00e7in bir Linux sanal sunucusu. Ubuntu i\u015fletim sistemi tercih edece\u011fiz.<br \/>\n*   <strong>Managed Databases (Y\u00f6netilen Veritabanlar\u0131):<\/strong> Veritaban\u0131m\u0131z\u0131n kurulumunu, bak\u0131m\u0131n\u0131 ve g\u00fcvenli\u011fini DigitalOcean&#8217;\u0131n \u00fcstlendi\u011fi bir hizmet.<br \/>\n*   <strong>Firewalls (G\u00fcvenlik Duvarlar\u0131):<\/strong> Droplet&#8217;imize gelen ve giden trafi\u011fi kontrol etmek i\u00e7in kullan\u0131l\u0131r. Yaln\u0131zca gerekli portlara (SSH, HTTP\/S, veritaban\u0131 portu) izin vererek g\u00fcvenli\u011fi art\u0131r\u0131r.<br \/>\n*   <strong>Load Balancers (Y\u00fck Dengeleyiciler):<\/strong> (Daha b\u00fcy\u00fck projeler i\u00e7in) Birden fazla Droplet aras\u0131nda trafi\u011fi dengeleyerek y\u00fcksek eri\u015filebilirlik ve \u00f6l\u00e7eklenebilirlik sa\u011flar. \u0130lk kurulum i\u00e7in zorunlu de\u011fildir.<br \/>\n*   <strong>DNS:<\/strong> Alan ad\u0131m\u0131z\u0131 (domain) API sunucumuza y\u00f6nlendirmek i\u00e7in.<\/p>\n<h3>API Geli\u015ftirme Ad\u0131mlar\u0131: JWT ile Kimlik Do\u011frulama<\/h3>\n<p>\u015eimdi, Flask kullanarak JWT tabanl\u0131 kimlik do\u011frulamal\u0131 bir API&#8217;nin nas\u0131l olu\u015fturulaca\u011f\u0131na bakal\u0131m.<\/p>\n<h4>Proje Yap\u0131land\u0131rmas\u0131<\/h4>\n<p>\u0130lk olarak, projemiz i\u00e7in bir dizin olu\u015fturup sanal ortam\u0131 ayarlayal\u0131m ve gerekli k\u00fct\u00fcphaneleri kural\u0131m:<\/p>\n<pre><code class=\"language-bash\">mkdir my_auth_api\ncd my_auth_api\npython3 -m venv venv\nsource venv\/bin\/activate\npip install Flask Flask-SQLAlchemy PyJWT passlib psycopg2-binary python-dotenv<\/code><\/pre>\n<p>*   <code>Flask<\/code>: Web \u00e7er\u00e7evesi.<br \/>\n*   <code>Flask-SQLAlchemy<\/code>: Flask ile SQLAlchemy entegrasyonu (ORM).<br \/>\n*   <code>PyJWT<\/code>: JWT olu\u015fturma ve do\u011frulama i\u00e7in.<br \/>\n*   <code>passlib<\/code>: \u015eifreleri g\u00fcvenli bir \u015fekilde hash&#8217;lemek i\u00e7in (bcrypt).<br \/>\n*   <code>psycopg2-binary<\/code>: PostgreSQL veritaban\u0131 ba\u011flay\u0131c\u0131s\u0131.<br \/>\n*   <code>python-dotenv<\/code>: Ortam de\u011fi\u015fkenlerini y\u00f6netmek i\u00e7in.<\/p>\n<p>Proje yap\u0131s\u0131:<\/p>\n<pre><code class=\"language-\">my_auth_api\/\n\u251c\u2500\u2500 venv\/\n\u251c\u2500\u2500 .env\n\u251c\u2500\u2500 app.py\n\u251c\u2500\u2500 models.py\n\u2514\u2500\u2500 requirements.txt<\/code><\/pre>\n<p><code>requirements.txt<\/code> dosyas\u0131n\u0131 olu\u015fturmay\u0131 unutmay\u0131n: <code>pip freeze > requirements.txt<\/code><\/p>\n<p><code>.env<\/code> dosyas\u0131 hassas bilgileri saklamak i\u00e7in kullan\u0131lacak:<\/p>\n<pre><code class=\"language-\">DATABASE_URL=\"postgresql:\/\/user:password@host:port\/database\"\nSECRET_KEY=\"your_super_secret_jwt_key\"<\/code><\/pre>\n<h4>Veritaban\u0131 Modelleri (<code>models.py<\/code>)<\/h4>\n<p>Kullan\u0131c\u0131 bilgilerini saklayacak bir model tan\u0131mlayal\u0131m. \u015eifreleri d\u00fcz metin olarak de\u011fil, hash&#8217;lenmi\u015f olarak saklamak kritik \u00f6neme sahiptir.<\/p>\n<pre><code class=\"language-python\"># models.py\nfrom flask_sqlalchemy import SQLAlchemy\nfrom passlib.hash import bcrypt\n\ndb = SQLAlchemy()\n\nclass User(db.Model):\n    id = db.Column(db.Integer, primary_key=True)\n    username = db.Column(db.String(80), unique=True, nullable=False)\n    password_hash = db.Column(db.String(128), nullable=False)\n\n    def __init__(self, username, password):\n        self.username = username\n        self.set_password(password)\n\n    def set_password(self, password):\n        self.password_hash = bcrypt.hash(password)\n\n    def check_password(self, password):\n        return bcrypt.verify(password, self.password_hash)\n\n    def __repr__(self):\n        return f'<User {self.username}>'<\/code><\/pre>\n<h4>Uygulama Mant\u0131\u011f\u0131 (<code>app.py<\/code>)<\/h4>\n<p>Ana uygulama dosyam\u0131zda Flask uygulamas\u0131n\u0131 yap\u0131land\u0131racak, veritaban\u0131 ba\u011flant\u0131s\u0131n\u0131 kuracak, kullan\u0131c\u0131 kay\u0131t, giri\u015f ve korumal\u0131 rotalar\u0131 tan\u0131mlayaca\u011f\u0131z.<\/p>\n<pre><code class=\"language-python\"># app.py\nimport os\nfrom datetime import datetime, timedelta\nfrom functools import wraps\n\nimport jwt\nfrom flask import Flask, request, jsonify\nfrom dotenv import load_dotenv\n\nfrom models import db, User\n\n<h2>.env dosyas\u0131n\u0131 y\u00fckle<\/h2>\nload_dotenv()\n\napp = Flask(__name__)\n\n<h2>Ortam de\u011fi\u015fkenlerinden yap\u0131land\u0131rma<\/h2>\napp.config['SQLALCHEMY_DATABASE_URI'] = os.getenv('DATABASE_URL')\napp.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False\napp.config['SECRET_KEY'] = os.getenv('SECRET_KEY') # JWT imzalama i\u00e7in gizli anahtar\n\ndb.init_app(app)\n\n<h2>Veritaban\u0131n\u0131 olu\u015fturma (ilk \u00e7al\u0131\u015ft\u0131rmada)<\/h2>\nwith app.app_context():\n    db.create_all()\n\n<h2>JWT Do\u011frulama Decorator'\u0131<\/h2>\ndef token_required(f):\n    @wraps(f)\n    def decorated(<em>args, <\/em>*kwargs):\n        token = None\n        # \u0130stek ba\u015fl\u0131\u011f\u0131ndan token'\u0131 al\n        if 'Authorization' in request.headers:\n            token = request.headers['Authorization'].split(\" \")[1] # \"Bearer <token>\"\n\n        if not token:\n            return jsonify({'message': 'Token eksik!'}), 401\n\n        try:\n            # Token'\u0131 do\u011frula\n            data = jwt.decode(token, app.config['SECRET_KEY'], algorithms=[\"HS256\"])\n            current_user = User.query.get(data['user_id'])\n            if not current_user:\n                return jsonify({'message': 'Ge\u00e7ersiz Token!'}), 401\n        except jwt.ExpiredSignatureError:\n            return jsonify({'message': 'Token s\u00fcresi doldu!'}), 401\n        except jwt.InvalidTokenError:\n            return jsonify({'message': 'Ge\u00e7ersiz Token!'}), 401\n        except Exception as e:\n            return jsonify({'message': f'Token do\u011frulama hatas\u0131: {str(e)}'}), 401\n\n        return f(current_user, <em>args, <\/em>*kwargs)\n    return decorated\n\n<h2>Kullan\u0131c\u0131 Kay\u0131t Endpoint'i<\/h2>\n@app.route('\/register', methods=['POST'])\ndef register():\n    data = request.get_json()\n    username = data.get('username')\n    password = data.get('password')\n\n    if not username or not password:\n        return jsonify({'message': 'Kullan\u0131c\u0131 ad\u0131 ve \u015fifre gerekli!'}), 400\n\n    if User.query.filter_by(username=username).first():\n        return jsonify({'message': 'Bu kullan\u0131c\u0131 ad\u0131 zaten mevcut!'}), 409\n\n    new_user = User(username=username, password=password)\n    db.session.add(new_user)\n    db.session.commit()\n\n    return jsonify({'message': 'Kullan\u0131c\u0131 ba\u015far\u0131yla kaydedildi!'}), 201\n\n<h2>Kullan\u0131c\u0131 Giri\u015f Endpoint'i<\/h2>\n@app.route('\/login', methods=['POST'])\ndef login():\n    data = request.get_json()\n    username = data.get('username')\n    password = data.get('password')\n\n    if not username or not password:\n        return jsonify({'message': 'Kullan\u0131c\u0131 ad\u0131 ve \u015fifre gerekli!'}), 400\n\n    user = User.query.filter_by(username=username).first()\n\n    if not user or not user.check_password(password):\n        return jsonify({'message': 'Ge\u00e7ersiz kullan\u0131c\u0131 ad\u0131 veya \u015fifre!'}), 401\n\n    # JWT olu\u015ftur\n    token_payload = {\n        'user_id': user.id,\n        'exp': datetime.utcnow() + timedelta(minutes=30) # 30 dakika ge\u00e7erlilik s\u00fcresi\n    }\n    token = jwt.encode(token_payload, app.config['SECRET_KEY'], algorithm=\"HS256\")\n\n    return jsonify({'token': token}), 200\n\n<h2>Korumal\u0131 Endpoint \u00d6rne\u011fi<\/h2>\n@app.route('\/protected', methods=['GET'])\n@token_required\ndef protected_route(current_user):\n    return jsonify({\n        'message': f'Ho\u015f geldin, {current_user.username}! Bu korumal\u0131 bir i\u00e7erik.',\n        'user_id': current_user.id\n    }), 200\n\n@app.route('\/', methods=['GET'])\ndef home():\n    return jsonify({'message': 'API \u00e7al\u0131\u015f\u0131yor, kimlik do\u011frulama gerekli!'}), 200\n\nif __name__ == '__main__':\n    app.run(debug=True, host='0.0.0.0') # Geli\u015ftirme ortam\u0131 i\u00e7in debug=True<\/code><\/pre>\n<p>Bu <code>app.py<\/code> dosyas\u0131:<br \/>\n1.  Ortam de\u011fi\u015fkenlerini y\u00fckler.<br \/>\n2.  Flask uygulamas\u0131n\u0131 ve veritaban\u0131 ba\u011flant\u0131s\u0131n\u0131 yap\u0131land\u0131r\u0131r.<br \/>\n3.  <code>token_required<\/code> ad\u0131nda bir decorator tan\u0131mlar. Bu decorator, bir rotaya gelen iste\u011fin <code>Authorization<\/code> ba\u015fl\u0131\u011f\u0131nda ge\u00e7erli bir JWT olup olmad\u0131\u011f\u0131n\u0131 kontrol eder. Token&#8217;\u0131 \u00e7\u00f6zer, s\u00fcresinin dolup dolmad\u0131\u011f\u0131n\u0131 ve imzas\u0131n\u0131n ge\u00e7erli olup olmad\u0131\u011f\u0131n\u0131 kontrol eder.<br \/>\n4.  <code>\/register<\/code> endpoint&#8217;i ile yeni kullan\u0131c\u0131 kayd\u0131na izin verir. \u015eifreler <code>bcrypt<\/code> ile hash&#8217;lenir.<br \/>\n5.  <code>\/login<\/code> endpoint&#8217;i ile kullan\u0131c\u0131 ad\u0131 ve \u015fifre kontrol\u00fc yapar. Ba\u015far\u0131l\u0131 olursa, kullan\u0131c\u0131 ID&#8217;sini ve s\u00fcre sonu bilgisini i\u00e7eren bir JWT olu\u015fturup istemciye d\u00f6ner.<br \/>\n6.  <code>\/protected<\/code> endpoint&#8217;i, <code>token_required<\/code> decorator&#8217;\u0131 ile korunmu\u015ftur. Sadece ge\u00e7erli bir JWT ile eri\u015filebilir.<\/p>\n<h3>DigitalOcean \u00dczerinde Da\u011f\u0131t\u0131m (Deployment)<\/h3>\n<p>API&#8217;mizi yerel ortamda test ettikten sonra, onu DigitalOcean Droplet&#8217;imize da\u011f\u0131tma zaman\u0131.<\/p>\n<h4>Droplet Olu\u015fturma<\/h4>\n<p>1.  <strong>DigitalOcean Hesab\u0131n\u0131za Giri\u015f Yap\u0131n:<\/strong> Kontrol panelinden &#8220;Create&#8221; -> &#8220;Droplets&#8221; se\u00e7ene\u011fini t\u0131klay\u0131n.<br \/>\n2.  <strong>\u0130\u015fletim Sistemi Se\u00e7imi:<\/strong> Ubuntu 22.04 LTS (veya en son LTS s\u00fcr\u00fcm\u00fc) tercih edin.<br \/>\n3.  <strong>Plan Se\u00e7imi:<\/strong> \u0130htiya\u00e7lar\u0131n\u0131za g\u00f6re bir plan se\u00e7in (\u00f6rne\u011fin, 1GB RAM \/ 1 CPU).<br \/>\n4.  <strong>Veri Merkezi B\u00f6lgesi:<\/strong> Kullan\u0131c\u0131lar\u0131n\u0131za en yak\u0131n b\u00f6lgeyi se\u00e7in.<br \/>\n5.  <strong>Kimlik Do\u011frulama:<\/strong> SSH anahtar\u0131 ekleyin veya olu\u015fturun. Bu, Droplet&#8217;inize g\u00fcvenli bir \u015fekilde ba\u011flanman\u0131z\u0131 sa\u011flar. \u015eifre ile giri\u015f yapmak yerine SSH anahtarlar\u0131 kullanmak her zaman daha g\u00fcvenlidir.<br \/>\n6.  <strong>Droplet Olu\u015ftur:<\/strong> Droplet&#8217;inizi olu\u015fturun.<\/p>\n<h4>Sunucu Yap\u0131land\u0131rmas\u0131 ve Gerekli Yaz\u0131l\u0131mlar\u0131n Kurulumu<\/h4>\n<p>Droplet olu\u015fturulduktan sonra, SSH ile ba\u011flan\u0131n:<\/p>\n<pre><code class=\"language-bash\">ssh root@your_droplet_ip_address<\/code><\/pre>\n<p>Sunucuyu g\u00fcncelleyin ve gerekli yaz\u0131l\u0131mlar\u0131 kurun:<\/p>\n<pre><code class=\"language-bash\">sudo apt update && sudo apt upgrade -y\nsudo apt install python3-pip python3-venv git nginx -y<\/code><\/pre>\n<h4>Uygulama Kodunu Droplet&#8217;e Aktarma<\/h4>\n<p>Uygulama kodunuzu GitHub gibi bir s\u00fcr\u00fcm kontrol sistemine y\u00fcklediyseniz, Droplet \u00fczerinde klonlayabilirsiniz:<\/p>\n<pre><code class=\"language-bash\">git clone https:\/\/github.com\/your_username\/my_auth_api.git\ncd my_auth_api<\/code><\/pre>\n<p>E\u011fer yerel olarak geli\u015ftirdiyseniz, <code>scp<\/code> komutu ile aktarabilirsiniz:<\/p>\n<pre><code class=\"language-bash\">scp -r my_auth_api root@your_droplet_ip_address:\/var\/www\/<\/code><\/pre>\n<p>Sonra Droplet&#8217;e ba\u011flan\u0131p <code>\/var\/www\/my_auth_api<\/code> dizinine gidin.<\/p>\n<p>Sanal ortam\u0131 kurun ve ba\u011f\u0131ml\u0131l\u0131klar\u0131 y\u00fckleyin:<\/p>\n<pre><code class=\"language-bash\">python3 -m venv venv\nsource venv\/bin\/activate\npip install -r requirements.txt<\/code><\/pre>\n<p><code>.env<\/code> dosyan\u0131z\u0131 olu\u015fturun ve hassas bilgileri (veritaban\u0131 ba\u011flant\u0131 dizesi, gizli anahtar) buraya ekleyin. <strong>Bu dosyan\u0131n git deposuna y\u00fcklenmedi\u011finden emin olun (.gitignore kullan\u0131n).<\/strong><\/p>\n<pre><code class=\"language-bash\">nano .env<\/code><\/pre>\n<p>\u0130\u00e7eri\u011fi yerel <code>.env<\/code> dosyan\u0131zdaki gibi doldurun.<\/p>\n<h4>DigitalOcean Managed Database Olu\u015fturma ve Yap\u0131land\u0131rma<\/h4>\n<p>1.  <strong>DigitalOcean Kontrol Paneli:<\/strong> &#8220;Create&#8221; -> &#8220;Databases&#8221; se\u00e7ene\u011fini t\u0131klay\u0131n.<br \/>\n2.  <strong>Veritaban\u0131 Motoru:<\/strong> PostgreSQL se\u00e7in.<br \/>\n3.  <strong>Plan ve B\u00f6lge:<\/strong> Droplet&#8217;inizle ayn\u0131 b\u00f6lgede ve uygun bir plan\u0131 se\u00e7in.<br \/>\n4.  <strong>Veritaban\u0131 Olu\u015ftur:<\/strong> Veritaban\u0131n\u0131z\u0131 olu\u015fturun.<br \/>\n5.  <strong>Ba\u011flant\u0131 Bilgileri:<\/strong> Veritaban\u0131 olu\u015fturulduktan sonra, ba\u011flant\u0131 bilgilerini (host, port, user, password, database name) alacaks\u0131n\u0131z. Bu bilgileri <code>.env<\/code> dosyas\u0131ndaki <code>DATABASE_URL<\/code> de\u011fi\u015fkenine do\u011fru formatta girin:<br \/>\n    <code>postgresql:\/\/user:password@host:port\/database_name<\/code><\/p>\n<p><strong>G\u00fcvenlik:<\/strong> DigitalOcean Managed Database&#8217;ler varsay\u0131lan olarak g\u00fcvenlidir. Ancak, Droplet&#8217;inizin IP adresini veritaban\u0131n\u0131n &#8220;G\u00fcvenilen Kaynaklar&#8221; listesine eklemeniz gerekebilir. Bu, yaln\u0131zca Droplet&#8217;inizin veritaban\u0131na eri\u015fmesine izin verir.<\/p>\n<p>Veritaban\u0131 ba\u011flant\u0131s\u0131n\u0131 test etmek i\u00e7in:<\/p>\n<pre><code class=\"language-bash\">python3\n>>> from app import app, db\n>>> with app.app_context():\n...     db.create_all() # E\u011fer tablolar\u0131n\u0131z yoksa olu\u015fturur\n...     from models import User\n...     # Test ama\u00e7l\u0131 bir kullan\u0131c\u0131 ekleyebilirsiniz\n...     # new_user = User(username='testuser', password='password123')\n...     # db.session.add(new_user)\n...     # db.session.commit()\n...     # print(User.query.all())<\/code><\/pre>\n<h4>Gunicorn ile Uygulamay\u0131 \u00c7al\u0131\u015ft\u0131rma<\/h4>\n<p>Gunicorn, Python WSGI (Web Server Gateway Interface) uygulamalar\u0131 i\u00e7in bir HTTP sunucusudur. Flask uygulamas\u0131n\u0131 Nginx arkas\u0131nda \u00e7al\u0131\u015ft\u0131rmak i\u00e7in Gunicorn kullanaca\u011f\u0131z.<\/p>\n<pre><code class=\"language-bash\">pip install gunicorn<\/code><\/pre>\n<p>Gunicorn&#8217;\u0131 bir <code>systemd<\/code> servisi olarak yap\u0131land\u0131rarak uygulaman\u0131n arka planda s\u00fcrekli \u00e7al\u0131\u015fmas\u0131n\u0131 ve sunucu yeniden ba\u015flat\u0131ld\u0131\u011f\u0131nda otomatik olarak ba\u015flamas\u0131n\u0131 sa\u011flayabiliriz.<\/p>\n<p><code>\/etc\/systemd\/system\/myapi.service<\/code> ad\u0131nda bir dosya olu\u015fturun:<\/p>\n<pre><code class=\"language-bash\">sudo nano \/etc\/systemd\/system\/myapi.service<\/code><\/pre>\n<p>\u0130\u00e7eri\u011fi a\u015fa\u011f\u0131daki gibi doldurun (kullan\u0131c\u0131 ad\u0131n\u0131z\u0131 ve uygulama dizininizi do\u011fru ayarlay\u0131n):<\/p>\n<pre><code class=\"language-ini\">[Unit]\nDescription=Gunicorn instance to serve my_auth_api\nAfter=network.target\n\n[Service]\nUser=root # veya kendi kullan\u0131c\u0131 ad\u0131n\u0131z\nGroup=www-data # veya kendi grubunuz\nWorkingDirectory=\/var\/www\/my_auth_api\nEnvironment=\"PATH=\/var\/www\/my_auth_api\/venv\/bin\"\nExecStart=\/var\/www\/my_auth_api\/venv\/bin\/gunicorn --workers 3 --bind unix:myapi.sock -m 007 app:app\nStandardOutput=append:\/var\/log\/gunicorn_myapi.log\nStandardError=append:\/var\/log\/gunicorn_myapi.log\nRestart=always\n\n[Install]\nWantedBy=multi-user.target<\/code><\/pre>\n<p>*   <code>WorkingDirectory<\/code>: Uygulama kodunuzun bulundu\u011fu dizin.<br \/>\n*   <code>Environment=\"PATH=...\"<\/code>: Sanal ortam\u0131n\u0131z\u0131n yolunu belirtir.<br \/>\n*   <code>ExecStart<\/code>: Gunicorn&#8217;\u0131 \u00e7al\u0131\u015ft\u0131ran komut. <code>--workers 3<\/code> 3 adet worker s\u00fcreci ba\u015flat\u0131r, <code>--bind unix:myapi.sock<\/code> Gunicorn&#8217;\u0131n bir Unix soketi \u00fczerinden dinlemesini sa\u011flar (Nginx bu soket \u00fczerinden ileti\u015fim kuracak). <code>app:app<\/code> ise Flask uygulaman\u0131z\u0131n (<code>app.py<\/code> dosyas\u0131ndaki <code>app<\/code> objesi) yolunu belirtir.<\/p>\n<p>Servisi etkinle\u015ftirin ve ba\u015flat\u0131n:<\/p>\n<pre><code class=\"language-bash\">sudo systemctl daemon-reload\nsudo systemctl start myapi\nsudo systemctl enable myapi\nsudo systemctl status myapi # Durumunu kontrol edin<\/code><\/pre>\n<h4>Nginx ile Ters Proxy ve SSL<\/h4>\n<p>Nginx, Gunicorn&#8217;\u0131n \u00f6n\u00fcnde bir ters proxy g\u00f6revi g\u00f6recek, gelen HTTP\/HTTPS isteklerini Gunicorn&#8217;a y\u00f6nlendirecek ve SSL sonland\u0131rmas\u0131 sa\u011flayacakt\u0131r.<\/p>\n<p>Nginx yap\u0131land\u0131rma dosyas\u0131n\u0131 olu\u015fturun:<\/p>\n<pre><code class=\"language-bash\">sudo nano \/etc\/nginx\/sites-available\/myapi<\/code><\/pre>\n<p>\u0130\u00e7eri\u011fi a\u015fa\u011f\u0131daki gibi doldurun (alan ad\u0131n\u0131z\u0131 <code>your_domain.com<\/code> ile de\u011fi\u015ftirin):<\/p>\n<pre><code class=\"language-nginx\">server {\n    listen 80;\n    server_name your_domain.com www.your_domain.com your_droplet_ip_address;\n\n    location \/ {\n        include proxy_params;\n        proxy_pass http:\/\/unix:\/var\/www\/my_auth_api\/myapi.sock;\n    }\n}<\/code><\/pre>\n<p>Yap\u0131land\u0131rma dosyas\u0131n\u0131 etkinle\u015ftirin ve Nginx&#8217;i yeniden ba\u015flat\u0131n:<\/p>\n<pre><code class=\"language-bash\">sudo ln -s \/etc\/nginx\/sites-available\/myapi \/etc\/nginx\/sites-enabled\/\nsudo nginx -t # Yap\u0131land\u0131rma sentaks\u0131n\u0131 kontrol et\nsudo systemctl restart nginx<\/code><\/pre>\n<p>\u015eimdi API&#8217;nize HTTP \u00fczerinden eri\u015febiliyor olmal\u0131s\u0131n\u0131z (IP adresi veya alan ad\u0131 ile).<\/p>\n<p><strong>SSL Sertifikas\u0131 (HTTPS):<\/strong> API&#8217;nizin g\u00fcvenli\u011fi i\u00e7in HTTPS kullanmak zorunludur. Let&#8217;s Encrypt ve Certbot ile \u00fccretsiz SSL sertifikas\u0131 alabilirsiniz:<\/p>\n<pre><code class=\"language-bash\">sudo apt install certbot python3-certbot-nginx -y\nsudo certbot --nginx -d your_domain.com -d www.your_domain.com<\/code><\/pre>\n<p>Certbot, Nginx yap\u0131land\u0131rman\u0131z\u0131 otomatik olarak g\u00fcncelleyecek ve SSL sertifikas\u0131n\u0131 kuracakt\u0131r. Ayr\u0131ca sertifikan\u0131n otomatik yenilenmesini de ayarlayacakt\u0131r.<\/p>\n<h4>G\u00fcvenlik Duvar\u0131 (Firewall) Yap\u0131land\u0131rmas\u0131<\/h4>\n<p>DigitalOcean kontrol panelinden veya <code>ufw<\/code> (Uncomplicated Firewall) kullanarak Droplet&#8217;inizin g\u00fcvenlik duvar\u0131n\u0131 yap\u0131land\u0131r\u0131n.<\/p>\n<p><strong>DigitalOcean Firewall:<\/strong><br \/>\n*   Gelen Kurallar (Inbound Rules):<br \/>\n    *   SSH (Port 22): Yaln\u0131zca kendi IP adresinizden eri\u015fime izin verin (veya g\u00fcvenli bir IP aral\u0131\u011f\u0131).<br \/>\n    *   HTTP (Port 80): Her yerden eri\u015fime izin verin.<br \/>\n    *   HTTPS (Port 443): Her yerden eri\u015fime izin verin.<br \/>\n    *   PostgreSQL (Port 5432) veya MySQL (Port 3306): Yaln\u0131zca Droplet&#8217;inizin \u00f6zel IP adresinden eri\u015fime izin verin (e\u011fer Managed Database kullan\u0131yorsan\u0131z).<\/p>\n<p><strong>UFW (Droplet \u0130\u00e7inden):<\/strong><\/p>\n<pre><code class=\"language-bash\">sudo ufw allow OpenSSH\nsudo ufw allow 'Nginx Full' # HTTP ve HTTPS i\u00e7in\nsudo ufw enable\nsudo ufw status<\/code><\/pre>\n<p>Bu ad\u0131mlar, API&#8217;nizin DigitalOcean \u00fczerinde g\u00fcvenli bir \u015fekilde \u00e7al\u0131\u015fmas\u0131n\u0131 sa\u011flayacakt\u0131r.<\/p>\n<h3>Ek G\u00fcvenlik ve \u0130yile\u015ftirmeler<\/h3>\n<p>API&#8217;nizi da\u011f\u0131tt\u0131ktan sonra, daha fazla g\u00fcvenlik ve performans iyile\u015ftirmesi d\u00fc\u015f\u00fcnebilirsiniz.<\/p>\n<h4>Rate Limiting (Oran S\u0131n\u0131rlama)<\/h4>\n<p>API&#8217;nize gelen istek say\u0131s\u0131n\u0131 s\u0131n\u0131rlayarak DDoS sald\u0131r\u0131lar\u0131n\u0131, brute-force denemelerini ve a\u015f\u0131r\u0131 kaynak t\u00fcketimini \u00f6nleyebilirsiniz. Nginx, bu ama\u00e7la kullan\u0131labilecek yerle\u015fik <code>limit_req<\/code> mod\u00fcl\u00fcne sahiptir.<\/p>\n<p>\u00d6rnek Nginx yap\u0131land\u0131rmas\u0131:<\/p>\n<pre><code class=\"language-nginx\"># \u0130stekleri IP adresine g\u00f6re s\u0131n\u0131rla: 10r\/s (saniyede 10 istek)\nlimit_req_zone $binary_remote_addr zone=mylimit:10m rate=10r\/s;\n\nserver {\n    # ...\n    location \/ {\n        limit_req zone=mylimit burst=20 nodelay; # 20 iste\u011fe kadar patlamaya izin ver, gecikme yok\n        # ...\n    }\n}<\/code><\/pre>\n<h4>CORS Politikalar\u0131<\/h4>\n<p>E\u011fer API&#8217;niz farkl\u0131 bir alan ad\u0131ndan gelen web uygulamalar\u0131 taraf\u0131ndan kullan\u0131lacaksa, CORS (Cross-Origin Resource Sharing) politikalar\u0131n\u0131 yap\u0131land\u0131rman\u0131z gerekir. Flask-CORS gibi k\u00fct\u00fcphanelerle veya Nginx \u00fczerinden bu ayarlar\u0131 yapabilirsiniz.<\/p>\n<pre><code class=\"language-python\"># app.py (Flask-CORS ile)\nfrom flask_cors import CORS\n<h2>...<\/h2>\napp = Flask(__name__)\nCORS(app, resources={r\"\/*\": {\"origins\": \"https:\/\/your_frontend_domain.com\"}}) # Belirli bir domainden gelen isteklere izin ver\n<h2>CORS(app) # T\u00fcm domainlere izin ver (Geli\u015ftirme i\u00e7in uygun, \u00fcretimde dikkatli olun)<\/code><\/pre>\n<\/h2>\n<h4>Loglama ve \u0130zleme<\/h4>\n<p>API&#8217;nizin sa\u011fl\u0131\u011f\u0131n\u0131 ve g\u00fcvenlik olaylar\u0131n\u0131 takip etmek i\u00e7in kapsaml\u0131 loglama ve izleme \u00f6nemlidir. Gunicorn ve Nginx kendi log dosyalar\u0131n\u0131 \u00fcretir. Bu loglar\u0131 d\u00fczenli olarak kontrol etmeli veya DigitalOcean&#8217;\u0131n Monitoring hizmeti gibi ara\u00e7larla entegre etmelisiniz. Hatalar\u0131 ve anormal davran\u0131\u015flar\u0131 tespit etmek i\u00e7in log analizi ara\u00e7lar\u0131 kullanmak faydal\u0131 olacakt\u0131r.<\/p>\n<h4>Otomatik \u00d6l\u00e7eklendirme ve Y\u00fck Dengeleyiciler<\/h4>\n<p>Uygulaman\u0131z\u0131n trafi\u011fi artt\u0131\u011f\u0131nda, tek bir Droplet yetersiz kalabilir. DigitalOcean Load Balancers ve Droplet gruplar\u0131 ile uygulaman\u0131z\u0131 otomatik olarak \u00f6l\u00e7eklendirebilir, birden fazla Droplet aras\u0131nda trafi\u011fi da\u011f\u0131tarak y\u00fcksek eri\u015filebilirlik ve performans sa\u011flayabilirsiniz. Bu, daha b\u00fcy\u00fck ve kritik uygulamalar i\u00e7in olmazsa olmazd\u0131r.<\/p>\n<h4>Ortam De\u011fi\u015fkenleri ve Gizli Anahtarlar\u0131n Y\u00f6netimi<\/h4>\n<p>Hassas bilgileri (veritaban\u0131 \u015fifreleri, API anahtarlar\u0131, JWT gizli anahtarlar\u0131) do\u011frudan kod i\u00e7inde tutmaktan ka\u00e7\u0131n\u0131n. <code>.env<\/code> dosyalar\u0131 veya DigitalOcean&#8217;\u0131n &#8220;Secrets&#8221; gibi daha geli\u015fmi\u015f \u00e7\u00f6z\u00fcmlerle bu bilgileri g\u00fcvenli bir \u015fekilde y\u00f6netin. <code>python-dotenv<\/code> k\u00fct\u00fcphanesi, <code>.env<\/code> dosyas\u0131ndaki de\u011fi\u015fkenleri uygulaman\u0131za y\u00fcklemenizi sa\u011flar.<\/p>\n<h3>Sonu\u00e7<\/h3>\n<p>DigitalOcean \u00fczerinde kimlik do\u011frulamal\u0131 bir API olu\u015fturmak, uygulaman\u0131z\u0131n g\u00fcvenli\u011fini sa\u011flamak ve veri b\u00fct\u00fcnl\u00fc\u011f\u00fcn\u00fc korumak i\u00e7in kritik bir ad\u0131md\u0131r. Bu makalede, JWT tabanl\u0131 kimlik do\u011frulama mekanizmas\u0131n\u0131 kullanarak Python Flask ile bir API geli\u015ftirme s\u00fcrecini, ard\u0131ndan bu API&#8217;yi DigitalOcean Droplet \u00fczerinde Gunicorn ve Nginx ile nas\u0131l da\u011f\u0131taca\u011f\u0131m\u0131z\u0131 ad\u0131m ad\u0131m inceledik. Managed Databases gibi DigitalOcean servisleri, veritaban\u0131 y\u00f6netim y\u00fck\u00fcn\u00fc hafifleterek geli\u015ftiricilerin ana odak noktas\u0131na yo\u011funla\u015fmas\u0131n\u0131 sa\u011flar.<\/p>\n<p>G\u00fcvenli bir API sadece kimlik do\u011frulama ile s\u0131n\u0131rl\u0131 de\u011fildir; ayn\u0131 zamanda HTTPS kullan\u0131m\u0131, g\u00fcvenlik duvar\u0131 yap\u0131land\u0131rmas\u0131, oran s\u0131n\u0131rlama, d\u00fczenli g\u00fcncellemeler ve kapsaml\u0131 loglama gibi ek g\u00fcvenlik \u00f6nlemlerini de gerektirir. DigitalOcean&#8217;\u0131n sundu\u011fu esnek ve g\u00fc\u00e7l\u00fc altyap\u0131, bu gereksinimleri kar\u015f\u0131lamak ve API&#8217;nizi g\u00fcvenli, \u00f6l\u00e7eklenebilir ve y\u00fcksek performansl\u0131 bir \u015fekilde da\u011f\u0131tmak i\u00e7in ideal bir platform sunar. Bu ad\u0131mlar\u0131 takip ederek, kendi g\u00fcvenli ve kimlik do\u011frulamal\u0131 API&#8217;nizi DigitalOcean \u00fczerinde ba\u015far\u0131yla hayata ge\u00e7irebilirsiniz.<\/body><\/p>\n","protected":false},"excerpt":{"rendered":"DigitalOcean \u00dczerinde Kimlik Do\u011frulamal\u0131 Bir API Olu\u015fturma\nDigitalOcean, geli\u015ftiricilere bulut tabanl\u0131 sanal sunucular (Droplets), y\u00f6netilen v","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"csco_page_header_type":"","csco_page_load_nextpost":"","csco_page_subscribe_form":"","csco_page_contact_form":"","footnotes":""},"categories":[1401],"tags":[],"class_list":{"0":"post-38471","1":"post","2":"type-post","3":"status-publish","4":"format-standard","6":"category-git","7":"cs-entry","8":"cs-video-wrap"},"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v20.5 (Yoast SEO v25.3.1) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>DigitalOcean \u00dczerinde Kimlik Do\u011frulamal\u0131 Bir API Olu\u015fturma - Kodlar\u0131n Gizemli D\u00fcnyas\u0131<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/fatihsoysal.com\/blog\/digitalocean-uzerinde-kimlik-dogrulamali-bir-api-olusturma\/\" \/>\n<meta property=\"og:locale\" content=\"tr_TR\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"DigitalOcean \u00dczerinde Kimlik Do\u011frulamal\u0131 Bir API Olu\u015fturma\" \/>\n<meta property=\"og:description\" content=\"DigitalOcean \u00dczerinde Kimlik Do\u011frulamal\u0131 Bir API Olu\u015fturma DigitalOcean, geli\u015ftiricilere bulut tabanl\u0131 sanal sunucular (Droplets), y\u00f6netilen v\" \/>\n<meta property=\"og:url\" content=\"https:\/\/fatihsoysal.com\/blog\/digitalocean-uzerinde-kimlik-dogrulamali-bir-api-olusturma\/\" \/>\n<meta property=\"og:site_name\" content=\"Kodlar\u0131n Gizemli D\u00fcnyas\u0131\" \/>\n<meta property=\"article:published_time\" content=\"2026-01-31T18:40:49+00:00\" \/>\n<meta name=\"author\" content=\"Fatih Soysal\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Yazan:\" \/>\n\t<meta name=\"twitter:data1\" content=\"Fatih Soysal\" \/>\n\t<meta name=\"twitter:label2\" content=\"Tahmini okuma s\u00fcresi\" \/>\n\t<meta name=\"twitter:data2\" content=\"18 dakika\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/digitalocean-uzerinde-kimlik-dogrulamali-bir-api-olusturma\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/digitalocean-uzerinde-kimlik-dogrulamali-bir-api-olusturma\/\"},\"author\":{\"name\":\"Fatih Soysal\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1\"},\"headline\":\"DigitalOcean \u00dczerinde Kimlik Do\u011frulamal\u0131 Bir API Olu\u015fturma\",\"datePublished\":\"2026-01-31T18:40:49+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/digitalocean-uzerinde-kimlik-dogrulamali-bir-api-olusturma\/\"},\"wordCount\":2631,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1\"},\"articleSection\":[\"Git\"],\"inLanguage\":\"tr\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/fatihsoysal.com\/blog\/digitalocean-uzerinde-kimlik-dogrulamali-bir-api-olusturma\/#respond\"]}],\"copyrightYear\":\"2026\",\"copyrightHolder\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/digitalocean-uzerinde-kimlik-dogrulamali-bir-api-olusturma\/\",\"url\":\"https:\/\/fatihsoysal.com\/blog\/digitalocean-uzerinde-kimlik-dogrulamali-bir-api-olusturma\/\",\"name\":\"DigitalOcean \u00dczerinde Kimlik Do\u011frulamal\u0131 Bir API Olu\u015fturma - Kodlar\u0131n Gizemli D\u00fcnyas\u0131\",\"isPartOf\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#website\"},\"datePublished\":\"2026-01-31T18:40:49+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/digitalocean-uzerinde-kimlik-dogrulamali-bir-api-olusturma\/#breadcrumb\"},\"inLanguage\":\"tr\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/fatihsoysal.com\/blog\/digitalocean-uzerinde-kimlik-dogrulamali-bir-api-olusturma\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/digitalocean-uzerinde-kimlik-dogrulamali-bir-api-olusturma\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Anasayfa\",\"item\":\"https:\/\/fatihsoysal.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"DigitalOcean \u00dczerinde Kimlik Do\u011frulamal\u0131 Bir API Olu\u015fturma\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#website\",\"url\":\"https:\/\/fatihsoysal.com\/blog\/\",\"name\":\"Fatihsoysal.com\",\"description\":\"Blog - Yaz\u0131l\u0131m D\u00fcnyas\u0131 Tecr\u00fcbelerim\",\"publisher\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/fatihsoysal.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"tr\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1\",\"name\":\"Fatih Soysal\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"tr\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/fatihsoysal.com\/blog\/wp-content\/uploads\/2024\/04\/cropped-replicate-prediction-3kgg1hgjn5rgp0cf0p5tr0jw7w-1.png\",\"contentUrl\":\"https:\/\/fatihsoysal.com\/blog\/wp-content\/uploads\/2024\/04\/cropped-replicate-prediction-3kgg1hgjn5rgp0cf0p5tr0jw7w-1.png\",\"width\":512,\"height\":512,\"caption\":\"Fatih Soysal\"},\"logo\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/image\/\"},\"description\":\"Kullan\u0131m ve kodlama m\u00fckemmeliyetini odak alan uygulamalar olu\u015fturma deneyimine sahip, profesyonel olarak 15+ y\u0131l \u00fczeri deneyime sahip bir yaz\u0131l\u0131m m\u00fchendisi.\",\"url\":\"https:\/\/fatihsoysal.com\/blog\/author\/fatihsoysal\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"DigitalOcean \u00dczerinde Kimlik Do\u011frulamal\u0131 Bir API Olu\u015fturma - Kodlar\u0131n Gizemli D\u00fcnyas\u0131","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/fatihsoysal.com\/blog\/digitalocean-uzerinde-kimlik-dogrulamali-bir-api-olusturma\/","og_locale":"tr_TR","og_type":"article","og_title":"DigitalOcean \u00dczerinde Kimlik Do\u011frulamal\u0131 Bir API Olu\u015fturma","og_description":"DigitalOcean \u00dczerinde Kimlik Do\u011frulamal\u0131 Bir API Olu\u015fturma DigitalOcean, geli\u015ftiricilere bulut tabanl\u0131 sanal sunucular (Droplets), y\u00f6netilen v","og_url":"https:\/\/fatihsoysal.com\/blog\/digitalocean-uzerinde-kimlik-dogrulamali-bir-api-olusturma\/","og_site_name":"Kodlar\u0131n Gizemli D\u00fcnyas\u0131","article_published_time":"2026-01-31T18:40:49+00:00","author":"Fatih Soysal","twitter_card":"summary_large_image","twitter_misc":{"Yazan:":"Fatih Soysal","Tahmini okuma s\u00fcresi":"18 dakika"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/fatihsoysal.com\/blog\/digitalocean-uzerinde-kimlik-dogrulamali-bir-api-olusturma\/#article","isPartOf":{"@id":"https:\/\/fatihsoysal.com\/blog\/digitalocean-uzerinde-kimlik-dogrulamali-bir-api-olusturma\/"},"author":{"name":"Fatih Soysal","@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1"},"headline":"DigitalOcean \u00dczerinde Kimlik Do\u011frulamal\u0131 Bir API Olu\u015fturma","datePublished":"2026-01-31T18:40:49+00:00","mainEntityOfPage":{"@id":"https:\/\/fatihsoysal.com\/blog\/digitalocean-uzerinde-kimlik-dogrulamali-bir-api-olusturma\/"},"wordCount":2631,"commentCount":0,"publisher":{"@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1"},"articleSection":["Git"],"inLanguage":"tr","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/fatihsoysal.com\/blog\/digitalocean-uzerinde-kimlik-dogrulamali-bir-api-olusturma\/#respond"]}],"copyrightYear":"2026","copyrightHolder":{"@id":"https:\/\/fatihsoysal.com\/blog\/#organization"}},{"@type":"WebPage","@id":"https:\/\/fatihsoysal.com\/blog\/digitalocean-uzerinde-kimlik-dogrulamali-bir-api-olusturma\/","url":"https:\/\/fatihsoysal.com\/blog\/digitalocean-uzerinde-kimlik-dogrulamali-bir-api-olusturma\/","name":"DigitalOcean \u00dczerinde Kimlik Do\u011frulamal\u0131 Bir API Olu\u015fturma - Kodlar\u0131n Gizemli D\u00fcnyas\u0131","isPartOf":{"@id":"https:\/\/fatihsoysal.com\/blog\/#website"},"datePublished":"2026-01-31T18:40:49+00:00","breadcrumb":{"@id":"https:\/\/fatihsoysal.com\/blog\/digitalocean-uzerinde-kimlik-dogrulamali-bir-api-olusturma\/#breadcrumb"},"inLanguage":"tr","potentialAction":[{"@type":"ReadAction","target":["https:\/\/fatihsoysal.com\/blog\/digitalocean-uzerinde-kimlik-dogrulamali-bir-api-olusturma\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/fatihsoysal.com\/blog\/digitalocean-uzerinde-kimlik-dogrulamali-bir-api-olusturma\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Anasayfa","item":"https:\/\/fatihsoysal.com\/blog\/"},{"@type":"ListItem","position":2,"name":"DigitalOcean \u00dczerinde Kimlik Do\u011frulamal\u0131 Bir API Olu\u015fturma"}]},{"@type":"WebSite","@id":"https:\/\/fatihsoysal.com\/blog\/#website","url":"https:\/\/fatihsoysal.com\/blog\/","name":"Fatihsoysal.com","description":"Blog - Yaz\u0131l\u0131m D\u00fcnyas\u0131 Tecr\u00fcbelerim","publisher":{"@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/fatihsoysal.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"tr"},{"@type":["Person","Organization"],"@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1","name":"Fatih Soysal","image":{"@type":"ImageObject","inLanguage":"tr","@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/image\/","url":"https:\/\/fatihsoysal.com\/blog\/wp-content\/uploads\/2024\/04\/cropped-replicate-prediction-3kgg1hgjn5rgp0cf0p5tr0jw7w-1.png","contentUrl":"https:\/\/fatihsoysal.com\/blog\/wp-content\/uploads\/2024\/04\/cropped-replicate-prediction-3kgg1hgjn5rgp0cf0p5tr0jw7w-1.png","width":512,"height":512,"caption":"Fatih Soysal"},"logo":{"@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/image\/"},"description":"Kullan\u0131m ve kodlama m\u00fckemmeliyetini odak alan uygulamalar olu\u015fturma deneyimine sahip, profesyonel olarak 15+ y\u0131l \u00fczeri deneyime sahip bir yaz\u0131l\u0131m m\u00fchendisi.","url":"https:\/\/fatihsoysal.com\/blog\/author\/fatihsoysal\/"}]}},"yoast_meta":{"yoast_wpseo_title":"","yoast_wpseo_metadesc":"","yoast_wpseo_canonical":""},"amp_enabled":true,"_links":{"self":[{"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/posts\/38471","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/comments?post=38471"}],"version-history":[{"count":1,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/posts\/38471\/revisions"}],"predecessor-version":[{"id":38472,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/posts\/38471\/revisions\/38472"}],"wp:attachment":[{"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/media?parent=38471"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/categories?post=38471"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/tags?post=38471"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}