I need to update my Spring Security configuration to introduce multi-tenant management (where I get URL for each web request and through a configuration file I retrieve the correct schema). So I add a filter (because with handler the login page doesn't have the correct schema since the handler is called after spring security) to my spring security configuration but now I catch the URL, set the schema but the page still empty and doesn't redirect to login page and also if I write /login no HTML page appears.
This is how I have configured spring security:
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true, proxyTargetClass = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private DataSource dataSource;
@Autowired
private RoleServices roleServices;
@Autowired
private CustomSuccessHandler customSuccessHandler;
@Autowired
public void configAuthentication(AuthenticationManagerBuilder auth)throws Exception {
auth.jdbcAuthentication().dataSource(dataSource)
.passwordEncoder(passwordEncoder())
.usersByUsernameQuery("select username,password,enabled from user where username=?")
.authoritiesByUsernameQuery("select u.username, CONCAT('ROLE_' , r.role) from user u inner join role r on u.idRole = r.idRole where lower(u.username) = lower(?)");
}
@Bean
public PasswordEncoder passwordEncoder(){
PasswordEncoder encoder = new BCryptPasswordEncoder();
return encoder;
}
@Override
public void configure(WebSecurity web) throws Exception {
web
//Spring Security ignores request to static resources such as CSS or JS files.
.ignoring()
.antMatchers("/static/**","/users/{\\d+}/password/recover","/users/{\\d+}/token/{\\d+}/password/temporary")
.antMatchers(HttpMethod.PUT,"/users/{\\d+}/token/{\\d+}/password/temporary");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
List<Role> roles=roleServices.getRoles();
//Retrieve array of roles(only string field without id)
String[] rolesArray = new String[roles.size()];
int i=0;
for (Role role:roles){
rolesArray[i++] = role.getRole();
}
http
.authorizeRequests() //Authorize Request Configuration
.anyRequest().hasAnyRole(rolesArray)//.authenticated()
.and()//Login Form configuration for all others
.formLogin()
.loginPage("/login").successHandler(customSuccessHandler)
//important because otherwise it goes in a loop because login page require authentication and authentication require login page
.permitAll()
.and()
.exceptionHandling().accessDeniedPage("/403")
.and()
.logout()
.logoutSuccessUrl("/login?logout")
.deleteCookies("JSESSIONID", "JSESSIONID")
.invalidateHttpSession(true)
.permitAll()
.and()
.sessionManagement().invalidSessionUrl("/login")
.and()
.addFilterAfter(new MultiTenancyInterceptor(), BasicAuthenticationFilter.class);
}
}
I added MultiTenancyInterceptor
filter where I set the Tenant
@Component
public class MultiTenancyInterceptor extends OncePerRequestFilter {
@Override
public void doFilterInternal(HttpServletRequest request,
HttpServletResponse response,
FilterChain filterChain)
throws IOException, ServletException {
String url = request.getRequestURL().toString();
URI uri;
try {
uri = new URI(url);
String domain = uri.getHost();
if(domain!=null){
TenantContext.setCurrentTenant(domain);
}
} catch (URISyntaxException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
but as I write the controller of login page doesn't receive the call:
@Override
@RequestMapping(value = { "/login" }, method = RequestMethod.GET)
public String loginPage(){
return "login";
}
Do you see an error in my configure
method? If you need further information I can add the other classes. Thanks
PS: I noticed that doFilter
is called twice for each page request
Best way is to implement Filter inteface and do some your url logic and then forward it to next action using filterChain.doFilter(request, response); Make sure to add this filter in web.xml.
Either way is you can use spring org.springframework.web.servlet.handler.HandlerInterceptorAdapter for pre and post handling for http requests. Spring internally forwards to next controller request method.
Example : https://www.mkyong.com/spring-mvc/spring-mvc-handler-interceptors-example/
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