Skip to content

Commit 229c7bc

Browse files
committed
Add AuthorizationManagerFactory in Kotlin DSL
Closes spring-projectsgh-17860
1 parent 765bdf1 commit 229c7bc

File tree

3 files changed

+220
-50
lines changed

3 files changed

+220
-50
lines changed

config/src/main/kotlin/org/springframework/security/config/annotation/web/AbstractRequestMatcherDsl.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ abstract class AbstractRequestMatcherDsl {
3939
override val rule: String) : AuthorizationRule(rule)
4040

4141
protected data class MatcherAuthorizationManagerRule(val matcher: RequestMatcher,
42-
override val rule: AuthorizationManager<RequestAuthorizationContext>) : AuthorizationManagerRule(rule)
42+
override val rule: AuthorizationManager<in RequestAuthorizationContext>) : AuthorizationManagerRule(rule)
4343

4444
protected data class PatternAuthorizationRule(val pattern: String,
4545
val patternType: PatternType,
@@ -51,11 +51,11 @@ abstract class AbstractRequestMatcherDsl {
5151
val patternType: PatternType,
5252
val servletPath: String? = null,
5353
val httpMethod: HttpMethod? = null,
54-
override val rule: AuthorizationManager<RequestAuthorizationContext>) : AuthorizationManagerRule(rule)
54+
override val rule: AuthorizationManager<in RequestAuthorizationContext>) : AuthorizationManagerRule(rule)
5555

5656
protected abstract class AuthorizationRule(open val rule: String)
5757

58-
protected abstract class AuthorizationManagerRule(open val rule: AuthorizationManager<RequestAuthorizationContext>)
58+
protected abstract class AuthorizationManagerRule(open val rule: AuthorizationManager<in RequestAuthorizationContext>)
5959

6060
protected enum class PatternType {
6161
ANT, MVC, PATH;

config/src/main/kotlin/org/springframework/security/config/annotation/web/AuthorizeHttpRequestsDsl.kt

Lines changed: 59 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -16,24 +16,23 @@
1616

1717
package org.springframework.security.config.annotation.web
1818

19+
import org.springframework.beans.factory.getBeanProvider
1920
import org.springframework.context.ApplicationContext
21+
import org.springframework.core.ResolvableType
2022
import org.springframework.http.HttpMethod
2123
import org.springframework.security.access.hierarchicalroles.NullRoleHierarchy
2224
import org.springframework.security.access.hierarchicalroles.RoleHierarchy
23-
import org.springframework.security.authorization.AuthenticatedAuthorizationManager
24-
import org.springframework.security.authorization.AuthorityAuthorizationManager
25-
import org.springframework.security.authorization.AuthorizationDecision
2625
import org.springframework.security.authorization.AuthorizationManager
26+
import org.springframework.security.authorization.AuthorizationManagerFactory
27+
import org.springframework.security.authorization.DefaultAuthorizationManagerFactory
2728
import org.springframework.security.config.annotation.web.builders.HttpSecurity
2829
import org.springframework.security.config.annotation.web.configurers.AuthorizeHttpRequestsConfigurer
2930
import org.springframework.security.config.core.GrantedAuthorityDefaults
30-
import org.springframework.security.core.Authentication
3131
import org.springframework.security.web.access.IpAddressAuthorizationManager
3232
import org.springframework.security.web.access.intercept.RequestAuthorizationContext
3333
import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher
3434
import org.springframework.security.web.util.matcher.AnyRequestMatcher
3535
import org.springframework.security.web.util.matcher.RequestMatcher
36-
import java.util.function.Supplier
3736

3837
/**
3938
* A Kotlin DSL to configure [HttpSecurity] request authorization using idiomatic Kotlin code.
@@ -44,8 +43,7 @@ import java.util.function.Supplier
4443
class AuthorizeHttpRequestsDsl : AbstractRequestMatcherDsl {
4544

4645
private val authorizationRules = mutableListOf<AuthorizationManagerRule>()
47-
private val rolePrefix: String
48-
private val roleHierarchy: RoleHierarchy
46+
private val authorizationManagerFactory: AuthorizationManagerFactory<in RequestAuthorizationContext>
4947

5048
private val PATTERN_TYPE = PatternType.PATH
5149

@@ -57,7 +55,7 @@ class AuthorizeHttpRequestsDsl : AbstractRequestMatcherDsl {
5755
* (i.e. created via hasAuthority("ROLE_USER"))
5856
*/
5957
fun authorize(matches: RequestMatcher = AnyRequestMatcher.INSTANCE,
60-
access: AuthorizationManager<RequestAuthorizationContext>) {
58+
access: AuthorizationManager<in RequestAuthorizationContext>) {
6159
authorizationRules.add(MatcherAuthorizationManagerRule(matches, access))
6260
}
6361

@@ -77,7 +75,7 @@ class AuthorizeHttpRequestsDsl : AbstractRequestMatcherDsl {
7775
* (i.e. created via hasAuthority("ROLE_USER"))
7876
*/
7977
fun authorize(pattern: String,
80-
access: AuthorizationManager<RequestAuthorizationContext>) {
78+
access: AuthorizationManager<in RequestAuthorizationContext>) {
8179
authorizationRules.add(
8280
PatternAuthorizationManagerRule(
8381
pattern = pattern,
@@ -105,7 +103,7 @@ class AuthorizeHttpRequestsDsl : AbstractRequestMatcherDsl {
105103
*/
106104
fun authorize(method: HttpMethod,
107105
pattern: String,
108-
access: AuthorizationManager<RequestAuthorizationContext>) {
106+
access: AuthorizationManager<in RequestAuthorizationContext>) {
109107
authorizationRules.add(
110108
PatternAuthorizationManagerRule(
111109
pattern = pattern,
@@ -135,7 +133,7 @@ class AuthorizeHttpRequestsDsl : AbstractRequestMatcherDsl {
135133
*/
136134
fun authorize(pattern: String,
137135
servletPath: String,
138-
access: AuthorizationManager<RequestAuthorizationContext>) {
136+
access: AuthorizationManager<in RequestAuthorizationContext>) {
139137
authorizationRules.add(
140138
PatternAuthorizationManagerRule(
141139
pattern = pattern,
@@ -167,7 +165,7 @@ class AuthorizeHttpRequestsDsl : AbstractRequestMatcherDsl {
167165
fun authorize(method: HttpMethod,
168166
pattern: String,
169167
servletPath: String,
170-
access: AuthorizationManager<RequestAuthorizationContext>) {
168+
access: AuthorizationManager<in RequestAuthorizationContext>) {
171169
authorizationRules.add(
172170
PatternAuthorizationManagerRule(
173171
pattern = pattern,
@@ -185,43 +183,48 @@ class AuthorizeHttpRequestsDsl : AbstractRequestMatcherDsl {
185183
* @param authority the authority to require (i.e. ROLE_USER, ROLE_ADMIN, etc).
186184
* @return the [AuthorizationManager] with the provided authority
187185
*/
188-
fun hasAuthority(authority: String): AuthorizationManager<RequestAuthorizationContext> {
189-
val manager = AuthorityAuthorizationManager.hasAuthority<RequestAuthorizationContext>(authority)
190-
return withRoleHierarchy(manager)
191-
}
186+
fun hasAuthority(authority: String): AuthorizationManager<in RequestAuthorizationContext> = this.authorizationManagerFactory.hasAuthority(authority)
192187

193188
/**
194189
* Specify that URLs require any of the provided authorities.
195190
*
196191
* @param authorities the authorities to require (i.e. ROLE_USER, ROLE_ADMIN, etc).
197192
* @return the [AuthorizationManager] with the provided authorities
198193
*/
199-
fun hasAnyAuthority(vararg authorities: String): AuthorizationManager<RequestAuthorizationContext> {
200-
val manager = AuthorityAuthorizationManager.hasAnyAuthority<RequestAuthorizationContext>(*authorities)
201-
return withRoleHierarchy(manager)
202-
}
194+
fun hasAnyAuthority(vararg authorities: String): AuthorizationManager<in RequestAuthorizationContext> = this.authorizationManagerFactory.hasAnyAuthority(*authorities)
195+
196+
197+
/**
198+
* Specify that URLs require any of the provided authorities.
199+
*
200+
* @param authorities the authorities to require (i.e. ROLE_USER, ROLE_ADMIN, etc).
201+
* @return the [AuthorizationManager] with the provided authorities
202+
*/
203+
fun hasAllAuthorities(vararg authorities: String): AuthorizationManager<in RequestAuthorizationContext> = this.authorizationManagerFactory.hasAllAuthorities(*authorities)
203204

204205
/**
205206
* Specify that URLs require a particular role.
206207
*
207208
* @param role the role to require (i.e. USER, ADMIN, etc).
208209
* @return the [AuthorizationManager] with the provided role
209210
*/
210-
fun hasRole(role: String): AuthorizationManager<RequestAuthorizationContext> {
211-
val manager = AuthorityAuthorizationManager.hasAnyRole<RequestAuthorizationContext>(this.rolePrefix, arrayOf(role))
212-
return withRoleHierarchy(manager)
213-
}
211+
fun hasRole(role: String): AuthorizationManager<in RequestAuthorizationContext> = this.authorizationManagerFactory.hasRole(role)
214212

215213
/**
216214
* Specify that URLs require any of the provided roles.
217215
*
218216
* @param roles the roles to require (i.e. USER, ADMIN, etc).
219217
* @return the [AuthorizationManager] with the provided roles
220218
*/
221-
fun hasAnyRole(vararg roles: String): AuthorizationManager<RequestAuthorizationContext> {
222-
val manager = AuthorityAuthorizationManager.hasAnyRole<RequestAuthorizationContext>(this.rolePrefix, arrayOf(*roles))
223-
return withRoleHierarchy(manager)
224-
}
219+
fun hasAnyRole(vararg roles: String): AuthorizationManager<in RequestAuthorizationContext> = this.authorizationManagerFactory.hasAnyRole(*roles)
220+
221+
/**
222+
* Specify that URLs require any of the provided roles.
223+
*
224+
* @param roles the roles to require (i.e. USER, ADMIN, etc).
225+
* @return the [AuthorizationManager] with the provided roles
226+
*/
227+
fun hasAllRoles(vararg roles: String): AuthorizationManager<in RequestAuthorizationContext> = this.authorizationManagerFactory.hasAllRoles(*roles)
225228

226229
/**
227230
* Require a specific IP or range of IP addresses.
@@ -233,27 +236,23 @@ class AuthorizeHttpRequestsDsl : AbstractRequestMatcherDsl {
233236
/**
234237
* Specify that URLs are allowed by anyone.
235238
*/
236-
val permitAll: AuthorizationManager<RequestAuthorizationContext> =
237-
AuthorizationManager { _: Supplier<out Authentication>, _: RequestAuthorizationContext -> AuthorizationDecision(true) }
239+
val permitAll: AuthorizationManager<in RequestAuthorizationContext>
238240

239241
/**
240242
* Specify that URLs are not allowed by anyone.
241243
*/
242-
val denyAll: AuthorizationManager<RequestAuthorizationContext> =
243-
AuthorizationManager { _: Supplier<out Authentication>, _: RequestAuthorizationContext -> AuthorizationDecision(false) }
244+
val denyAll: AuthorizationManager<in RequestAuthorizationContext>
244245

245246
/**
246247
* Specify that URLs are allowed by any authenticated user.
247248
*/
248-
val authenticated: AuthorizationManager<RequestAuthorizationContext> =
249-
AuthenticatedAuthorizationManager.authenticated()
249+
val authenticated: AuthorizationManager<in RequestAuthorizationContext>
250250

251251
/**
252252
* Specify that URLs are allowed by users who have authenticated and were not "remembered".
253253
* @since 6.5
254254
*/
255-
val fullyAuthenticated: AuthorizationManager<RequestAuthorizationContext> =
256-
AuthenticatedAuthorizationManager.fullyAuthenticated()
255+
val fullyAuthenticated: AuthorizationManager<in RequestAuthorizationContext>
257256

258257
internal fun get(): (AuthorizeHttpRequestsConfigurer<HttpSecurity>.AuthorizationManagerRequestMatcherRegistry) -> Unit {
259258
return { requests ->
@@ -274,16 +273,34 @@ class AuthorizeHttpRequestsDsl : AbstractRequestMatcherDsl {
274273
}
275274
}
276275

277-
constructor() {
278-
this.rolePrefix = "ROLE_"
279-
this.roleHierarchy = NullRoleHierarchy()
276+
constructor(context: ApplicationContext) {
277+
this.authorizationManagerFactory = resolveAuthorizationManagerFactory(context)
278+
this.authenticated = this.authorizationManagerFactory.authenticated()
279+
this.denyAll = this.authorizationManagerFactory.denyAll()
280+
this.fullyAuthenticated = this.authorizationManagerFactory.fullyAuthenticated()
281+
this.permitAll = this.authorizationManagerFactory.permitAll()
280282
}
281283

282-
constructor(context: ApplicationContext) {
284+
private fun resolveAuthorizationManagerFactory(context: ApplicationContext): AuthorizationManagerFactory<in RequestAuthorizationContext> {
285+
val specific = context.getBeanProvider<AuthorizationManagerFactory<RequestAuthorizationContext>>().getIfUnique()
286+
if (specific != null) {
287+
return specific
288+
}
289+
val type = ResolvableType.forClassWithGenerics(AuthorizationManagerFactory::class.java, Object::class.java)
290+
val general: AuthorizationManagerFactory<in RequestAuthorizationContext>? = context.getBeanProvider<AuthorizationManagerFactory<in RequestAuthorizationContext>>(type).getIfUnique()
291+
if (general != null) {
292+
return general
293+
}
294+
val defaultFactory: DefaultAuthorizationManagerFactory<RequestAuthorizationContext> = DefaultAuthorizationManagerFactory()
283295
val rolePrefix = resolveRolePrefix(context)
284-
this.rolePrefix = rolePrefix
296+
if (rolePrefix != null) {
297+
defaultFactory.setRolePrefix(rolePrefix)
298+
}
285299
val roleHierarchy = resolveRoleHierarchy(context)
286-
this.roleHierarchy = roleHierarchy
300+
if (roleHierarchy != null) {
301+
defaultFactory.setRoleHierarchy(roleHierarchy)
302+
}
303+
return defaultFactory
287304
}
288305

289306
private fun resolveRolePrefix(context: ApplicationContext): String {
@@ -301,9 +318,4 @@ class AuthorizeHttpRequestsDsl : AbstractRequestMatcherDsl {
301318
}
302319
return NullRoleHierarchy()
303320
}
304-
305-
private fun withRoleHierarchy(manager: AuthorityAuthorizationManager<RequestAuthorizationContext>): AuthorityAuthorizationManager<RequestAuthorizationContext> {
306-
manager.setRoleHierarchy(this.roleHierarchy)
307-
return manager
308-
}
309321
}

0 commit comments

Comments
 (0)