Since the Spring Security got updated, I had to do some changes in my code. This is my configuration class now.
public class SecurityConfig {
private final UserDetailsServiceImpl userDetailsService;
private final UserRepository userRepository;
public SecurityConfig(UserDetailsServiceImpl userDetailsService, UserRepository userRepository) {
this.userDetailsService = userDetailsService;
this.userRepository = userRepository;
}
@Bean
public AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception {
return authenticationConfiguration.getAuthenticationManager();
}
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http.csrf().disable()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.addFilter(new CustomAuthenticationFilter(authenticationManager()))
.addFilter(new CustomAuthorizationFilter(authenticationManager(), userRepository))
.authorizeRequests()
.antMatchers(HttpMethod.POST, "/user/users/save").permitAll()
.antMatchers(HttpMethod.POST, "/login").permitAll()
.antMatchers(HttpMethod.POST, "/users//register").permitAll()
.antMatchers("/**").permitAll() // Only for testing purposes
.antMatchers("/user/**").hasAuthority("ADMIN")
.antMatchers("/user/**").authenticated();
return http.build();
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
However, since I have changed the configure method and the authentication manager to beans, I am not able to pass the authentication manager to my filters. Which look like this.
public class CustomAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
private final AuthenticationManager authenticationManager;
@Value("${security.key}")
private String secretKey;
public CustomAuthenticationFilter(AuthenticationManager authenticationManager) {
this.authenticationManager = authenticationManager;
}
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
LoginRequest loginRequest = null;
try {
loginRequest = new ObjectMapper().readValue(request.getInputStream(), LoginRequest.class);
} catch (IOException e) {
throw new IllegalArgumentException();
}
String username = loginRequest.getUsername();
String password = loginRequest.getPassword();
UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(username, password);
return authenticationManager.authenticate(authenticationToken);
}
@Override
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authentication) throws IOException, ServletException {
UserDetailsImpl user = (UserDetailsImpl) authentication.getPrincipal();
Algorithm algorithm = HMAC512(secretKey.getBytes());
List<String> list = user.getAuthorities().stream().map(GrantedAuthority::getAuthority).collect(Collectors.toList());
String accessToken = JWT.create()
.withSubject(user.getUsername())
.withExpiresAt(new Date(System.currentTimeMillis()+10*60*1000))
.withClaim("authorities", list)
.sign(algorithm);
response.addHeader("authorization","Bearer " + accessToken);
}
}
How can I inject the authenticationManager to my filter?
The recommended way to access the AuthenticationManager is by using a custom DSL. This is actually how Spring Security internally implements methods like HttpSecurity.authorizeRequests().
public class MyCustomDsl extends AbstractHttpConfigurer<MyCustomDsl, HttpSecurity> {
@Override
public void configure(HttpSecurity http) throws Exception {
AuthenticationManager authenticationManager = http.getSharedObject(AuthenticationManager.class);
http.addFilter(new CustomAuthenticationFilter(authenticationManager));
}
public static MyCustomDsl customDsl() {
return new MyCustomDsl();
}
}
The custom DSL can then be applied when building the SecurityFilterChain:
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
// ...
http.apply(customDsl());
return http.build();
}
This is described in the blog post on migrating away from the WebSecurityConfigurerAdapter, under the section "Accessing the local AuthenticationManager".
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With