Microservice mimari ile yazılmış bir projemiz var. Bu projede api gateway için spring cloud gateway kullanıyoruz. Bir Auth microserviceine ihtiyacımız var. Kullanıcı login olduğunda bu servis ile JWT token üretmek istiyoruz. Kurguyu nasıl yapmalıyım?





Microservice mimarisi içerisinde bir Auth (Yetkilendirme) mikroservisini entegre etmek ve JWT (JSON Web Token) tabanlı kimlik doğrulaması yapmak için aşağıdaki adımları izleyebilirsiniz:


Auth Mikroservisinin Kurulumu:


Auth mikroservisini, kullanıcı kimlik doğrulama ve JWT token üretimi için sorumlu olacak şekilde tasarlayın.

Kullanıcı adı ve şifre gibi kimlik bilgilerini alacak, doğrulayacak ve başarılı bir doğrulama durumunda JWT token üretecek bir API endpoint'i oluşturun.

JWT Token Yapısı:


JWT token'lar genellikle header, payload ve signature olmak üzere üç bölümden oluşur.

payload kısmında kullanıcının kimlik bilgileri ve token'ın geçerlilik süresi gibi bilgiler bulunabilir.

signature, token'ın güvenliğini sağlamak için kullanılır ve genellikle bir sunucu tarafından saklanan gizli bir anahtar ile imzalanır.

Spring Cloud Gateway Entegrasyonu:


Spring Cloud Gateway üzerinde, gelen istekleri yakalayacak ve JWT token doğrulaması yapacak bir filtre (filter) tanımlayın.

Bu filtre, her istek için HTTP başlıklarında yer alan JWT token'ı kontrol eder ve geçerli ise isteği ilgili mikroservise yönlendirir.

Eğer token geçersiz veya yoksa, hata mesajı döndürerek erişimi engelleyin.

Güvenlik ve Performans:


Token doğrulama işlemi, performansı etkileyebileceğinden, gerektiğinde önbellekleme (caching) stratejileri kullanılabilir.

Güvenlik açısından, JWT token'ların güvenli bir şekilde saklanmasına ve iletilmesine dikkat edin (örneğin, HTTPS üzerinden iletim).

Test ve Devreye Alma:


Sistemi farklı senaryolar altında test edin, örneğin geçersiz veya süresi dolmuş token'larla erişim denemeleri yapın.

Tüm servisler arasındaki entegrasyonun düzgün çalıştığından emin olun ve gerekli durumda hata ayıklama yapın.

Bu süreci uygularken, özellikle güvenlik ve sistem performansı gibi konularda dikkatli olmanız önemlidir. Ayrıca, JWT token'ların güvenliğini artırmak için ileri seviye teknikler (örneğin, token döndürme, token sızıntılarını önleme) üzerinde de çalışabilirsiniz.


Yani kullanıcı doğrulamasını ve token üretimini auth mikro servisinde yapacağım. Token kontrolünü de gateway'de yapacağım.


Evet, doğru anlamışsınız. Özetle:


Kullanıcı Doğrulaması ve Token Üretimi (Auth Mikroservis):


Kullanıcıların kimlik bilgilerini alacak ve doğrulayacak bir API endpoint'i tasarlayın.

Kullanıcı doğrulandığında, JWT token üreten bir mekanizma kurun. Bu token, kullanıcının kimlik bilgilerini ve belki de yetkilerini içerecek şekilde yapılandırılmalıdır.

Token, güvenlik açısından önemli olduğundan, güvenli bir şekilde üretilmeli ve imzalanmalıdır.

Token Kontrolü (Spring Cloud Gateway):


Spring Cloud Gateway üzerinde, gelen isteklerin HTTP başlıklarını kontrol edecek ve JWT token'ı doğrulayacak bir filtre oluşturun.

Bu filtre, token'ın geçerliliğini ve bütünlüğünü kontrol eder. Eğer token geçerliyse, isteği ilgili mikroservise yönlendirir.

Geçersiz veya eksik token durumlarında, hata mesajı döndürerek erişimi engelleyin.

Bu yapıyı uygularken, aşağıdaki noktalara dikkat etmeniz faydalı olacaktır:


Güvenlik: JWT token'larının güvenli bir şekilde saklanması ve iletilmesi önemlidir. Özellikle, token'ların üçüncü taraf saldırılarına karşı korunması için HTTPS gibi güvenli protokoller kullanılmalıdır.

Performans: Token doğrulama işlemi her istekle gerçekleşeceği için, performansı göz önünde bulundurun. Gerekirse önbellekleme mekanizmaları kullanarak işlem süresini optimize edin.

Elastiklik ve Ölçeklenebilirlik: Sisteminizin yük altında nasıl performans gösterdiğini test edin ve gerekli durumlarda ölçeklendirme stratejileri geliştirin.

Bu yapının başarılı bir şekilde uygulanması, sisteminizin güvenliğini ve kullanıcı deneyimini önemli ölçüde artıracaktır.


Peki birçok microserviceim ve bu servislerin çeşitli endpointleri var. Authoraziztion kontrolünü yine gateay'de mi yapmalıyım?


Evet, mikroservis mimarisinde yetkilendirme (authorization) kontrolünü API Gateway seviyesinde yapmak, genellikle tercih edilen bir yaklaşımdır. Bu yaklaşımın birçok avantajı vardır:


Merkezi Yönetim:


Tüm yetkilendirme kontrollerinin API Gateway üzerinde merkezileştirilmesi, yönetimi kolaylaştırır ve güvenlik politikalarını tutarlı bir şekilde uygulamanıza olanak tanır.

Güvenlik:


Yetkilendirme, sistem güvenliğinin kritik bir parçasıdır. API Gateway, güvenlik katmanı olarak hareket ederek, yetkisiz erişimleri önlemede önemli bir rol oynar.

Yeniden Kullanılabilirlik ve Entegrasyon Kolaylığı:


Aynı yetkilendirme kurallarını farklı mikroservisler için tekrar tekrar yazmak yerine, bu kuralları API Gateway'de bir kez tanımlayarak tüm servisler için kullanabilirsiniz.

Ölçeklenebilirlik ve Performans:


Yetkilendirme işlemlerinin API Gateway'de yapılması, mikroservislerin yükünü azaltır ve sistemin genel performansını ve ölçeklenebilirliğini artırır.

Esneklik:


Farklı mikroservisler için farklı yetkilendirme politikaları uygulamak istediğinizde, bu değişiklikleri tek bir noktada, yani API Gateway'de yapmak daha esnek bir yaklaşım sunar.

Yetkilendirme kontrolünü API Gateway'de yaparken aşağıdaki noktaları göz önünde bulundurmalısınız:


Rol Tabanlı Erişim Kontrolü (RBAC): Kullanıcıların rollerine göre hangi servis veya endpoint'lere erişebileceğini belirleyin.

İnce Taneli Yetkilendirme: Bazı durumlarda, daha ince taneli yetkilendirme kontrolleri gerekebilir. Bu, özellikle kullanıcıların belirli verilere veya işlevlere erişim seviyelerinin farklı olduğu durumlarda önemlidir.

Token Analizi ve Politika Uygulama: Kullanıcıdan alınan JWT token'ı analiz ederek, içerdiği bilgilere (örneğin, roller, izinler) göre isteklere izin verin veya reddedin.

Güvenlik ve Hata Yönetimi: Yetkilendirme sürecinde güvenlik açıklarını önlemek ve olası hataları düzgün bir şekilde yönetmek için dikkatli olun.

Bu yaklaşım, mikroservis mimarinizin genel güvenliğini ve yönetilebilirliğini artıracak ve sistem genelinde tutarlı bir yetkilendirme politikası sağlayacaktır.


Bu security mimarisi için Örnek bit uygulamanın önce api gatewayini kodlar mısın?


Elbette, basit bir Spring Cloud Gateway tabanlı API Gateway örneği oluşturalım. Bu örnek, Spring Cloud Gateway'i kullanarak basit bir yönlendirme ve JWT tabanlı yetkilendirme filtresi içerecek. Bu örnek, JWT token'larını doğrulamak için bir yetkilendirme servisi (Auth Service) ile iletişime geçmeyecek, ancak token'ın yapısını ve geçerliliğini kontrol edecek şekilde yapılandırılacak. Gerçek bir uygulamada, Auth Service ile iletişim kurarak token doğrulaması yapmanız gerekecektir.


Proje Yapısı

Örnek bir Spring Cloud Gateway uygulaması için temel bir Maven proje yapısı aşağıdaki gibi olacaktır:


plaintext

Copy code

my-gateway-service/

├── src/

│   ├── main/

│   │   ├── java/

│   │   │   └── com/

│   │   │       └── myapp/

│   │   │           ├── MyGatewayServiceApplication.java

│   │   │           └── config/

│   │   │               └── GatewayConfig.java

│   │   └── resources/

│   │       └── application.yml

└── pom.xml

Adım 1: Maven Bağımlılıkları

pom.xml dosyasına Spring Cloud Gateway ve JWT için gerekli bağımlılıkları ekleyin:


xml

Copy code

<dependencies>

    <dependency>

        <groupId>org.springframework.cloud</groupId>

        <artifactId>spring-cloud-starter-gateway</artifactId>

    </dependency>

    <dependency>

        <groupId>io.jsonwebtoken</groupId>

        <artifactId>jjwt-api</artifactId>

        <version>0.11.2</version>

    </dependency>

    <dependency>

        <groupId>io.jsonwebtoken</groupId>

        <artifactId>jjwt-impl</artifactId>

        <version>0.11.2</version>

        <scope>runtime</scope>

    </dependency>

    <dependency>

        <groupId>io.jsonwebtoken</groupId>

        <artifactId>jjwt-jackson</artifactId>

        <version>0.11.2</version>

        <scope>runtime</scope>

    </dependency>

    <!-- Diğer gerekli bağımlılıklar -->

</dependencies>

Adım 2: Uygulama Başlangıç Sınıfı

MyGatewayServiceApplication.java dosyasında Spring Boot uygulamasını başlatın:


java

Copy code

package com.myapp;


import org.springframework.boot.SpringApplication;

import org.springframework.boot.autoconfigure.SpringBootApplication;


@SpringBootApplication

public class MyGatewayServiceApplication {


    public static void main(String[] args) {

        SpringApplication.run(MyGatewayServiceApplication.class, args);

    }

}

Adım 3: Gateway Yapılandırması

GatewayConfig.java dosyasında bir route yapılandırması ve JWT doğrulama filtresi tanımlayın:


java

Copy code

package com.myapp.config;


import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

import org.springframework.cloud.gateway.route.RouteLocator;

import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;


@Configuration

public class GatewayConfig {


    @Bean

    public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {

        return builder.routes()

                .route("path_route", r -> r.path("/service/**")

                        .filters(f -> f.filter(new JwtAuthenticationFilter()))

                        .uri("lb://SERVICE-NAME"))

                // Diğer route tanımlamaları

                .build();

    }

}

Adım 4: JWT Doğrulama Filtresi

JWT doğrulama filtresini (JwtAuthenticationFilter) ayrı bir sınıf olarak oluşturun. Bu filtre, gelen isteklerdeki JWT token'ları doğrulayacaktır. Bu örnek, token doğrulamanın nasıl yapılacağını göstermektedir; gerçek bir uygulamada token içeriğini ve imzasını doğrulamanız gerekir:


java

Copy code

package com.myapp.config;


import org.springframework.cloud.gateway.filter.GatewayFilter;

import org.springframework.cloud.gateway.filter.GatewayFilterChain;

import org.springframework.web.server.ServerWebExchange;

import reactor.core.publisher.Mono;


public class JwtAuthenticationFilter implements GatewayFilter {


    @Override

    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {

        // JWT token'ı doğrul


java

Copy code

        // JWT token'ı doğrulama işlemi

        String token = exchange.getRequest().getHeaders().getFirst("Authorization");


        if (token == null || !validateToken(token)) {

            exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);

            return exchange.getResponse().setComplete();

        }


        return chain.filter(exchange);

    }


    private boolean validateToken(String token) {

        // Burada, token'ın geçerliliğini kontrol edin.

        // Bu örnekte basit bir kontrol yapılıyor. Gerçek bir uygulamada,

        // token'ın imzasını, süresini ve içeriğini doğrulamanız gerekecektir.

        return token != null && token.startsWith("Bearer ");

    }

}

Adım 5: Uygulama Yapılandırma Dosyası (application.yml)

application.yml dosyasında, Gateway'in dinleyeceği port ve diğer ayarları yapılandırın:


yaml

Copy code

spring:

  cloud:

    gateway:

      routes:

        - id: service_route

          uri: lb://SERVICE-NAME

          predicates:

            - Path=/service/**

          filters:

            - JwtAuthenticationFilter

  application:

    name: my-gateway-service


server:

  port: 8080

Notlar ve Öneriler

Bu örnek, JWT token'larının basit bir şekilde doğrulanmasını göstermektedir. Gerçek bir uygulamada, token'ın imzasını ve süresini kontrol etmek ve token içeriğine göre yetkilendirme yapmak için daha karmaşık bir doğrulama işlemi gerekir.

JwtAuthenticationFilter sınıfı, token doğrulama mantığınızı içerecektir. Bu örnekte, token'ın varlığı ve formatı kontrol ediliyor. Gerçek bir uygulamada, buraya token'ı çözümleme ve doğrulama işlemlerini eklemelisiniz.

Spring Cloud Gateway, dinamik yönlendirme, hız sınırlama, devre kesici desenleri ve daha birçok özellik sunar. İhtiyacınıza göre bu özellikleri araştırıp projenize ekleyebilirsiniz.

Güvenliğinizi artırmak için, HTTPS kullanmayı ve JWT token'larınız için güvenli bir imza mekanizması kullanmayı düşünün.

Bu örnek, bir Spring Cloud Gateway tabanlı API Gateway'in temel yapısını ve JWT tabanlı yetkilendirme filtresinin nasıl ekleneceğini göstermektedir. Gerçek dünya uygulamalarında, daha karmaşık senaryolar ve güvenlik gereksinimleri olacaktır. Bu nedenle, projenizin özel ihtiyaçlarına göre ek ayarlamalar ve güvenlik kontrolleri yapmanız önemlidir.


Bu security mimarisi için Örnek bir auth service kodlar mısın?


Tabii ki, bir örnek Auth Service uygulaması oluşturmak için Spring Boot ve Spring Security kullanabiliriz. Bu servis, kullanıcı kimlik bilgilerini doğrular ve başarılı kimlik doğrulaması sonrasında bir JWT token üretir. Aşağıda basit bir Auth Service örneği sunuyorum.


Proje Yapısı

Örnek bir Spring Boot Auth Service projesi için temel bir Maven proje yapısı:


plaintext

Copy code

auth-service/

├── src/

│   ├── main/

│   │   ├── java/

│   │   │   └── com/

│   │   │       └── myapp/

│   │   │           ├── AuthServiceApplication.java

│   │   │           ├── config/

│   │   │           │   └── SecurityConfig.java

│   │   │           ├── controller/

│   │   │           │   └── AuthenticationController.java

│   │   │           └── service/

│   │   │               └── JwtTokenService.java

│   │   └── resources/

│   │       └── application.yml

└── pom.xml

Adım 1: Maven Bağımlılıkları

pom.xml dosyasına Spring Boot ve JWT için gerekli bağımlılıkları ekleyin:


xml

Copy code

<dependencies>

    <dependency>

        <groupId>org.springframework.boot</groupId>

        <artifactId>spring-boot-starter-security</artifactId>

    </dependency>

    <dependency>

        <groupId>org.springframework.boot</groupId>

        <artifactId>spring-boot-starter-web</artifactId>

    </dependency>

    <dependency>

        <groupId>io.jsonwebtoken</groupId>

        <artifactId>jjwt-api</artifactId>

        <version>0.11.2</version>

    </dependency>

    <dependency>

        <groupId>io.jsonwebtoken</groupId>

        <artifactId>jjwt-impl</artifactId>

        <version>0.11.2</version>

        <scope>runtime</scope>

    </dependency>

    <dependency>

        <groupId>io.jsonwebtoken</groupId>

        <artifactId>jjwt-jackson</artifactId>

        <version>0.11.2</version>

        <scope>runtime</scope>

    </dependency>

    <!-- Diğer gerekli bağımlılıklar -->

</dependencies>

Adım 2: Uygulama Başlangıç Sınıfı

AuthServiceApplication.java dosyasında Spring Boot uygulamasını başlatın:


java

Copy code

package com.myapp;


import org.springframework.boot.SpringApplication;

import org.springframework.boot.autoconfigure.SpringBootApplication;


@SpringBootApplication

public class AuthServiceApplication {


    public static void main(String[] args) {

        SpringApplication.run(AuthServiceApplication.class, args);

    }

}

Adım 3: Güvenlik Yapılandırması

SecurityConfig.java dosyasında Spring Security yapılandırmasını yapın:


java

Copy code

package com.myapp.config;


import org.springframework.context.annotation.Configuration;

import org.springframework.security.config.annotation.web.builders.HttpSecurity;

import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;

import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;


@Configuration

@EnableWebSecurity

public class SecurityConfig extends WebSecurityConfigurerAdapter {


    @Override

    protected void configure(HttpSecurity http) throws Exception {

        http.csrf().disable()

            .authorizeRequests()

            .antMatchers("/authenticate").permitAll()

            .anyRequest().authenticated();

    }

}

Adım 4: Authentication Controller

AuthenticationController.java dosyasında, kullanıcı kimlik doğrulamasını ve JWT token üretimini yöneten bir controller oluşturun:


java

Copy code

package com.myapp.controller;


import org.springframework.web.bind.annotation.PostMapping;

import org.springframework.web.bind.annotation.RequestBody;

import org.springframework.web.bind.annotation.RestController;

import com.myapp.service.JwtTokenService;


@RestController

public class AuthenticationController {


    private final JwtTokenService jwtTokenService;


    public AuthenticationController(JwtTokenService jwtTokenService) {

        this.jwtTokenService = jwtTokenService;

    }


    @PostMapping("/authenticate")

    public String createToken(@RequestBody UserCredentials credentials) {

        // Burada kullanıcı doğrulaması yapın. Örnek için basit bir kontrol:

        if ("user".equals(credentials.getUsername()) && "password".equals(credentials.getPassword())) {

            return jwtTokenService.generateToken(credentials.getUsername());

        } else {

            throw new RuntimeException("Invalid credentials");

        }

    }

}

Adım 5: JWT Token Servisi

JwtTokenService.java dosyasında, JWT token olarak, JWT token'ları üreten bir servis oluşturun. Bu servis, kullanıcı bilgilerini temel alarak güvenli bir token üretir:


java

Copy code

package com.myapp.service;


import io.jsonwebtoken.Jwts;

import io.jsonwebtoken.SignatureAlgorithm;

import org.springframework.stereotype.Service;


import java.util.Date;

import java.util.HashMap;

import java.util.Map;


@Service

public class JwtTokenService {


    private static final String SECRET_KEY = "your_secret_key"; // Güvenli bir anahtar kullanın

    private static final long EXPIRATION_TIME = 900_000; // Token süresi (örneğin 15 dakika)


    public String generateToken(String username) {

        Map<String, Object> claims = new HashMap<>();

        claims.put("sub", username);

        return Jwts.builder()

                .setClaims(claims)

                .setIssuer("YourApp")

                .setIssuedAt(new Date(System.currentTimeMillis()))

                .setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME))

                .signWith(SignatureAlgorithm.HS512, SECRET_KEY)

                .compact();

    }

}

Adım 6: Uygulama Yapılandırma Dosyası (application.yml)

application.yml dosyasında, Auth Service uygulamasının çalışacağı portu ve diğer ayarları yapılandırın:


yaml

Copy code

spring:

  application:

    name: auth-service


server:

  port: 8081

Notlar ve Öneriler

Bu örnek, basit bir kullanıcı adı ve şifre doğrulaması yapıyor ve başarılı kimlik doğrulaması sonrası bir JWT token üretiyor. Gerçek bir uygulamada, kullanıcı bilgilerini bir veritabanı veya başka bir kaynaktan doğrulamanız gerekecektir.

JwtTokenService sınıfında, JWT token'ın imzalanması ve süresi gibi güvenlikle ilgili önemli parametreler bulunmaktadır. Bu parametrelerin güvenliği sağlamak ve uygulamanızın ihtiyaçlarına uygun olmasını sağlamak için dikkatlice seçilmesi gerekmektedir.

Güvenlik konusunda, SECRET_KEY'in güvenli bir şekilde saklanması ve yönetilmesi çok önemlidir. Gerçek bir uygulamada, bu anahtarın güvenli bir şekilde saklanması ve yönetilmesi için ek önlemler alınmalıdır.

Bu örnek, JWT token üretimi için io.jsonwebtoken:jjwt kütüphanesini kullanıyor. Bu kütüphane, JWT ile çalışmak için yaygın olarak kullanılan ve güvenilir bir seçenektir.

Bu temel Auth Service örneği, bir mikroservis mimarisinde kimlik doğrulama ve JWT tabanlı yetkilendirme işlemlerinin nasıl gerçekleştirilebileceğini göstermektedir. Gerçek dünya uygulamalarında, daha karmaşık kimlik doğrulama mekanizmaları, token yenileme stratejileri ve güvenlik önlemleri gerekebilir. Bu nedenle, projenizin özel ihtiyaçlarına göre ek ayarlamalar ve güvenlik kontrolleri yapmanız önemlidir.


Bu security mimarisi için Api Gatewayde örnek autharazation örnekleri yapat mısın?


Evet, API Gateway'de yetkilendirme (authorization) kontrolü için bazı örnekler oluşturabiliriz. Burada, Spring Cloud Gateway kullanarak gelen istekler üzerinde yetkilendirme kontrolleri yapacağız. Bu örnekler, isteklerin JWT token'larına göre nasıl filtrelenip yetkilendirileceğini gösterecektir.


Örnek 1: Rol Tabanlı Yetkilendirme

Bu örnekte, kullanıcı rollerine göre istekleri filtreleyeceğiz. Örneğin, yalnızca "admin" rolüne sahip kullanıcıların belirli bir endpoint'e erişimine izin vermek isteyebiliriz.


RoleBasedAuthorizationFilter.java adında bir filtre oluşturun:


java

Copy code

package com.myapp.config;


import io.jsonwebtoken.Claims;

import io.jsonwebtoken.Jwts;

import org.springframework.cloud.gateway.filter.GatewayFilter;

import org.springframework.cloud.gateway.filter.GatewayFilterChain;

import org.springframework.http.HttpStatus;

import org.springframework.web.server.ServerWebExchange;

import reactor.core.publisher.Mono;


public class RoleBasedAuthorizationFilter implements GatewayFilter {


    private static final String SECRET_KEY = "your_secret_key";


    @Override

    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {

        String token = exchange.getRequest().getHeaders().getFirst("Authorization");


        if (token != null && token.startsWith("Bearer ")) {

            String jwtToken = token.substring(7);

            Claims claims = Jwts.parser()

                                .setSigningKey(SECRET_KEY)

                                .parseClaimsJws(jwtToken)

                                .getBody();


            String role = claims.get("role", String.class);


            if ("admin".equals(role)) {

                return chain.filter(exchange); // Admin rolü varsa isteği geçir

            }

        }


        exchange.getResponse().setStatusCode(HttpStatus.FORBIDDEN);

        return exchange.getResponse().setComplete(); // Yetkisiz erişim

    }

}

Bu filtre, JWT token içindeki role alanını kontrol eder ve sadece "admin" rolüne sahip token'lar için isteği geçirir.


Örnek 2: JWT Token Süresi Kontrolü

Bu örnekte, JWT token'ın süresinin geçip geçmediğini kontrol edeceğiz. Süresi geçmiş token'larla yapılan istekler reddedilecek.


JwtExpirationFilter.java adında bir filtre oluşturun:


java

Copy code

package com.myapp.config;


import io.jsonwebtoken.Claims;

import io.jsonwebtoken.ExpiredJwtException;

import io.jsonwebtoken.Jwts;

import org.springframework.cloud.gateway.filter.GatewayFilter;

import org.springframework.cloud.gateway.filter.GatewayFilterChain;

import org.springframework.http.HttpStatus;

import org.springframework.web.server.ServerWebExchange;

import reactor.core.publisher.Mono;


public class JwtExpirationFilter implements GatewayFilter {


    private static final String SECRET_KEY = "your_secret_key";


    @Override

    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {

        String token = exchange.getRequest().getHeaders().getFirst("Authorization");


        try {

            if (token != null && token.startsWith("Bearer ")) {

                String jwtToken = token.substring(7);

                Jwts.parser().setSigningKey(SECRET_KEY).parseClaimsJws(jwtToken); // Süresi geçmişse Exception fırlatır

                return chain.filter(exchange);

            }

        } catch (ExpiredJwtException e) {

            // Token süresi geçmiş

        }


        exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);

        return exchange.getResponse().setComplete(); // Yetkisiz erişim

    }

}

Bu filtre, token'ın süresini kontrol eder ve süresi geçmişse isteği reddeder.


Gateway Yapılandırması

Bu filtreleri Spring Cloud Gateway'e eklemek için, GatewayConfig.java dosyanızda aşağıdaki gibi bir yapılandırma yapabilirsiniz:


java

Copy code

@Configuration

public class GatewayConfig {


    @Bean

    public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {

        return builder.routes()

                .route("admin_route", r -> r.path("/admin/**")

                        .filters(f -> f.filter(new RoleBasedAuthorizationFilter()))

                        .uri("lb://ADMIN-SERVICE"))

                .route("general_route", r -> r.path("/api/**")

                        .filters(f -> f.filter(new JwtExpirationFilter()))

                        .uri("lb://GENERAL-SERVICE"))

                .build();

    }

}

Bu yapılandırmada, /admin/** yolu ile gelen istekler RoleBasedAuthorizationFilter tarafından filtrelenerek yalnızca "admin" rolüne sahip kullanıcıların bu yola erişimine izin verilir. Diğer taraftan, /api/** yolu ile gelen tüm istekler JwtExpirationFilter tarafından filtrelenerek, yalnızca süresi geçmemiş JWT token'ları içeren isteklere izin verilir.


Örnek 3: İnce Taneli Yetkilendirme Kontrolü

Bu örnekte, kullanıcının yetkilerine göre daha ince taneli bir yetkilendirme kontrolü gerçekleştirebiliriz. Örneğin, kullanıcının belirli bir API kaynağına erişim yetkisi olup olmadığını kontrol edebiliriz.


FineGrainedAuthorizationFilter.java adında bir filtre oluşturun:


java

Copy code

package com.myapp.config;


import io.jsonwebtoken.Claims;

import io.jsonwebtoken.Jwts;

import org.springframework.cloud.gateway.filter.GatewayFilter;

import org.springframework.cloud.gateway.filter.GatewayFilterChain;

import org.springframework.http.HttpStatus;

import org.springframework.web.server.ServerWebExchange;

import reactor.core.publisher.Mono;


import java.util.List;


public class FineGrainedAuthorizationFilter implements GatewayFilter {


    private static final String SECRET_KEY = "your_secret_key";


    @Override

    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {

        String token = exchange.getRequest().getHeaders().getFirst("Authorization");


        if (token != null && token.startsWith("Bearer ")) {

            String jwtToken = token.substring(7);

            Claims claims = Jwts.parser()

                                .setSigningKey(SECRET_KEY)

                                .parseClaimsJws(jwtToken)

                                .getBody();


            List<String> permissions = claims.get("permissions", List.class);


            // Örnek kontrol: "read_data" iznine sahip kullanıcılar

            if (permissions != null && permissions.contains("read_data")) {

                return chain.filter(exchange); // İzin verilen istek

            }

        }


        exchange.getResponse().setStatusCode(HttpStatus.FORBIDDEN);

        return exchange.getResponse().setComplete(); // Yetkisiz erişim

    }

}

Bu filtre, JWT token içindeki permissions alanını kontrol eder ve belirli izinlere sahip kullanıcılara isteğin geçişine izin verir.


Gateway Yapılandırması için Ek Örnek

FineGrainedAuthorizationFilter'ı eklemek için GatewayConfig.java'da yeni bir route tanımı yapabilirsiniz:


java

Copy code

@Configuration

public class GatewayConfig {


    @Bean

    public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {

        // Diğer route tanımlamaları


        return builder.routes()

                .route("data_route", r -> r.path("/data/**")

                        .filters(f -> f.filter(new FineGrainedAuthorizationFilter()))

                        .uri("lb://DATA-SERVICE"))

                .build();

    }

}

Bu yapılandırma ile /data/** yoluna gelen istekler, FineGrainedAuthorizationFilter tarafından filtrelenerek yalnızca belirli izinlere sahip kullanıcıların erişimine izin verilir.


Son Notlar

Güvenlik açısından, SECRET_KEY gibi hassas bilgileri kod içinde saklamaktan kaçının. Bunun yerine, güvenli bir yapılandırma yönetimi mekanizması (örneğin, Spring Cloud Config) kullanın.

JWT token'larınızın içeriğini ve yapısını uygulamanızın güvenlik ihtiyaçlarına göre özenle planlayın.

Yukarıdaki örneklerde basit string karşılaştırmaları yapıldı. Gerçek uygulamalarda, güvenlik kontrollerinin daha kapsamlı ve güvenli olması gerekecektir.

Spring Cloud Gateway, reaktif programlama modelini kullanır. Bu nedenle, filtrelerinizin reaktif API'lerle uyumlu olmasına dikkat edin.


aoi gatewayde tokenı doğruladım ama yetkilendirmeyi servislerde rol tavanlıı ve anatasyonlatla yapmak istiyorum


API Gateway'de JWT token doğrulaması yaptıktan sonra, yetkilendirmeyi (authorization) mikroservislerde rol tabanlı ve anotasyonlarla yapmak istiyorsanız, Spring Security'nin sağladığı anotasyonları kullanabilirsiniz. Bu yaklaşım, her bir mikroservisin kendi içinde gelen istekleri kullanıcının rollerine göre kontrol etmesine olanak tanır. İşte bu süreci nasıl gerçekleştirebileceğinize dair adımlar:


1. Spring Security Bağımlılıklarını Ekleyin

Her mikroservis projesine Spring Security bağımlılığını ekleyin. pom.xml dosyasına aşağıdaki gibi ekleyebilirsiniz:


xml

Copy code

<dependency>

    <groupId>org.springframework.boot</groupId>

    <artifactId>spring-boot-starter-security</artifactId>

</dependency>

2. Spring Security Konfigürasyonu

Her mikroserviste, Spring Security'yi yapılandırın. Burada, gelen JWT token'ın doğrulanması ve Spring Security context'ine kullanıcı bilgilerinin eklenmesi işlemlerini gerçekleştirebilirsiniz.


Örnek bir güvenlik konfigürasyonu:


java

Copy code

import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;

import org.springframework.security.config.annotation.web.builders.HttpSecurity;

import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;


@EnableWebSecurity

@EnableGlobalMethodSecurity(prePostEnabled = true)

public class SecurityConfig extends WebSecurityConfigurerAdapter {


    @Override

    protected void configure(HttpSecurity http) throws Exception {

        http

            .csrf().disable()

            .authorizeRequests()

            .anyRequest().authenticated()

            .and()

            .addFilter(new JwtTokenAuthenticationFilter(authenticationManager()));

            // Burada JwtTokenAuthenticationFilter, JWT token'ı doğrulayan özel bir filtredir.

    }

}

3. Method Düzeyinde Rol Tabanlı Yetkilendirme

Servislerinizdeki controller veya service sınıflarında, Spring Security'nin @PreAuthorize veya @Secured anotasyonlarını kullanarak rol tabanlı yetkilendirme yapabilirsiniz.


Örnek kullanım:


java

Copy code

import org.springframework.security.access.prepost.PreAuthorize;

import org.springframework.web.bind.annotation.GetMapping;

import org.springframework.web.bind.annotation.RestController;


@RestController

public class MyController {


    @PreAuthorize("hasRole('ROLE_ADMIN')")

    @GetMapping("/admin")

    public String adminOnly() {

        return "Yalnızca Admin erişebilir.";

    }


    @PreAuthorize("hasRole('ROLE_USER')")

    @GetMapping("/user")

    public String userOnly() {

        return "Yalnızca Kullanıcı erişebilir.";

    }

}

4. JWT Token Doğrulama Filtresi

JwtTokenAuthenticationFilter adında özel bir filtre oluşturarak, gelen isteklerdeki JWT token'ları doğrulayabilir ve kullanıcının yetkilerini Spring Security context'ine ekleyebilirsiniz. Bu filtre, API Gateway tarafından doğrulanmış token'ları alır ve kullanıcının rollerini çözümler.


5. Rol ve Yetkilendirme Bilgilerini JWT Token İçerisinde Taşıma

JWT token'ınızın içerisinde kullanıcının rollerini ve diğer yetkilendirme bilgilerini taşıdığından emin olun. Böylece, her mikroservis bu bilgileri kullanarak kendi içinde yetkilendirme yapabilir.


Bu yaklaşım, sisteminizin güvenliğini artırır ve her mikroservisin bağımsız olarak yetkilendirme yapabilmesini sağlar. Ayrıca, API Gateway'de yalnızca kimlik doğrulaması (authentication) yaparak, yetkilendirmenin (authorization) mikroservisler tarafından daha detaylı ve esnek bir şekilde yapılmasına olanak tanır.


Api Gateway'de feign ile diğer microserviceleri çağırıyorsam feign endpointlerine anatasyon ile authorization kontrolü koyabilir miyim?


Evet, Api Gateway'de feign ile diğer microserviceleri çağırırken feign endpointlerine annotation ile authorization kontrolü koyabilirsiniz. Bunun için aşağıdaki adımları takip edebilirsiniz:


Api Gateway'de feign client oluşturmak için @FeignClient annotation'unu kullanın.

@FeignClient annotation'una name ve url property'lerini verin.

@RequestMapping annotation'unu kullanarak feign endpoint'lerini tanımlayın.

@PreAuthorize annotation'unu kullanarak feign endpoint'leri için authorization kontrolü sağlayın.

Örneğin, aşağıdaki kodda user-service microservice'ini çağıran bir feign client oluşturulmuştur. /users endpoint'i için @PreAuthorize("hasRole('ROLE_USER')") annotation'u kullanılarak authorization kontrolü sağlanmıştır.


@FeignClient(name = "user-service", url = "http://localhost:8080/user-service")

public interface UserService {


    @GetMapping("/users")

    @PreAuthorize("hasRole('ROLE_USER')")

    List<User> getAllUsers();

}

Bu kod çalıştırıldığında, hasRole('ROLE_USER') expression'ı true döndürmezse, /users endpoint'ine erişmeye çalışan kullanıcıya bir hata mesajı döndürülür.

Hiç yorum yok

Rastgele İçerik

DonanımHaber

© tüm hakları saklıdır
made with by templateszoo