Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in / Register
Toggle navigation
S
spring-boot
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
DEMO
spring-boot
Commits
40ac5b4a
Commit
40ac5b4a
authored
Sep 27, 2019
by
Madhura Bhave
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Autoconfigure RSocket Security
Closes gh-18356
parent
bc96e099
Changes
9
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
197 additions
and
2 deletions
+197
-2
pom.xml
spring-boot-project/spring-boot-autoconfigure/pom.xml
+5
-0
ReactiveUserDetailsServiceAutoConfiguration.java
...reactive/ReactiveUserDetailsServiceAutoConfiguration.java
+28
-1
RSocketSecurityAutoConfiguration.java
...re/security/rsocket/RSocketSecurityAutoConfiguration.java
+44
-0
spring.factories
...utoconfigure/src/main/resources/META-INF/spring.factories
+1
-0
ReactiveUserDetailsServiceAutoConfigurationTests.java
...ive/ReactiveUserDetailsServiceAutoConfigurationTests.java
+22
-0
RSocketSecurityAutoConfigurationTests.java
...curity/rsocket/RSocketSecurityAutoConfigurationTests.java
+74
-0
pom.xml
...g-boot-smoke-tests/spring-boot-smoke-test-rsocket/pom.xml
+8
-0
application.properties
...ke-test-rsocket/src/main/resources/application.properties
+1
-0
SampleRSocketApplicationTests.java
...java/smoketest/rsocket/SampleRSocketApplicationTests.java
+14
-1
No files found.
spring-boot-project/spring-boot-autoconfigure/pom.xml
View file @
40ac5b4a
...
...
@@ -682,6 +682,11 @@
<artifactId>
spring-security-oauth2-resource-server
</artifactId>
<optional>
true
</optional>
</dependency>
<dependency>
<groupId>
org.springframework.security
</groupId>
<artifactId>
spring-security-rsocket
</artifactId>
<optional>
true
</optional>
</dependency>
<dependency>
<groupId>
org.springframework.security
</groupId>
<artifactId>
spring-security-saml2-service-provider
</artifactId>
...
...
spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/reactive/ReactiveUserDetailsServiceAutoConfiguration.java
View file @
40ac5b4a
...
...
@@ -23,12 +23,19 @@ import org.apache.commons.logging.Log;
import
org.apache.commons.logging.LogFactory
;
import
org.springframework.beans.factory.ObjectProvider
;
import
org.springframework.boot.autoconfigure.AutoConfigureAfter
;
import
org.springframework.boot.autoconfigure.condition.AnyNestedCondition
;
import
org.springframework.boot.autoconfigure.condition.ConditionalOnBean
;
import
org.springframework.boot.autoconfigure.condition.ConditionalOnClass
;
import
org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean
;
import
org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication
;
import
org.springframework.boot.autoconfigure.rsocket.RSocketMessagingAutoConfiguration
;
import
org.springframework.boot.autoconfigure.security.SecurityProperties
;
import
org.springframework.boot.context.properties.EnableConfigurationProperties
;
import
org.springframework.context.annotation.Bean
;
import
org.springframework.context.annotation.Conditional
;
import
org.springframework.context.annotation.Configuration
;
import
org.springframework.messaging.rsocket.annotation.support.RSocketMessageHandler
;
import
org.springframework.security.authentication.ReactiveAuthenticationManager
;
import
org.springframework.security.core.userdetails.MapReactiveUserDetailsService
;
import
org.springframework.security.core.userdetails.ReactiveUserDetailsService
;
...
...
@@ -51,7 +58,9 @@ import org.springframework.util.StringUtils;
@ConditionalOnMissingBean
(
value
=
{
ReactiveAuthenticationManager
.
class
,
ReactiveUserDetailsService
.
class
},
type
=
{
"org.springframework.security.oauth2.jwt.ReactiveJwtDecoder"
,
"org.springframework.security.oauth2.server.resource.introspection.ReactiveOpaqueTokenIntrospector"
})
@ConditionalOnWebApplication
(
type
=
ConditionalOnWebApplication
.
Type
.
REACTIVE
)
@Conditional
(
ReactiveUserDetailsServiceAutoConfiguration
.
ReactiveUserDetailsServiceCondition
.
class
)
@EnableConfigurationProperties
(
SecurityProperties
.
class
)
@AutoConfigureAfter
(
RSocketMessagingAutoConfiguration
.
class
)
public
class
ReactiveUserDetailsServiceAutoConfiguration
{
private
static
final
String
NOOP_PASSWORD_PREFIX
=
"{noop}"
;
...
...
@@ -84,4 +93,22 @@ public class ReactiveUserDetailsServiceAutoConfiguration {
return
NOOP_PASSWORD_PREFIX
+
password
;
}
static
class
ReactiveUserDetailsServiceCondition
extends
AnyNestedCondition
{
ReactiveUserDetailsServiceCondition
()
{
super
(
ConfigurationPhase
.
REGISTER_BEAN
);
}
@ConditionalOnBean
(
RSocketMessageHandler
.
class
)
static
class
RSocketSecurityEnabledCondition
{
}
@ConditionalOnWebApplication
(
type
=
ConditionalOnWebApplication
.
Type
.
REACTIVE
)
static
class
ReactiveWebApplicationCondition
{
}
}
}
spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/rsocket/RSocketSecurityAutoConfiguration.java
0 → 100644
View file @
40ac5b4a
/*
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
org
.
springframework
.
boot
.
autoconfigure
.
security
.
rsocket
;
import
org.springframework.boot.autoconfigure.EnableAutoConfiguration
;
import
org.springframework.boot.autoconfigure.condition.ConditionalOnClass
;
import
org.springframework.boot.rsocket.server.ServerRSocketFactoryProcessor
;
import
org.springframework.context.annotation.Bean
;
import
org.springframework.context.annotation.Configuration
;
import
org.springframework.security.config.annotation.rsocket.EnableRSocketSecurity
;
import
org.springframework.security.rsocket.core.SecuritySocketAcceptorInterceptor
;
/**
* {@link EnableAutoConfiguration Auto-configuration} for Spring Security for an RSocket
* server.
*
* @author Madhura Bhave
* @since 2.2.0
*/
@Configuration
(
proxyBeanMethods
=
false
)
@EnableRSocketSecurity
@ConditionalOnClass
(
SecuritySocketAcceptorInterceptor
.
class
)
public
class
RSocketSecurityAutoConfiguration
{
@Bean
ServerRSocketFactoryProcessor
springSecurityRSocketSecurity
(
SecuritySocketAcceptorInterceptor
interceptor
)
{
return
(
factory
)
->
factory
.
addSocketAcceptorPlugin
(
interceptor
);
}
}
spring-boot-project/spring-boot-autoconfigure/src/main/resources/META-INF/spring.factories
View file @
40ac5b4a
...
...
@@ -109,6 +109,7 @@ org.springframework.boot.autoconfigure.security.servlet.UserDetailsServiceAutoCo
org.springframework.boot.autoconfigure.security.servlet.SecurityFilterAutoConfiguration,\
org.springframework.boot.autoconfigure.security.reactive.ReactiveSecurityAutoConfiguration,\
org.springframework.boot.autoconfigure.security.reactive.ReactiveUserDetailsServiceAutoConfiguration,\
org.springframework.boot.autoconfigure.security.rsocket.RSocketSecurityAutoConfiguration,\
org.springframework.boot.autoconfigure.security.saml2.Saml2RelyingPartyAutoConfiguration,\
org.springframework.boot.autoconfigure.sendgrid.SendGridAutoConfiguration,\
org.springframework.boot.autoconfigure.session.SessionAutoConfiguration,\
...
...
spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/reactive/ReactiveUserDetailsServiceAutoConfigurationTests.java
View file @
40ac5b4a
...
...
@@ -21,13 +21,17 @@ import java.time.Duration;
import
org.junit.jupiter.api.Test
;
import
org.springframework.boot.autoconfigure.AutoConfigurations
;
import
org.springframework.boot.autoconfigure.rsocket.RSocketMessagingAutoConfiguration
;
import
org.springframework.boot.autoconfigure.rsocket.RSocketStrategiesAutoConfiguration
;
import
org.springframework.boot.autoconfigure.security.SecurityProperties
;
import
org.springframework.boot.context.properties.EnableConfigurationProperties
;
import
org.springframework.boot.test.context.runner.ApplicationContextRunner
;
import
org.springframework.boot.test.context.runner.ReactiveWebApplicationContextRunner
;
import
org.springframework.context.annotation.Bean
;
import
org.springframework.context.annotation.Configuration
;
import
org.springframework.context.annotation.Import
;
import
org.springframework.security.authentication.ReactiveAuthenticationManager
;
import
org.springframework.security.config.annotation.rsocket.EnableRSocketSecurity
;
import
org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity
;
import
org.springframework.security.core.userdetails.MapReactiveUserDetailsService
;
import
org.springframework.security.core.userdetails.ReactiveUserDetailsService
;
...
...
@@ -59,6 +63,17 @@ class ReactiveUserDetailsServiceAutoConfigurationTests {
});
}
@Test
void
userDetailsServiceWhenRSocketConfigured
()
{
new
ApplicationContextRunner
()
.
withConfiguration
(
AutoConfigurations
.
of
(
ReactiveUserDetailsServiceAutoConfiguration
.
class
,
RSocketMessagingAutoConfiguration
.
class
,
RSocketStrategiesAutoConfiguration
.
class
))
.
withUserConfiguration
(
TestRSocketSecurityConfiguration
.
class
).
run
((
context
)
->
{
ReactiveUserDetailsService
userDetailsService
=
context
.
getBean
(
ReactiveUserDetailsService
.
class
);
assertThat
(
userDetailsService
.
findByUsername
(
"user"
).
block
(
Duration
.
ofSeconds
(
30
))).
isNotNull
();
});
}
@Test
void
doesNotConfigureDefaultUserIfUserDetailsServiceAvailable
()
{
this
.
contextRunner
.
withUserConfiguration
(
UserConfig
.
class
,
TestSecurityConfiguration
.
class
).
run
((
context
)
->
{
...
...
@@ -135,6 +150,13 @@ class ReactiveUserDetailsServiceAutoConfigurationTests {
}
@Configuration
(
proxyBeanMethods
=
false
)
@EnableRSocketSecurity
@EnableConfigurationProperties
(
SecurityProperties
.
class
)
static
class
TestRSocketSecurityConfiguration
{
}
@Configuration
(
proxyBeanMethods
=
false
)
static
class
UserConfig
{
...
...
spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/rsocket/RSocketSecurityAutoConfigurationTests.java
0 → 100644
View file @
40ac5b4a
/*
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
org
.
springframework
.
boot
.
autoconfigure
.
security
.
rsocket
;
import
java.util.List
;
import
io.rsocket.RSocketFactory
;
import
org.junit.jupiter.api.Test
;
import
org.mockito.ArgumentCaptor
;
import
org.mockito.Mockito
;
import
org.springframework.boot.autoconfigure.AutoConfigurations
;
import
org.springframework.boot.autoconfigure.rsocket.RSocketMessagingAutoConfiguration
;
import
org.springframework.boot.autoconfigure.rsocket.RSocketStrategiesAutoConfiguration
;
import
org.springframework.boot.autoconfigure.security.reactive.ReactiveUserDetailsServiceAutoConfiguration
;
import
org.springframework.boot.rsocket.server.ServerRSocketFactoryProcessor
;
import
org.springframework.boot.test.context.FilteredClassLoader
;
import
org.springframework.boot.test.context.runner.ApplicationContextRunner
;
import
org.springframework.security.config.annotation.rsocket.RSocketSecurity
;
import
org.springframework.security.rsocket.core.SecuritySocketAcceptorInterceptor
;
import
static
org
.
assertj
.
core
.
api
.
Assertions
.
assertThat
;
/**
* Tests for {@link RSocketSecurityAutoConfiguration}.
*
* @author Madhura Bhave
*/
class
RSocketSecurityAutoConfigurationTests
{
private
ApplicationContextRunner
contextRunner
=
new
ApplicationContextRunner
().
withConfiguration
(
AutoConfigurations
.
of
(
ReactiveUserDetailsServiceAutoConfiguration
.
class
,
RSocketSecurityAutoConfiguration
.
class
,
RSocketMessagingAutoConfiguration
.
class
,
RSocketStrategiesAutoConfiguration
.
class
));
@Test
void
autoConfigurationEnablesRSocketSecurity
()
{
this
.
contextRunner
.
run
((
context
)
->
assertThat
(
context
.
getBean
(
RSocketSecurity
.
class
)).
isNotNull
());
}
@Test
void
autoConfigurationIsConditionalOnSecuritySocketAcceptorInterceptorClass
()
{
this
.
contextRunner
.
withClassLoader
(
new
FilteredClassLoader
(
SecuritySocketAcceptorInterceptor
.
class
))
.
run
((
context
)
->
assertThat
(
context
).
doesNotHaveBean
(
RSocketSecurity
.
class
));
}
@Test
void
autoConfigurationAddsCustomizerForServerRSocketFactory
()
{
RSocketFactory
.
ServerRSocketFactory
factory
=
Mockito
.
mock
(
RSocketFactory
.
ServerRSocketFactory
.
class
);
ArgumentCaptor
<
SecuritySocketAcceptorInterceptor
>
captor
=
ArgumentCaptor
.
forClass
(
SecuritySocketAcceptorInterceptor
.
class
);
this
.
contextRunner
.
run
((
context
)
->
{
ServerRSocketFactoryProcessor
customizer
=
context
.
getBean
(
ServerRSocketFactoryProcessor
.
class
);
customizer
.
process
(
factory
);
Mockito
.
verify
(
factory
).
addSocketAcceptorPlugin
(
captor
.
capture
());
List
<
SecuritySocketAcceptorInterceptor
>
values
=
captor
.
getAllValues
();
assertThat
(
values
.
get
(
0
)).
isInstanceOf
(
SecuritySocketAcceptorInterceptor
.
class
);
});
}
}
spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-rsocket/pom.xml
View file @
40ac5b4a
...
...
@@ -36,6 +36,14 @@
<groupId>
org.springframework.boot
</groupId>
<artifactId>
spring-boot-starter-rsocket
</artifactId>
</dependency>
<dependency>
<groupId>
org.springframework.boot
</groupId>
<artifactId>
spring-boot-starter-security
</artifactId>
</dependency>
<dependency>
<groupId>
org.springframework.security
</groupId>
<artifactId>
spring-security-rsocket
</artifactId>
</dependency>
<!-- Test -->
<dependency>
<groupId>
org.springframework.boot
</groupId>
...
...
spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-rsocket/src/main/resources/application.properties
View file @
40ac5b4a
spring.rsocket.server.port
=
0
spring.security.user.password
=
password
spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-rsocket/src/test/java/smoketest/rsocket/SampleRSocketApplicationTests.java
View file @
40ac5b4a
...
...
@@ -27,6 +27,8 @@ import org.springframework.beans.factory.annotation.Autowired;
import
org.springframework.boot.rsocket.context.LocalRSocketServerPort
;
import
org.springframework.boot.test.context.SpringBootTest
;
import
org.springframework.messaging.rsocket.RSocketRequester
;
import
org.springframework.security.rsocket.metadata.BasicAuthenticationEncoder
;
import
org.springframework.security.rsocket.metadata.UsernamePasswordMetadata
;
@SpringBootTest
(
properties
=
"spring.rsocket.server.port=0"
)
public
class
SampleRSocketApplicationTests
{
...
...
@@ -38,9 +40,20 @@ public class SampleRSocketApplicationTests {
private
RSocketRequester
.
Builder
builder
;
@Test
void
test
RSocketEndpoint
()
{
void
unauthenticatedAccessTo
RSocketEndpoint
()
{
RSocketRequester
requester
=
this
.
builder
.
connectTcp
(
"localhost"
,
this
.
port
).
block
(
Duration
.
ofSeconds
(
5
));
Mono
<
Project
>
result
=
requester
.
route
(
"find.project.spring-boot"
).
retrieveMono
(
Project
.
class
);
StepVerifier
.
create
(
result
).
expectErrorMessage
(
"Access Denied"
).
verify
();
}
@Test
void
rSocketEndpoint
()
{
RSocketRequester
requester
=
this
.
builder
.
rsocketStrategies
((
builder
)
->
builder
.
encoder
(
new
BasicAuthenticationEncoder
()))
.
setupMetadata
(
new
UsernamePasswordMetadata
(
"user"
,
"password"
),
UsernamePasswordMetadata
.
BASIC_AUTHENTICATION_MIME_TYPE
)
.
connectTcp
(
"localhost"
,
this
.
port
).
block
(
Duration
.
ofSeconds
(
5
));
Mono
<
Project
>
result
=
requester
.
route
(
"find.project.spring-boot"
).
retrieveMono
(
Project
.
class
);
StepVerifier
.
create
(
result
)
.
assertNext
((
project
)
->
Assertions
.
assertThat
(
project
.
getName
()).
isEqualTo
(
"spring-boot"
))
.
verifyComplete
();
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment