cemo koc (Migrated from SEC-2799) said:
We are migrating our architecture to Spring Boot and we have some issues. I want to add some filters from autoconfiguration classes. However I could not find an easy way to add another security filter. I have to use reflection and the only solution I can do currently is something like this:
@Configuration
public class Test implements WebSecurityConfigurer<WebSecurity> {
@Autowired
WebSecurityConfigurerAdapter configurerAdapter;
@Override
public void configure(WebSecurity builder) throws Exception {
//access by reflection
}
@Override
public void init(WebSecurity builder) throws Exception {
}
}
Please provide an easy way to configure filters.
Comment From: spring-projects-issues
Rob Winch said:
If you are trying to add Filters from autoconfigure classes you should be able to autowire the filter in and use something like this:
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
Filter autowiredFilter;
public void configure(HttpSecurity http) {
http
.adddFilter(autowiredFilter)
}
Comment From: spring-projects-issues
cemo koc said:
I have already a class which is extending WebSecurityConfigurerAdapter, say MySecurityConfig. I also want to add another filter to HttpSecurity from another configuration, say YourSecurityConfig.
For this case, I ended up having another instance of HttpSecurity inside YourSecurityConfig.
I believe that this is an important pattern. Many autoconfiguration libraries will try to this. I will include a jar in my classpath and It will configure automatically everything.
Any chance for this?
Comment From: spring-projects-issues
Rob Winch said:
I'm not sure I'm following. Can you provide a more concrete example (i.e. type out the classes and what you want to do)
Comment From: spring-projects-issues
cemo koc said:
This is our generic security config.
@EnableWebSecurity
@Configuration
public class MySecurityConfig extends WebSecurityConfigurerAdapter {
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
// implementation
}
@Override
public void configure(WebSecurity web) throws Exception {
// implementation
}
@Override
protected void configure(HttpSecurity http) throws Exception {
// implementation
}
}
In another jar I have a filter I would like to add my security filter chain. I dream of something like this in this jar. It can be autoconfigured by Spring Boot:
@Configuration
public class YourSecurityAutoConfiguration implements HttpSecurityConfigurer{
@Override
public void init(HttpSecurity security) throws Exception {
security.addFilter(new NewFilter());
}
}
Comment From: spring-projects-issues
Rob Winch said:
There can be multiple instances of HttpSecurity. How does it know which HttpSecurity to apply to?
Generally speaking the accepted pattern for customizing HttpSecurity is to apply a configurer to it. For example:
http
.apply(new CustomConfigurer())
.someCustomAttribute(1)
The CustomConfigurer would look like this:
public class CustomConfigurer extends SecurityConfigurerAdapter<DefaultSecurityFilterChain, HttpSecurity> {
@Override
public void configure(HttpSecurity http) throws Exception {
http
.addFilterBefore(new NewFilter(), UsernamePasswordAuthenticationFilter.class);
}
public CustomConfigurer someCustomAttribute(int attribute) {
// do something with attribute
return this;
}
}
Comment From: spring-projects-issues
cemo koc said:
Thanks for your explanation. I am considering a solution based on naming HttpSecurity configurations. For example each HttpSecurity might have a name and HttpSecurityConfigurer's configure them with a name. Is it a bad solution?
Comment From: spring-projects-issues
cemo koc said:
@Rob,
Is it bad that exposing HttpSecurity configurations as a bean?
My current hack is pretty ugly but totally working. I am marking my WebSecurityConfigurerAdapter as a primary and injecting it other configurations extensions.
For example, In our development environment we don't use https whereas at production I have to. I have done such a configuration and working pretty good.
@ConditionalOnNonDevelopment
@Configuration
@Order(value = Ordered.LOWEST_PRECEDENCE - 1987)
static class SecureChannelConfiguration implements WebSecurityConfigurer<WebSecurity> {
@Autowired
WebSecurityConfigurerAdapter webSecurityConfigurerAdapter;
@Override
public void init(WebSecurity builder) throws Exception {}
@Override
public void configure(WebSecurity builder) throws Exception {
getHttpSecurity()
.requiresChannel()
.antMatchers("/login", "/payment")
.requiresSecure()
.anyRequest()
.requiresInsecure();
}
private HttpSecurity getHttpSecurity() throws InvocationTargetException, IllegalAccessException {
Method method = findMethod(WebSecurityConfigurerAdapter.class, "getHttp");
makeAccessible(method);
HttpSecurity httpSecurity = (HttpSecurity) method.invoke(webSecurityConfigurerAdapter);
requireNonNull(httpSecurity);
return httpSecurity;
}
}
This is a serious need I believe.
Comment From: spring-projects-issues
Rob Winch said:
Personally, I would ensure you are using HTTPS in development as well (even if it is a self signed certificate) It is rather trivial to setup and ensures your development environment is more aligned with your production environment.
Most likely you will need different configurations for production though (i.e. different data store) and if you really want to support "requires HTTPS" in production only I think you are better off doing something like this:
@Value("#{systemProperties[production'] ?: true}")
private boolean production;
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin()
.and()
.httpBasic();
if(isProduction) {
http
.requiresChannel()
.anyRequest().requiresSecure();
}
}
A few notes: - This introduces the possibility of having a misconfiguration (take note that security misconfiguration is OWASP top 10) - I would NOT require secure channel for only part of your application (i.e. only for login and payment). You are asking for trouble. If you don't believe me, google for firesheep. If people give you the excuse that SSL is slow...it is not an excuse. See https://istlsfastyet.com/
Comment From: spring-projects-issues
cemo koc said:
@Rob thanks for throughout explanation. You are totally right. However this issue is not limited to channel configurations. HttpSecurity is a fundamental class in Spring Security and current centralised configuration style is limiting is power. I just wanted to show an use case to demonstrate our needs. Let me to give you some other use cases to convince you. :)
The primary idea behind my issue to split configurations to more declarative way. I would like to include a library and It should do its job by registering or fine tuning necessary points.
Other examples: 1. I have slightly updated RememberMe Services of Spring Security for our custom needs. I would like to register it by only including necessary library. 2. I would like to add some custom Configurer's without polluting my primary configuration. For example, I would like to apply a configurer easily for our REST API. 3. I have done some fine tuning to Servlet API configurations to better align with Servlet API. SEC-2797
Please let me know If you still wish extra samples to be convinced. I will gladly provide you. I really love Spring Security and I believe that this extension point will
Comment From: ghillert
@rwinch Found the need for this requirement as well. For when Spring Cloud Data Flow runs inside Cloud Foundry, I have to make minor tweaks to the existing security setup from a secondary configuration class. It seems that right now reflection is the only way to retrieve the HttpSecurity object from the injected WebSecurityConfigurerAdapter.
Comment From: rwinch
The HttpSecurity should not be accessed by other Configurations because it will cause ordering issues. We cannot force the external Configuration to be ran before Spring Security builds the HttpSecurity object.
Instead, you should use logic like this https://github.com/spring-projects/spring-security/issues/3022#issuecomment-180603538
Alternatively, you can encapsulate your logic in a DSL which has access to the entire Spring ApplicationContext using https://docs.spring.io/spring-security/site/docs/4.2.x/reference/html/jc.html#jc-custom-dsls