Add Filter To Spring Security To Implement Multi Tenant
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
Answer
After the suggest of dur I add the code
filterChain.doFilter(request, response);
at the end of filter method
Related Questions
- → How to update data attribute on Ajax complete
- → October CMS - Radio Button Ajax Click Twice in a Row Causes Content to disappear
- → Octobercms Component Unique id (Twig & Javascript)
- → Passing a JS var from AJAX response to Twig
- → Laravel {!! Form::open() !!} doesn't work within AngularJS
- → DropzoneJS & Laravel - Output form validation errors
- → Import statement and Babel
- → Uncaught TypeError: Cannot read property '__SECRET_DOM_DO_NOT_USE_OR_YOU_WILL_BE_FIRED' of undefined
- → React-router: Passing props to children
- → ListView.DataSource looping data for React Native
- → Can't test submit handler in React component
- → React + Flux - How to avoid global variable
- → Webpack, React & Babel, not rendering DOM