Dev Arksoft
  • Arksoft Developer Network
  • Ağustos 2023
    • Angularda DOM (Document Object Model) Manipülasyonu
    • Angular’da Routing
    • Representational State Transfer (REST)
    • .Net Framework için Local NugetPackage
    • Agile Nedir?
  • Temmuz 2023
    • Angular HTTP Interceptors
    • Angularda Promise ve Observable
    • Mongo DB Kullanımı
  • Haziran 2023
    • Angular Validators
  • Mayıs 2023
    • Docker Uzerine Redis Kurulumu ve .Net Core ile Redise Erişim
  • Nisan 2023
    • Angular 14 Componentler Arası İletişim
  • Şubat 2023
    • JMeter ile Performans Testi
  • Ocak 2023
    • Windows Giriş Ekranında C# Form Açmak
  • Temmuz 2022
    • Regular Expressions
  • Haziran 2022
    • RSA Şifreleme
    • AutoMapper Kullanımı
    • Permutasyon ve Kombinasyon
    • Generic Repository Pattern
    • Levenshtein Algoritması
    • HTML 5’e Giriş
    • Graph Yapılar
  • Mayıs 2022
    • IQueryable IEnumerable Farklar
    • Sıralama Algoritmaları
  • Şubat 2022
    • ADFS Custom 2FA Integration
    • Reacta Giriş ve Reactın Temel Prensipleri
    • TypeScript Kullanımı
    • Serialization Kullanımı
    • Log4Net Kullanımı
    • Collections Yapıları
    • Windows Service Projesini Debug Etme ve Harici Exe Çalıştırma
    • Culture ve DateTime Kullanımı
    • Reflection Kullanımı
    • Steganografi Teknikleri
    • ElasticSearch Kullanımı
    • SWAGGER ve JWT TOKEN BASED WEBAPI Kullanımı
    • LINQ Komutları Kullanımı
    • Image Processing İşlemleri Kullanımı
Powered by GitBook
On this page
  1. Şubat 2022

SWAGGER ve JWT TOKEN BASED WEBAPI Kullanımı

Husamettin Elalmis

PreviousElasticSearch KullanımıNextLINQ Komutları Kullanımı

Last updated 2 years ago

Merhaba arkadaşlar, bu yazıda sizlere Swagger ve JWT .NetCore WebAPI yapılandırmasını anlatacağım,

Yenilikler

  • Swagger, WebAPI projelerinde kullanılan ve .netCore projelerine entegre edilebilen 3th party bir API dokumantasyon aracıdır. Bu araç, PostMan'nın yapabildiklerini kısmen yapabilmektedir. Özellikle dokumantasyon işlemlerinde standard yöntemlerin kullanılabilmesi amacıyla geliştirilmiş ve kabul görmüştür.

  • Önceki .netCore versiyonlarında (3.0, 3.1) manuel bu araç ilave olarak kurulabiliyordu ve kullanılabiliyordu

  • .netCore 5.0 ile birlikte WebAPI projelerine embedded şeklinde (nugetpackage) kurulu halde gelmektedir.

  • Swagger, bizim controller classlarımızdaki method signaturlerini otomatik olarak okuyarak ekranda kendisi UI olarak göstermektedir.

  • UI üzerinde, methodların açıklamaları ve parametrelerini görebilmekte ve istenilen method test amaçlı invoke edebilmekteyiz. (Postman usulu)

  • JWT yapılandırmasını ise, nugetpackageler ile birlikte projeye kurularak ve doğru configure ayarları yaparak entegre yapıyor olacağız. (eskiden JWT yapılandırmaları daha meşakkatli idi, MVC taraflarında bu işlemlerin configure edilmesi biraz daha karmaşık idi)

Swagger Nedir?

  • .netCore5.0 ile entegre gelen API dokumantasyon ve API Test aracıdır.

  • UI otomatik olarak oluşturulmakta ve projenin start edilmesi ile birlikte ekrana gelmektedir

  • Swagger görünümü yukarıdaki gibidir. Methodlar, controller classından otomatik olarak okunarak gelmektedir.

  • İstenilen herhangi bir metodun parametreleri görülebilir, ve invoke(test) edilebilir. Postman gibi çağırabilmekteyiz.

  • İlgili methodun parametreleri görüntülenir. Try It Out butonu ile invoke edilebilir.

  • Execute butonu ile post denemeleri yapılabilmektedir

  • Swagger, artık standard hale gelmiş bir araçtır.

JWT Nedir?

JWT, JsonWebToken anlamına gelir. Web tabanlı Json formatında Token demektir. Token, bilet anlamına gelir. Güvenlik amacıyla geliştirilmiş bir mekanizmadır. Biz, bir API çağrısını yaptığımızda bu bile tile ilgili methodu çağırabiliyor olacağız. Bileti olmayan bu methodumuzu çağıramıyor olacak. Bu mekanizma ile güvenlik sağlanması amaçlanmıştır.

JWT Hakkında Bilinmesi Gereken Temel Kavramlar

  • JWT, bir json tokendir.

  • Örnek bir jwt tokeni şöyledir, eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJoZWxhbG1pcyIsImVtYWlsIjoiaHVzYW1ldHRpbi5lbGFsbWlzQGFya3NvZnQuY29tLnRyIiwianRpIjoiODFjNWM3N2EtMjk4Ni00MDZlLWE2MzQtMDNlZGNlNzM5YzE3IiwiZXhwIjoxNjI0Nzk4ODQyLCJpc3MiOiJhcmtzb2Z0LmNvbS50ciIsImF1ZCI6ImFya3NvZnQuY29tLnRyIn0.woj4Td0GrYN8aNVmSR1zpgCtPVp2fRE1LXlSTqXobSw

  • Bu token, 3 segmentten oluşmaktadır.

    • 1.segment: Kullanılan algoritmanın tipini söyler.

    • 2.segment: Bu token üzerinde yaşayan bilgileri söyler (claims diyoruz buna)

    • 3.segment: Bu tokenin hash kodunu söyler. Hash kodu, kırılırsa token kırılmış olur. Hash kodu kırılamadığı sürece bu tokenın kırılamayacağı öngörülür. Bu tokena bilet diyoruz. Bu token ile methodlarımızı çağırıyor olacağız.

    • 3 segmentli yapının açık görünümü. ( https://jwt.io/ adresini kullanabilirsiniz)

  • Tokenlar, belirtilen süre kadar yaşar. Süresi biten token 401 yer. (UnAuthorized)

  • Tokenlerin içerisinde Dünya Standartlarında oluşturulmuş yaşayan bilgiler vardır. Bunlara claims diyoruz. (Detaylı bilgi için https://datatracker.ietf.org/doc/html/rfc7519#section-4 adresini inceleyebilirsiniz )

  • Tokeni doğrulanmış bir istek, response alabilir. Buna 200 success diyoruz. Doğrulanmamış bir token veya süresi bitmiş bir token 401 UnAuthorized hatası alır.

  • Claimsler, isteğe bağlı olarak kullanılır, en çok kullanılanlar ise UserName, UserEmail gibi bilgilerdir. Bunlar token içerisinde yaşar. Uygulama, bu claims içerisindeki bilgileri kendi logic kontrollerini yaparak dbye sorarak diğer yetki mekanizmalarını devreye alır. Bu kısım bize kalmıştır.

  • JWT tokenlar, genellikle Post edilerek methoda gönderilir. Header kısmında "Bearer" ön eki alarak bu token sunucuya gönderilir. Sunucu, bu Bearer başlıklı headerin içerisindeki token bilgisini alır ve doğrulama işlemine tabi tutar. Doğrulama sağlanırsa geriye içerik döndürülür (200), doğrulama sağlanmazsa geriye 401 UnAuthorized döner. Bu nedenle, JWT projelerinde header kısımlarında mutlaka "Bearer <token>" şeklinde çağrımlar olur. (Postman tarafında da bunu kullanıyor olacağız)

PostMan Nedir?

  • RestAPI, SOAP vb. Web tabanlı API çağrılarını test etmeye yarayan 3th parti bir araçtır.

  • Postman, yukarıdaki gibi bir IDEye sahiptir.

  • https://www.postman.com/downloads/ adresinden masaüstü sürümünü indirebilirsiniz.

  • Özellikle, Testerlar tarafından kullanılan bir araçtır. Developerlar method çağrıları yaparken, testerlar güvenlik açıkları ile ilgilenir.

Örnek Proje Yapılandırması

  • .NetCore5.0 WebAPI projesi oluşturulmuştur

  • Swashbuckle (swagger) kurulu gelmiştir, diğer nugetpackageler kurulmuştur (JWT ile ilgilidir bunlar)

AppSettings.json Yapılandırması

{


“Logging”: {


“LogLevel”: {


“Default”: “Information”,


“Microsoft”: “Warning”,


“Microsoft.Hosting.Lifetime”: “Information”

}

},


“AllowedHosts”: “*”,

 


“Jwt”: {


“Key”: “arksoft easy2patch application”,


“Issuer”: “arksoft.com.tr”

}

}

Startup.cs Yapılandırması

using Microsoft.AspNetCore.Authentication.JwtBearer;

using Microsoft.AspNetCore.Builder;

using Microsoft.AspNetCore.Hosting;

using Microsoft.Extensions.Configuration;

using Microsoft.Extensions.DependencyInjection;

using Microsoft.Extensions.Hosting;

using Microsoft.IdentityModel.Tokens;

using Microsoft.OpenApi.Models;

using System;

using System.Text;

 

namespace TestWebApi

{


public
class
Startup

{


public
Startup(IConfiguration configuration)

{

Configuration = configuration;

}

 


public IConfiguration Configuration { get; }

 


public
void ConfigureServices(IServiceCollection services)

{


// cors ayarları

services.AddCors(options =>

{

options.AddPolicy(“CorsPolicy”, builder => builder.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader().AllowCredentials());

});

 


// jwt ayarları

services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)

.AddJwtBearer(options =>

{

options.TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters

{

ValidateIssuer = true,

ValidateAudience = true,

ValidateLifetime = true,

ValidateIssuerSigningKey = true,

ValidIssuer = Configuration[“Jwt:Issuer”],

ValidAudience = Configuration[“Jwt:Issuer”],

IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration[“Jwt:Key”])),

ClockSkew = TimeSpan.Zero // bu önemli. yoksa token expire olmuyor

};

});

 

services.AddControllers();

services.AddSwaggerGen(c =>

{

c.SwaggerDoc(“v1”, new OpenApiInfo { Title = “Easy2Patch Api”, Version = “v1” });

});

}

 


public
void Configure(IApplicationBuilder app, IWebHostEnvironment env)

{


if (env.IsDevelopment())

{

app.UseDeveloperExceptionPage();

app.UseSwagger();

app.UseSwaggerUI(c => c.SwaggerEndpoint(“/swagger/v1/swagger.json”, “Easy2Patch v1”));

}

 

app.UseHttpsRedirection();

 

app.UseRouting();

 


// jwt için. Burası önemli, authorizationun üstünde olmalı

app.UseAuthentication();

 

app.UseAuthorization();

 

app.UseEndpoints(endpoints =>

{

endpoints.MapControllers();

});

}

}

}

UserModel.cs

namespace TestWebApi.Model

{


public
class
UserModel

{


public
string UserName { get; set; }


public
string Password { get; set; }


public
string Email { get; set; }

}

}

LoginRequestItem.cs

namespace TestWebApi.Model

{


public
class
LoginRequestItem

{


public
string UserName{ get; set; }


public
string Password { get; set; }

}

}

 

LoginController.cs

using Microsoft.AspNetCore.Authorization;

using Microsoft.AspNetCore.Http;

using Microsoft.AspNetCore.Mvc;

using Microsoft.Extensions.Configuration;

using Microsoft.IdentityModel.Tokens;

using System;

using System.Collections.Generic;

using System.IdentityModel.Tokens.Jwt;

using System.Linq;

using System.Security.Claims;

using System.Text;

using TestWebApi.Model;

 

namespace TestWebApi.Controllers

{

[Route(“api/[controller]”)]

[ApiController]


public
class
LoginController : ControllerBase

{


private IConfiguration _config;

 


public
LoginController(IConfiguration config)

{

_config = config;

}

 

[AllowAnonymous] // Herkese açık method

[HttpPost(“Login”)] // Uyarı: Swagger, bu şekilde istiyor yoksa hata verir.


public IActionResult Login([FromBody] LoginRequestItem obj) // LoginRequestItem obje olarak alması için. Parametre kullanmıyoruz.

{

UserModel model = new UserModel();

model.UserName = obj.UserName;

model.Password = obj.Password;

IActionResult response = Unauthorized();

 


var user = AuthenticateUser(model);

 


if (user != null)

{


var tokenStr = GenerateJSONWebToken(user); // token üretilir

response = Ok(new { token = tokenStr });

}

 


return response;

}

 


// AuthenticateUser – Login olan kullanıcıyı doğrula


private UserModel AuthenticateUser(UserModel model)

{

UserModel user = null;

 


// Burada DB seviyesinde araya girilir


if (model.UserName == “helalmis” && model.Password == “1”)

{

user = new UserModel() { UserName = “helalmis”, Password = “1”, Email = “husamettin.elalmis@arksoft.com.tr” };

}

 


return user;

}

 

[Authorize] // JWT ile çağrılsın

[HttpPost(“TestPost”)] // Uyarı: Swagger, bu şekilde istiyor yoksa hata verir.


public
string TestPost()

{


var identity = HttpContext.User.Identity as ClaimsIdentity;

IList<Claim> claim = identity.Claims.ToList();


var userName = claim[0].Value;


return
“Welcome to “ + userName;

}

 

[Authorize] // JWT ile çağrılsın

[HttpGet(“TestGet”)] // Uyarı: Swagger, bu şekilde istiyor yoksa hata verir.


public ActionResult<IEnumerable<string>> TestGet()

{


return
new
string[] { “val1”, “val2”, “val3” };

}

 

[AllowAnonymous] // Herkese açık method

[HttpGet(“TestAnonymous”)] // Uyarı: Swagger, bu şekilde istiyor yoksa hata verir.


public
string TestAnonymous()

{


return
“TestAnonymous ok”;

}

 


// GenerateJSONWebToken – token üretir


private
string GenerateJSONWebToken(UserModel user)

{


var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_config[“Jwt:Key”]));


var createndials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256);


var claims = new[]

{


new Claim(JwtRegisteredClaimNames.Sub, user.UserName),


new Claim(JwtRegisteredClaimNames.Email, user.Email),


new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),

};

 


var token = new JwtSecurityToken(

issuer: _config[“Jwt:Issuer”],

audience: _config[“Jwt:Issuer”],

claims,

expires: DateTime.Now.AddSeconds(15), // 15 sn yaşam süresi. Bu süre bize kalmış

signingCredentials: createndials

);

 


var encodeToken = new JwtSecurityTokenHandler().WriteToken(token);

 


return encodeToken;

}

}

}

Uygulamanın Test Edilmesi

  • Uygulama Run edilir, yukarıdaki ekran görünür

PostMan İle JWT Testlerinin Yapılması

  • Login testinin yapılması (401) – hatalı şifre

  • Kullanıcı adı ve şifre doğru. 200 OK. Token aldık (15 sn yaşam süresi var.)

  • Token testinin çalıştığı görülür.

  • Süresi biten token için 401 UnAuthorized alındığı görülür.

  • Anonymous çağrılarının çalıştığı görülür

  • TestGet methodunun token ile çağrıldığı görülür

  • Süresi bitmiş olan tokenin 401 aldığı görülür. (Aynı method çağrılma esnasında)

Sonuç

  • WebAPI projelerinde Swagger kullanımı standard hale gelmiştir

  • Güvenlik tarafında genellikle JWT token mekanizması kullanılmaktadır

  • Bu projede tokeni biz ürettik, bunun farklı bir versiyonu AzureAD üzerinden yapılabilir. Tüm token mekanizmaları belirtilen bir application üzerinden AzureAD üzerinden alınmasına imkan vardır. Bu google da olabilir, Amazon da olabilir. Merkezi token mekanizma sağlayan her türlü provider kullanılabilir.

  • Tumark WebAPI Cloud projesi, JWT token mekanizmasını kullanıyor olacaktır.

Saygılarımla,

Hüsamettin ELALMIŞ – 27.06.2021

husamettin.elalmis@arksoft.com.tr