From 8cc0b3e08f509010c34d25c936422feee1f62f77 Mon Sep 17 00:00:00 2001 From: h_sharifi Date: Wed, 17 Jan 2024 18:50:41 +0330 Subject: [PATCH 1/4] #BAEL-7434: add AuthenticationManager bean --- .../multitenant/security/SecurityConfiguration.java | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/persistence-modules/spring-jpa-2/src/main/java/com/baeldung/multitenant/security/SecurityConfiguration.java b/persistence-modules/spring-jpa-2/src/main/java/com/baeldung/multitenant/security/SecurityConfiguration.java index acad0d61e4..b1b12b3b9f 100644 --- a/persistence-modules/spring-jpa-2/src/main/java/com/baeldung/multitenant/security/SecurityConfiguration.java +++ b/persistence-modules/spring-jpa-2/src/main/java/com/baeldung/multitenant/security/SecurityConfiguration.java @@ -4,9 +4,9 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.config.Customizer; +import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration; 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.configurers.AbstractHttpConfigurer; import org.springframework.security.config.annotation.web.configurers.HeadersConfigurer; import org.springframework.security.config.http.SessionCreationPolicy; import org.springframework.security.core.userdetails.User; @@ -42,16 +42,21 @@ public class SecurityConfiguration { return new BCryptPasswordEncoder(); } + @Bean + public AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception { + return authenticationConfiguration.getAuthenticationManager(); + } + @Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { - final AuthenticationManager authenticationManager = http.getSharedObject(AuthenticationManager.class); + final AuthenticationManager authenticationManager = authenticationManager(http.getSharedObject(AuthenticationConfiguration.class)); http .authorizeHttpRequests(authorize -> authorize.requestMatchers("/login").permitAll().anyRequest().authenticated()) .sessionManagement(securityContext -> securityContext.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) .addFilterBefore(new LoginFilter("/login", authenticationManager), UsernamePasswordAuthenticationFilter.class) .addFilterBefore(new AuthenticationFilter(), UsernamePasswordAuthenticationFilter.class) - .csrf(AbstractHttpConfigurer::disable) + .csrf(csrf -> csrf.disable()) .headers(header -> header.frameOptions(HeadersConfigurer.FrameOptionsConfig::disable)) .httpBasic(Customizer.withDefaults()); From 79b63e92fce6aa7476d66698f07ff55c1f5eaef3 Mon Sep 17 00:00:00 2001 From: h_sharifi Date: Wed, 17 Jan 2024 18:51:28 +0330 Subject: [PATCH 2/4] #BAEL-7434: add logback dependency --- persistence-modules/spring-jpa-2/pom.xml | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/persistence-modules/spring-jpa-2/pom.xml b/persistence-modules/spring-jpa-2/pom.xml index c20c43912b..e3387d94c0 100644 --- a/persistence-modules/spring-jpa-2/pom.xml +++ b/persistence-modules/spring-jpa-2/pom.xml @@ -55,7 +55,7 @@ io.jsonwebtoken jjwt-api - 0.12.3 + ${jjwt.version} @@ -107,6 +107,18 @@ jackson-core ${jakson-core.version} + + ch.qos.logback + logback-classic + ${logback.version} + test + + + ch.qos.logback + logback-core + ${logback.version} + test + @@ -115,8 +127,11 @@ 3.1.0 10.1.9 - 2.15.1 - 2.14.2 + 2.16.1 + 2.16.1 + + 0.12.3 + 1.4.14 \ No newline at end of file From e8d187fec0049692e0beb241008ba9211a32fbd2 Mon Sep 17 00:00:00 2001 From: h_sharifi Date: Wed, 17 Jan 2024 18:52:26 +0330 Subject: [PATCH 3/4] #BAEL-7434: refactor jwt --- .../security/AuthenticationService.java | 28 +++++++++++-------- 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/persistence-modules/spring-jpa-2/src/main/java/com/baeldung/multitenant/security/AuthenticationService.java b/persistence-modules/spring-jpa-2/src/main/java/com/baeldung/multitenant/security/AuthenticationService.java index 42eab1d6de..c547640b4d 100644 --- a/persistence-modules/spring-jpa-2/src/main/java/com/baeldung/multitenant/security/AuthenticationService.java +++ b/persistence-modules/spring-jpa-2/src/main/java/com/baeldung/multitenant/security/AuthenticationService.java @@ -1,26 +1,31 @@ package com.baeldung.multitenant.security; import io.jsonwebtoken.Jwts; -import io.jsonwebtoken.SignatureAlgorithm; +import io.jsonwebtoken.security.Keys; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; +import javax.crypto.SecretKey; +import java.nio.charset.StandardCharsets; import java.util.Collections; import java.util.Date; public class AuthenticationService { private static final long EXPIRATIONTIME = 864_000_00; // 1 day in milliseconds - private static final String SIGNINGKEY = "SecretKey"; + private static final String SECRETKEY = "q3t6w9zCFJNcQfTjWnq3t6w9zCFJNcQfTjWnZr4u7xADGKaPd"; + private static final SecretKey SIGNINGKEY = Keys.hmacShaKeyFor(SECRETKEY.getBytes(StandardCharsets.UTF_8)); private static final String PREFIX = "Bearer"; public static void addToken(HttpServletResponse res, String username, String tenant) { - String JwtToken = Jwts.builder().setSubject(username) - .setAudience(tenant) - .setExpiration(new Date(System.currentTimeMillis() + EXPIRATIONTIME)) - .signWith(SignatureAlgorithm.HS512, SIGNINGKEY) + String JwtToken = Jwts.builder() + .subject(username) + .audience().add(tenant).and() + .issuedAt(new Date(System.currentTimeMillis())) + .expiration(new Date(System.currentTimeMillis() + EXPIRATIONTIME)) + .signWith(SIGNINGKEY) .compact(); res.addHeader("Authorization", PREFIX + " " + JwtToken); } @@ -29,9 +34,8 @@ public class AuthenticationService { String token = req.getHeader("Authorization"); if (token != null) { String user = Jwts.parser() - .setSigningKey(SIGNINGKEY) - .build().parseClaimsJws(token.replace(PREFIX, "")) - .getBody() + .verifyWith(SIGNINGKEY) + .build().parseClaimsJws(token.replace(PREFIX, "").trim()).getPayload() .getSubject(); if (user != null) { return new UsernamePasswordAuthenticationToken(user, null, Collections.emptyList()); @@ -48,7 +52,7 @@ public class AuthenticationService { } String tenant = Jwts.parser() .setSigningKey(SIGNINGKEY) - .build().parseClaimsJws(token.replace(PREFIX, "")) + .build().parseClaimsJws(token.replace(PREFIX, "").trim()) .getBody() .getAudience() .iterator() From 189b0723ab87a7152e364415e8af5484f2827515 Mon Sep 17 00:00:00 2001 From: h_sharifi Date: Wed, 17 Jan 2024 18:53:04 +0330 Subject: [PATCH 4/4] #BAEL-7434: add defaultTenant --- .../multitenant/config/MultitenantConfiguration.java | 6 +++++- .../spring-jpa-2/src/main/resources/application.properties | 4 ++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/persistence-modules/spring-jpa-2/src/main/java/com/baeldung/multitenant/config/MultitenantConfiguration.java b/persistence-modules/spring-jpa-2/src/main/java/com/baeldung/multitenant/config/MultitenantConfiguration.java index 64d66f5cc9..cf547066dd 100644 --- a/persistence-modules/spring-jpa-2/src/main/java/com/baeldung/multitenant/config/MultitenantConfiguration.java +++ b/persistence-modules/spring-jpa-2/src/main/java/com/baeldung/multitenant/config/MultitenantConfiguration.java @@ -1,5 +1,6 @@ package com.baeldung.multitenant.config; +import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.jdbc.DataSourceBuilder; import org.springframework.context.annotation.Bean; @@ -18,6 +19,9 @@ import java.util.Properties; @Configuration public class MultitenantConfiguration { + @Value("${defaultTenant}") + private String defaultTenant; + @Bean @ConfigurationProperties(prefix = "tenants") public DataSource dataSource() { @@ -43,7 +47,7 @@ public class MultitenantConfiguration { } AbstractRoutingDataSource dataSource = new MultitenantDataSource(); - dataSource.setDefaultTargetDataSource(resolvedDataSources.get("tenant_1")); + dataSource.setDefaultTargetDataSource(resolvedDataSources.get(defaultTenant)); dataSource.setTargetDataSources(resolvedDataSources); dataSource.afterPropertiesSet(); diff --git a/persistence-modules/spring-jpa-2/src/main/resources/application.properties b/persistence-modules/spring-jpa-2/src/main/resources/application.properties index 0270c1683e..61fccff032 100644 --- a/persistence-modules/spring-jpa-2/src/main/resources/application.properties +++ b/persistence-modules/spring-jpa-2/src/main/resources/application.properties @@ -9,3 +9,7 @@ spring.datasource.url=jdbc:h2:mem:db;DB_CLOSE_DELAY=-1 #spring.datasource.username=mysqluser #spring.datasource.password=mysqlpass #spring.datasource.url=jdbc:mysql://localhost:3306/myDb?createDatabaseIfNotExist=true + +# MultiTenantApplication +defaultTenant=tenant_1 +spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect \ No newline at end of file