Merge pull request #21 from TouchInstinct/common-spring-security
add common-spring-security
This commit is contained in:
commit
2265170de3
12
README.md
12
README.md
|
|
@ -48,6 +48,18 @@
|
|||
* `errors.*` - исключения и типы данных для `web`
|
||||
* `webclient.*` - классы для расширения webclient, включая логирование
|
||||
|
||||
## common-spring-security
|
||||
|
||||
* `configurations.DefaultSecurityConfiguration` - дефолтная реализация WebSecurity,
|
||||
определяет для каких request path надо ограничить доступ.
|
||||
Использует `url.interceptors.UrlExpressionRegistryInterceptor` для принятия решения.
|
||||
* `auditor.AuditorResolver` - служит для преобразования `principal` в строку, используется с `JpaAuditing`
|
||||
|
||||
## common-spring-security-jpa
|
||||
|
||||
* `auditor.SecurityAuditorAware` - резолвит имя пользователя для полей `@CreatedBy`, `@LastModifiedBy`.
|
||||
Требуется явно создать бин `AuditorAware<String>` в проекте.
|
||||
|
||||
## common-spring-test
|
||||
|
||||
Утилиты для тестирования в среде `spring-test`
|
||||
|
|
|
|||
|
|
@ -0,0 +1,13 @@
|
|||
plugins {
|
||||
id("kotlin")
|
||||
id("kotlin-spring")
|
||||
id("maven-publish")
|
||||
}
|
||||
|
||||
dependencies {
|
||||
api(project(":common-spring-security"))
|
||||
|
||||
implementation("org.springframework.boot:spring-boot-starter-data-jpa")
|
||||
|
||||
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
@file:Suppress("unused")
|
||||
|
||||
package ru.touchin.common.spring.security.auditor
|
||||
|
||||
import org.springframework.data.domain.AuditorAware
|
||||
import org.springframework.security.core.Authentication
|
||||
import org.springframework.security.core.context.SecurityContext
|
||||
import org.springframework.security.core.context.SecurityContextHolder
|
||||
import java.util.Optional
|
||||
|
||||
class SecurityAuditorAware(
|
||||
auditorResolversList: List<AuditorResolver>
|
||||
) : AuditorAware<String> {
|
||||
|
||||
private val auditorResolvers = auditorResolversList.asSequence()
|
||||
|
||||
override fun getCurrentAuditor(): Optional<String> {
|
||||
return Optional.ofNullable(SecurityContextHolder.getContext())
|
||||
.map(SecurityContext::getAuthentication)
|
||||
.filter(Authentication::isAuthenticated)
|
||||
.map(Authentication::getPrincipal)
|
||||
.flatMap { principal: Any? ->
|
||||
val result = auditorResolvers
|
||||
.mapNotNull{ it.resolve(principal) }
|
||||
.firstOrNull()
|
||||
|
||||
Optional.ofNullable(result)
|
||||
}
|
||||
.or { Optional.of(UNKNOWN_USER) }
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val UNKNOWN_USER = "unknownUser"
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
plugins {
|
||||
id("kotlin")
|
||||
id("kotlin-spring")
|
||||
id("maven-publish")
|
||||
}
|
||||
|
||||
dependencies {
|
||||
api(project(":common-spring"))
|
||||
api("org.springframework.boot:spring-boot-starter-security")
|
||||
|
||||
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
package ru.touchin.common.spring.security.auditor
|
||||
|
||||
interface AuditorResolver {
|
||||
|
||||
fun resolve(principal: Any?): String?
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
package ru.touchin.common.spring.security.auditor
|
||||
|
||||
import org.springframework.core.annotation.Order
|
||||
import org.springframework.stereotype.Service
|
||||
import ru.touchin.common.spring.Ordered
|
||||
|
||||
@Service
|
||||
@Order(Ordered.HIGH)
|
||||
class StringAuditorResolver : AuditorResolver {
|
||||
|
||||
override fun resolve(principal: Any?): String? {
|
||||
return principal as? String
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
package ru.touchin.common.spring.security.configurations
|
||||
|
||||
import org.springframework.context.annotation.ComponentScan
|
||||
import org.springframework.context.annotation.Configuration
|
||||
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 ru.touchin.common.spring.security.url.interceptors.UrlExpressionRegistryInterceptor
|
||||
|
||||
@Configuration
|
||||
@ComponentScan("ru.touchin.common.spring.security.url.interceptors")
|
||||
@EnableGlobalMethodSecurity(prePostEnabled = true)
|
||||
class DefaultSecurityConfiguration(
|
||||
private val urlExpressionRegistryInterceptors: List<UrlExpressionRegistryInterceptor>,
|
||||
) : WebSecurityConfigurerAdapter() {
|
||||
|
||||
override fun configure(http: HttpSecurity) {
|
||||
http
|
||||
.cors().disable()
|
||||
.csrf().disable()
|
||||
.httpBasic().disable()
|
||||
.authorizeRequests { urlExpressionRegistry ->
|
||||
urlExpressionRegistryInterceptors.forEach {
|
||||
it.invoke(urlExpressionRegistry)
|
||||
}
|
||||
|
||||
urlExpressionRegistry.anyRequest().authenticated()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
package ru.touchin.common.spring.security.url.interceptors
|
||||
|
||||
import org.springframework.http.HttpMethod
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity
|
||||
import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer
|
||||
import org.springframework.stereotype.Component
|
||||
|
||||
@Component
|
||||
class HealthRegistryInterceptor : UrlExpressionRegistryInterceptor {
|
||||
|
||||
override fun invoke(
|
||||
authorizeRequestsCustomizer: ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry
|
||||
) {
|
||||
authorizeRequestsCustomizer.antMatchers(HttpMethod.GET, "/api/health").permitAll()
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
package ru.touchin.common.spring.security.url.interceptors
|
||||
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity
|
||||
import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer
|
||||
|
||||
interface UrlExpressionRegistryInterceptor {
|
||||
|
||||
operator fun invoke(
|
||||
authorizeRequestsCustomizer: ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry
|
||||
)
|
||||
|
||||
}
|
||||
|
|
@ -23,6 +23,8 @@ include("common")
|
|||
include("common-spring")
|
||||
include("common-spring-jpa")
|
||||
include("common-spring-web")
|
||||
include("common-spring-security")
|
||||
include("common-spring-security-jpa")
|
||||
include("common-spring-test")
|
||||
include("common-spring-test-jpa")
|
||||
include("common-measure")
|
||||
|
|
|
|||
Loading…
Reference in New Issue