My configuration:
#Autowired
private PasswordEncoder passwordEncoder;
#Bean
public PasswordEncoder passwordEncoderBean() {
return new BCryptPasswordEncoder();
}
#Bean
#Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
// #Autowired
#Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.userDetailsService(jwtUserDetailsService)
.passwordEncoder(passwordEncoder);
}
this code works fine. But if I remove #Autowired from passwordEncoder, then I must add #Autowired on the configure method. But this rules not apply on authenticationManagerBean() method. Can anyone explain ?
Look at this URL https://spring.io/guides/topicals/spring-security-architecture/
It seems that you Autowire AuthenticationManagerBuilder auth as a #Bean here.
Configure(AuthenticationManagerBuilder auth) so it will work in this case and passwordEncoder is also Autowired.
It seems you use Spring annotations configuration,
If you don't add Spring annotations to method or field, Spring doesn't know it need to be initiated and therefore when used in Spring context ( also without initialize it outside Spring), objects will be null
For security reasons you need to avoid storing the password in plaintext. based on this principle you have this option to encode your password.
In your example, you are using the PasswordEncoder interface:
.passwordEncoder(passwordEncoder);
Using this approach you must inform one implementation. In Spring you can inject this implementation using #Autowired (in the declaration or like your code on the method that use your PasswordEncoder interface).
Just a question... Why you created one implementation?
public PasswordEncoder passwordEncoderBean(){...
I think that this method can be replaced for your Autowired encode interface.
Related
I have in a given project the circumstance that I need to extend or overwrite the default AccessDeniedHandler of spring.security. The reason is not important, but I need this to be able to implement custom behaviour whenever a MissingCsrfTokenException or InvalidCsrfTokenException is thrown.
My question is: How to override the org.springframework.security.web.access.AccessDeniedHandler class properly?
Meanwhile I figured out 3 ways which seem to be promising:
Set my custom version of AccessDeniedHandlerImpl when configuring spring.security as instance of my class
Set my custom accessDeniedHandler when configuring spring.security and get it as a bean
Override AccessDeniedHandlerImpl with #Component named AccessDeniedHandler and set it as #Primary
I am new to spring framework and unsure how to solve this the best way.
From my understanding as a technician, I would prefer setting my custom AccessDeniedHandler through spring.security configuration (independent of the way I configure it there). Because using a component will require any other developer to look up for the annotations (but maybe I am wrong with this).
Implementing it through spring security configuration
// in the spring security configuration class
protected void configure(final HttpSecurity http) throws Exception {
http
.exceptionHandling().accessDeniedHandler(new CustomAccessDeniedHandler());
}
or
// in the spring security configuration class
#Bean
public AccessDeniedHandler accessDeniedHandler(){
return new CustomAccessDeniedHandler();
}
protected void configure(final HttpSecurity http) throws Exception {
http
.exceptionHandling().accessDeniedHandler(accessDeniedHandler());
}
As a component override
// in custom AccessDeniedHandler class
#Component
#Primary
public CustomAccessDeniedHandler implements AccessDeniedHandler {
// custom implementation
}
Which will automatically fetch my custom AccessDeniedHandler instead of the default AccessDeniedHandlerImpl defined in org.springframework.security.
Finally the point for me is to figure out, what is the better way to implement this, through configuration or #Component and #Primary.
So I am studying Spring Security for a implementation. I came across a piece of code I cannot get my head around. So as per documentation the following method needs to be overridden when we want to customize the AuthenticationManager used by Spring.
protected void configure(AuthenticationManagerBuilder auth) throws java.lang.Exception
My question is who is calling this method and passing the AuthenticationManagerBuilder instance here.
The working examples I see do not create/expose any AuthenticationManagerBuilder bean.
Also , i see the following in the documentation,
protected AuthenticationManager authenticationManager()
throws java.lang.Exception Gets the AuthenticationManager to use.
The default
strategy is if configure(AuthenticationManagerBuilder) method is
overridden to use the AuthenticationManagerBuilder that was passed in.
Otherwise, autowire the AuthenticationManager by type.
The overridden method is a void method and probably that is why I am getting confused more w.r.t what it is doing/should be doing.
Any help/pointers are highly appreciated. I know it works I just cant seem to figure out how.
Much thanks.
Assuming following is the code you came across
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(MyAuthenticationProvider);
}
}
Note that
The WebSecurityConfigurerAdapter provides a convenient base
class for creating a WebSecurityConfigurer instance.
The WebSecurityConfigurerAdapter implementation is a
Configuration as it is annotated with #EnableWebSecurity
Here
#EnableWebSecurity is meta-annotated with #EnableGlobalAuthentication
#Retention(value=RUNTIME)
#Target(value=TYPE)
#Documented
#Import(value={WebSecurityConfiguration.class,org.springframework.security.config.annotation.web.configuration.SpringWebMvcImportSelector.class,org.springframework.security.config.annotation.web.configuration.OAuth2ImportSelector.class})
#EnableGlobalAuthentication
#Configuration
public #interface EnableWebSecurity
and #EnableGlobalAuthentication imports AuthenticationConfiguration
#Retention(value=RUNTIME)
#Target(value=TYPE)
#Documented
#Import(value=AuthenticationConfiguration.class)
#Configuration
public #interface EnableGlobalAuthentication
AuthenticationConfiguration has the following piece of code that registers AuthenticationManagerBuilder as a bean
#Bean
public AuthenticationManagerBuilder authenticationManagerBuilder(
ObjectPostProcessor<Object> objectPostProcessor, ApplicationContext context) {
...
}
I want to use #Autowire with a Filter. So I define my filter in the SecurityConfig as below:
#Override
protected void configure(HttpSecurity http) throws Exception {
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
http.addFilterBefore(getA(), BasicAuthenticationFilter.class);
http.csrf().disable();
}
#Bean
public A getA(){
return new A();
}
This filter A extends Spring's GenericFilterBean.
I get below output when I invoke the controller, which shows the filter hits twice.
filter A before
filter A before
mycontroller invoke
filter A after
filter A after
My observation is, this extra invocation invoke with Spring container because if filter is not register as bean, it only get hits once. What is the reason and how can I fix it?
As you have observed, Spring Boot will automatically register any bean that is a Filter with the servlet container. One option is to not expose your filter as a bean and only register it with Spring Security.
If you want to be able to autowire dependencies into your Filter then it needs to be a bean. That means you need to tell Spring Boot not to register it as a filter. As described in the documentation, you do that using a FilterRegistrationBean:
#Bean
public FilterRegistrationBean registration(MyFilter filter) {
FilterRegistrationBean registration = new FilterRegistrationBean(filter);
registration.setEnabled(false);
return registration;
}
If you are on Spring 6.0.2 or plus version and if using OncePerRequestFilter,
Overriding shouldNotFilter method as follows will work.
#Override
protected boolean shouldNotFilter(HttpServletRequest request) {
return request.getServletPath().contains("/api/path/which/needs/to/exclude");
}
Removing #Component from the filter class helped me.
public class AuthTokenFilter extends OncePerRequestFilter {
}
In this example there is an #Autowired annotation on the configureGlobal method:
#EnableWebSecurity
public class MultiHttpSecurityConfig {
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) {
auth
.inMemoryAuthentication()
.withUser("user").password("password").roles("USER").and()
.withUser("admin").password("password").roles("USER", "ADMIN");
}
Is that necessary or does Spring automatically inject the AuthenticationBuilder on methods annotated with #EnableWebSecurity??
The code snippet is pulled from when-to-use-spring-securitys-antmatcher
According to Spring documentation #EnableWebSecurity is an annotation that only switches off the default web application security configuration in order to let you add some custom features like the configureGlobal.
configureGlobal should be #Autowired in order to get the AuthenticationManagerBuilder bean and define the authentication type for the application.
In conclusion #EnableWebSecurity doesn't inject beans, it only provides a way to customize the web security application.
#EnableWebSecurity
Is it possible to use Spring's #Autowired annotation within a Spring configuration written in Java?
For example:
#Configuration
public class SpringConfiguration{
#Autowired
DataSource datasource;
#Bean
public DataSource dataSource(){
return new dataSource();
}
// ...
}
Obviously a DataSource interface cannot be directly instantiated but I directly instantiated it here for simplification. Currently, when I try the above, the datasource object remains null and is not autowired by Spring.
I got #Autowired to work successfully with a Hibernate SessionFactory object by returning a FactoryBean<SessionFactory>.
So my question specifically: is there a way to do that with respect to a DataSource? Or more generally, what is the method to autowire a bean within a Spring Java Configuration?
I should note I am using Spring version 3.2.
If you need a reference to the DataSource bean within the same #Configuration file, just invoke the bean method.
#Bean
public OtherBean someOtherBean() {
return new OtherBean(dataSource());
}
or have it autowired into the #Bean method
#Bean
public OtherBean someOtherBean(DataSource dataSource) {
return new OtherBean(dataSource);
}
The lifecycle of a #Configuration class sometimes prevents autowiring like you are suggesting.
For completeness sake: Yes it is technically possible to use #Autowired annotation in spring #Configuration classes, and it works the same way as for other spring beans. But the accepted answer shows how the original problem should be solved.
maybe you can use constructor to inject some bean from other configuration file to your configuration,while #Autowired may not work correct in the configuration file
#Configuration
public class AppConfig {
private DataSource dataSource;
public AppConfig(DataSource dataSource) {
this.dataSource = dataSource;
}
#Bean
public OtherBean otherBean(){
return new OtherBean(dataSource);
}
}
beans configured with #Configuration class can't be autowired ,
So you cannot use #Autowiring and #configuration together