Привет, весенние фанаты! Добро пожаловать в очередной выпуск Spring Tips . В этом выпуске мы рассмотрим новый DSL Kotlin для Spring Security. Я люблю Котлин. Я представил Kotlin в нескольких других видеороликах Spring Tips: язык программирования Kotlin , Bootiful Kotlin Redux и поддержка Spring для сопрограмм . Некоторые из этих видео очень старые! В весенней диаспоре уже есть ряд различных проектов, которые поставляют DSL Kotlin. Среди них, в частности, Spring Framework, Spring Webflux, Spring Data, Spring Cloud Contract и Spring Cloud Gateway. А теперь Spring Security!
Spring Security — это удивительный проект, он решает некоторые из самых сложных проблем в отрасли и помогает людям защитить свои приложения. И, как будто этого было недостаточно, он проявил твердую решимость сделать безопасность легко . Если бы вы когда-либо использовали Spring Security в самых первых его воплощениях, вы бы знали, что для этого требуется множество XML-страниц! — чтобы сделать что-нибудь. Это улучшилось до такой степени, что в Spring Security 3 вы могли заблокировать приложение со стандартными настройками по умолчанию с помощью одного или двух разделов XML. Затем в Spring Security 4 они представили Java DSL, который дал людям возможность их компиляторов помогать им проверять вещи. Постепенно Spring Security также ввел значения по умолчанию из здравого смысла. В настоящее время вы можете зарегистрироватьUserDetailsService
Spring Security заблокирует все конечные точки HTTP в приложении HTTP на основе сервлетов и потребует проверки подлинности. Не может быть проще! Или это может? В Spring Security 5.2 они представили некоторые высоко ценимые улучшения в Spring Security. Теперь, в дополнение к использованию гибкого DSL Java-конфигурации прошлого, существует также новый подход, в котором вы можете предоставить лямбду и получить объект контекста, который затем сможете использовать. Вам больше не нужно делать отступы для своих API-интерфейсов Spring Security, чтобы понять их намерения! И теперь, в этой статье, мы собираемся поднять все на новый уровень, очень быстро рассмотрев совершенно новый Spring Security Kotlin DSL.
Помните, Spring Security решает две ортогональные проблемы: аутентификация и авторизация. Аутентификация отвечает на вопрос: « кто делает запрос?» Это Джош или Джейн? Авторизация отвечает на вопрос «какие разрешения запрашивающий пользователь имеет внутри системы?» Аутентификация это все о подключении провайдеров идентификации. Есть миллион способов сделать это (Active Directory, имена пользователей и пароли в памяти, LDAP, SAML и т. Д.). Больше о подключении реализаций. Мы просто собираемся использовать менеджер аутентификации имени пользователя и пароля в памяти, так как он нам нужен, и это не то, где DSL действительно сияет.
DSL наиболее полезны не при замене реализаций данного типа, а при описании правил или настройке поведения. Итак, мы будем использовать Spring Security DSL для настройки поведения авторизации.
Ниже приведено приложение на основе Spring Boot, которое использует Spring Security. Я создал новый проект из Spring Initializr, который использует Kotlin и использует Spring Security и Spring Boot 2.3.M2 или более позднюю версию. Он использует функциональную DSL регистрации bean-компонентов для программной регистрации bean-компонентов. Мы говорили о регистрации программных бинов в видео Spring Tips от waaaaay еще в 2017 году . Конечно, это видео продемонстрировало его использование в Java, но приложение в Kotlin в основном такое же: вы регистрируете bean-компонент, заключая его в вызов bean
функции.
Первый боб InMemoryUserDetailsManager
. Второй компонент — это функциональная конечная точка HTTP /greetings
. Когда приходит HTTP-запрос, мы извлекаем аутентифицированный принципал из текущего запроса, извлекаем имя и затем создаем ServerResponse
тело, тело которого будет представлено как Map<String,String>
.
Интересным является класс KotlinSecurityConfiguration
. Это расширяется WebSecurityConfigurerAdapter
. Есть несколько методов, которые мы могли бы переопределить там, но я решил переопределить configure
метод, чтобы указать две вещи: я хотел включить аутентификацию HTTP BASIC и указать, какие маршруты требуют аутентификации, а какие широко открыты. Приведенная ниже конфигурация предусматривает, что все запросы /greetings/**
( /greetings/
конечная точка и все, что ниже нее, например /greetings/foo
) должны быть аутентифицированы. Второе правило гласит, что все остальное широко открыто. Очень важно, чтобы более конкретное правило — /greetings/**
предшествовало более широкому правилу. Правила оцениваются по порядку сверху вниз. Если бы мы сначала поместили второе правило, то оно соответствовало бы каждому запросу, и нам никогда не понадобилось бы оценивать правило для/greetings
— это было бы эффективно открыто широко!
Котлин
xxxxxxxxxx
1
package com.example.kotlinsecurity
2
import org.springframework.boot.autoconfigure.SpringBootApplication
4
import org.springframework.boot.runApplication
5
import org.springframework.context.annotation.Bean
6
import org.springframework.context.support.beans
7
import org.springframework.security.config.annotation.web.builders.HttpSecurity
8
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity
9
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter
10
import org.springframework.security.config.web.servlet.invoke
11
import org.springframework.security.core.userdetails.User
12
import org.springframework.security.provisioning.InMemoryUserDetailsManager
13
import org.springframework.web.servlet.function.ServerResponse
14
import org.springframework.web.servlet.function.router
15
@SpringBootApplication
17
class KotlinSecurityApplication
18
@EnableWebSecurity
20
class KotlinSecurityConfiguration : WebSecurityConfigurerAdapter() {
21
override fun configure(http: HttpSecurity?) {
23
http {
24
httpBasic {}
25
authorizeRequests {
26
authorize("/greetings/**", hasAuthority("ROLE_ADMIN"))
27
authorize("/**", permitAll)
28
}
29
}
30
}
31
}
32
fun main(args: Array<String>) {
34
runApplication<KotlinSecurityApplication>(*args) {
35
addInitializers(beans {
36
bean {
37
fun user(user: String, pw: String, vararg roles: String) =
39
User.withDefaultPasswordEncoder().username(user).password(pw).roles(*roles).build()
40
InMemoryUserDetailsManager(user("jlong", "pw", "USER"), user("rwinch", "pw1", "USER", "ADMIN"))
42
}
43
bean {
44
router {
45
GET("/greetings") { request ->
46
request.principal().map { it.name }.map { ServerResponse.ok().body(mapOf("greeting" to "Hello, $it")) }.orElseGet { ServerResponse.badRequest().build() }
47
}
48
}
49
}
50
})
51
}
52
}
Заключение
В этой статье мы представили новый Kotlin DSL от Spring Security. Там больше текста, чем кода, потому что, и это очень важно, Spring Security многое для вас делает , так что площадь поверхности API буквально является минимальным минимумом в настройках, которые вы хотите сделать, помимо уже разумных значений по умолчанию. Я надеюсь, что вы узнали что-то новое и дадите шанс Spring Security DSL.