In the following class that extends WebSecurityConfigurerAdapter i've overwritten the configure(HttpSecurity) method.
#Configuration
#EnableGlobalMethodSecurity(securedEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter{
#Autowired
public void configureAuth(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("fabio")
.password("123")
.roles("ADMIN")
.and()
.withUser("joe")
.password("123")
.roles("GUEST");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/post/list").permitAll()
.antMatchers("/admin/**").hasRole("ADMIN")
.anyRequest().authenticated()
.and()
.formLogin()
.and()
.logout();
}
}
With this i should be able to get to localhost:8080/post/list page without having to commit to a user login since it has the .permitAll() , but when i try to getting into it it always prompts the login page before, only after i enter the previous credentials i'm able to view it. How can i fix this ?
controller class
#RestController
#RequestMapping("/post")
public class HomeController {
#Secured("ROLE_GUEST")
#RequestMapping("/list")
public String list(){
return "list...";
}
#Secured("ROLE_USER")
#RequestMapping("/drafts")
public String drafts(){
return "drafts...";
}
#Secured({"ROLE_ADMIN","ROLE_USER"})
#RequestMapping("/add")
public String add(){
return "adding...";
}
}
According to the #RequestMapping definition there is a conflict because it is secured by annotation #Secured("ROLE_GUEST") but also you need to access it with .permitAll() configuration.
Option 1: Just remove the #Secured("ROLE_GUEST") in order to let .permitAll() do the work.
Option 2: use #Secured("ROLE_ANONYMOUS") on the #RequestMapping("/list") instead of #Secured("ROLE_GUEST"). You can see the definition of ROLE_ANONYMOUS in the Spring Documentation
It will depends on the path value after /post/list. Please see the following examples of how to define antMatchers depending on the path value.
localhost:8080/post/list = .antMatchers( "/post/list").permitAll()
localhost:8080/post/list/stuff = .antMatchers( "/post/list/**").permitAll()
localhost:8080/post/list, localhost:8080/post/list1234
= .antMatchers( "/post/list**").permitAll()
For more information visit the AnthPathMatcher documentation and HttpSecurity
Related
I'm trying to add security headers to my Spring Boot application.
It already had a Java class with multiple filters extending from WebSecurityConfigurerAdapter. But whenever I try to add the annotation #EnableWebSecurity to this class or even with a new custom one I always receive NullPointerException for the bean springSecurityFilterChain.
Changing the order to add some filters seems to solve this problem but whenever I try to enter the app I can't because it seems the HTTP Authorization header field is null (which I recover inside one of my custom filters).
Do any have a clue of what is happening?
EDIT: After some days of cheking this I noted that the Authorization header was not the problem as the code is built to let that call enter without it and before any change it was already sent without header.
Still with the same call and the changes I'm receiving a 403 FORBIDDEN (before any change this call was receiving 302 FOUND).
This happens before even reaching the controller and I can only get debugging until the filter.
As there were no other changes in the code except the #EnableWebSecurity and the way to add one filter I suspect the problem is around here but i can't find what is causing it exactly.
EDIT: I'm adding the code in case anyone need to see it.
This is the class that has the multiple filters:
#Configuration
#EnableGlobalMethodSecurity(prePostEnabled = true)
#EnableWebSecurity //ADDED THIS ONE
public class MultipleEntryPointsSecurityConfig {
#Configuration
#Order(1)
public class OauthSecurityAdapter extends WebSecurityConfigurerAdapter {
#Autowired
private OAuth2RestTemplate restTemplate;
#Bean
public CustomFilterOneFilter customFilterOneFilter() {
final CustomFilterOneFilter filter = new CustomFilterOneFilter ("/testLogin");
filter.setRestTemplate(restTemplate);
return filter;
}
#Bean
public FilterRegistrationBean<OAuth2ClientContextFilter> oauth2ClientFilterRegistration(
OAuth2ClientContextFilter filter) {
FilterRegistrationBean<OAuth2ClientContextFilter> registration = new FilterRegistrationBean<OAuth2ClientContextFilter>();
registration.setFilter(filter);
registration.setOrder(-100);
return registration;
}
#Override
protected void configure(HttpSecurity http) throws Exception {
// #formatter:off
http
.antMatcher("/login")
.cors()
.and()
.csrf().disable()
//CHANGED THIS
// .addFilterAfter(openIdConnectFilter(), OAuth2ClientContextFilter.class)
//FOR THESE TWO
.addFilterAfter(new OAuth2ClientContextFilter(), AbstractPreAuthenticatedProcessingFilter.class)
.addFilterAfter(openIdConnectFilter(), OAuth2ClientContextFilter.class)
.httpBasic()
.authenticationEntryPoint(new LoginUrlAuthenticationEntryPoint("/testLogin"))
.and()
.logout()
.logoutSuccessUrl("/logout")
.permitAll()
.and()
.csrf().disable()
.authorizeRequests()
.anyRequest().authenticated();
// #formatter:on
}
}
#Configuration
#Order(2)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Bean
public JwtSecurityFilter authenticationJwtTokenFilter() {
return new JwtSecurityFilter();
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.antMatcher("/api/**")
.cors()
.and()
.csrf().disable()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers("/api/**").authenticated();
http
.addFilterAfter(new UsernamePasswordAuthenticationFilter(), AbstractPreAuthenticatedProcessingFilter.class)
.addFilterAfter(authenticationJwtTokenFilter(), UsernamePasswordAuthenticationFilter.class);
//CHANGED THE BELOW ONE FOR THE TWO ABOVE
//http.addFilterBefore(authenticationJwtTokenFilter(), UsernamePasswordAuthenticationFilter.class);
}
}
#Configuration
#Order(3)
public static class PublicConfigurationAdapter extends WebSecurityConfigurerAdapter {
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers(HttpMethod.GET, "/**").permitAll()
.antMatchers("/api/v1/login/**").permitAll();
}
}
}
And this is the custom filter where I try to recover the Authorization header:
#Component
public class JwtSecurityFilter extends OncePerRequestFilter{
#Override
public void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
throws IOException, ServletException {
String authHeader = request.getHeader(HttpHeaders.AUTHORIZATION);
//FAILS HERE!
if(authHeader == null || !authHeader.startsWith("Bearer ")) {
SecurityContextHolder.getContext().setAuthentication(null);
chain.doFilter(request, response);
return;
}
...
}
}
I want to restrict usage of endpoints based on roles: admin/user.
So I'm trying to implement Spring Security using NoOpPasswordEncoder (for testing purpose),
but the problem is:
all endpoints return status 200 and unresponsive to constraints as antMatchers.
To clarify: I want to log in as user and get the error because of antMatcher:
.antMatchers("/api/addresses")
.hasAuthority("ROLE_ADMIN")
but I'm getting 200 using current configuration now.
I've tested Spring Security configuration in format:
#Configuration
#EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(inMemoryUserDetailsManager());
}
#Bean
public InMemoryUserDetailsManager inMemoryUserDetailsManager() {
final Properties users = new Properties();
users.put("admin","{noop}admin,ROLE_ADMIN,enabled");
users.put("user","{noop}user,ROLE_USER,enabled");
return new InMemoryUserDetailsManager(users);
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests()
.antMatchers("/api/addresses")
.access("hasAuthority('ROLE_ADMIN')")
.antMatchers("/api/address/**")
.access("hasAuthority('ROLE_ADMIN') or hasAuthority('ROLE_USER')")
.anyRequest()
.authenticated()
.and()
.httpBasic()
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}
}
based on example config.
While investigating, I've tried to comment, e.g. lines:
.antMatchers("/api/address/**")
.access("hasAuthority('ROLE_ADMIN') or hasAuthority('ROLE_USER')")
to check what happens and still receive 200 when log in as user.
also I've tried to use hasAuthority() methods like:
#Configuration
#EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(inMemoryUserDetailsManager());
}
#Bean
public InMemoryUserDetailsManager inMemoryUserDetailsManager() {
final Properties users = new Properties();
users.put("ADMIN","{noop}admin,ROLE_ADMIN,enabled");
users.put("USER","{noop}user,ROLE_USER,enabled");
return new InMemoryUserDetailsManager(users);
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests()
.antMatchers("/api/addresses")
.hasAuthority("ROLE_ADMIN")
.antMatchers("/api/address/**")
.hasAnyAuthority("ROLE_ADMIN", "ROLE_USER")
.anyRequest()
.authenticated()
.and()
.httpBasic()
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}
}
following the correct order with antMatchers(), when more specific rules have to go first, but it still doesn't help me.
Does anyone know what I'm missing here? Thanks in advance for any ideas.
UPD #1:
I've tried to clear cookies in Postman, log in as user, but I'm still getting 200.
I'm getting 401 only if I don't use Basic Auth in Postman for GET request:
UPD #2:
I've reproduced this issue using versions of technologies:
Java 11
spring-boot-starter-parent 2.5.3
spring-boot-starter-security 2.5.3
Cause & solutions:
The cause of issue was redundant configuration option:
server.servlet.context-path=/api
because /api prefix was already present in .antMatchers()
Solution #1:
To fix it I've removed it from application.properties file and add this prefix directly to endpoints.
Solution #2:
It can be solved vice versa: remove prefix /api in antMatchers() and leave:
server.servlet.context-path=/api
using application.properties
Solution #3:
Also I've solved the problem using another configuration:
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(inMemoryUserDetailsManager());
}
#Bean
public InMemoryUserDetailsManager inMemoryUserDetailsManager() {
final Properties users = new Properties();
users.put("admin","{noop}admin,ROLE_ADMIN,enabled");
users.put("user","{noop}user,ROLE_USER,enabled");
return new InMemoryUserDetailsManager(users);
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests()
.anyRequest()
.permitAll()
.and()
.httpBasic()
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}
}
with adding annotations on methods of controller:
#PreAuthorize("hasAuthority('ROLE_ADMIN')")
and accordingly:
#PreAuthorize("hasAuthority('ROLE_ADMIN') or hasAuthority('ROLE_USER')")
As result I'm getting 403 instead of 200:
im exploring a little of spring.
i got across spring boot for easy endpoints see:
#Controller
#EnableAutoConfiguration
public class SampleController {
#RequestMapping("/sample")
#ResponseBody
String sample() {
return "Hello sample!";
}
#RequestMapping("/sample2")
#ResponseBody
String sample2() {
return "Hello sample secured!";
}
}
logically the endpoints are accessible on localhost:8181/sample
but on using spring security the "protected" endpoint becames unaccessible because the login page gives me 404
my security class is as follows:
#Configuration
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/sample" ).permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll()
.and()
.logout()
.permitAll();
}
#Bean
#Override
public UserDetailsService userDetailsService() {
UserDetails user =
User.withDefaultPasswordEncoder()
.username("user")
.password("password")
.roles("USER")
.build();
return new InMemoryUserDetailsManager(user);
}
}
i am able to access /sample as is not protected. but unable to access /sample2 as it redirects to /login
im configuring my security class according to this guide: https://spring.io/guides/gs/securing-web/
I am able to access /sample as is not protected. But unable to access
/sample2 as it redirects to /login
Because you have not by-passed /sample2 in your security configuration.
.antMatchers("/sample2" ).permitAll()
Another thing is that as you have specified custom login page
.formLogin()
.loginPage("/login")
you have to provide a login page.
Inject userDetailsService into authenticationProvider:
#Bean
public AuthenticationProvider authenticationProvider(){
DaoAuthenticationProvider authenticationProvider=new CustomAuthenticationProvider();
authenticationProvider.setUserDetailsService(userDetailsService());
return authenticationProvider;
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception{
auth.authenticationProvider(authenticationProvider());
}
Add this configuration to spring security:
.antMatchers("/sample2").hasRole("USER")
So I have a two login pages. One for Customer and one for AM. I configured 2 login pages in my WebSecurityConfig class. When I try to login in AM using an admin account it works but when I try to login in Customer using a user account the loginProcessingUrl can't be found.
In my WebSecurityConfig class:
#Configuration
#EnableWebSecurity
public class WebSecurityConfig
{
#Autowired
MyDBAuthenticationService myDBAuthenticationService;
#Autowired
public void configureGlobalSecurity(AuthenticationManagerBuilder auth) throws Exception
{
auth.userDetailsService(myDBAuthenticationService);
}
#Configuration
#Order(1)
public static class WebConfigurationAdapter1 extends WebSecurityConfigurerAdapter
{
#Override
protected void configure(HttpSecurity http) throws Exception
{
http
.authorizeRequests().antMatchers("/am/**").access("hasRole('ROLE_AM')")
.and()
.exceptionHandling()
.accessDeniedPage("/403")
.and()
.formLogin()
.loginPage("/amLogin")
.loginProcessingUrl("/am/postLogin")
.defaultSuccessUrl("/amChatPage")
.failureUrl("/amLogin?error")
.and().logout().logoutUrl("/amLogout").logoutSuccessUrl("/amLogoutSuccessful")
.deleteCookies("JSESSIONID")
.and().csrf().disable();
System.out.println("1st Configurer");
}
}
#Configuration
#Order(2)
public static class WebConfigurationAdapter2 extends WebSecurityConfigurerAdapter
{
#Override
protected void configure(HttpSecurity http) throws Exception
{
http
.authorizeRequests().antMatchers("/customer/**").access("hasRole('ROLE_CUSTOMER')")
.and()
.exceptionHandling()
.accessDeniedPage("/403")
.and()
.formLogin()
.loginPage("/customerLogin")
.loginProcessingUrl("/customer/postLogin")
.defaultSuccessUrl("/customerChatPage")
.failureUrl("/customerLogin?error")
.and().logout().logoutUrl("/customerLogout").logoutSuccessUrl("/customerLogoutSuccessful")
.and().csrf().disable();
System.out.println("2nd Configurer");
}
}
}
Here's my SpringWebAppInitializer class:
#Configuration
public class SpringWebAppInitializer implements WebApplicationInitializer{
#Override
public void onStartup(ServletContext sc) throws ServletException {
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
context.register(ApplicationContextConfig.class);
ServletRegistration.Dynamic dispatcher = sc.addServlet("dispatcher", new DispatcherServlet(context));
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping("/");
}
}
Things that I have done so far are:
Putting sout() in each static class to know if it gets run. Both did display the sout().
Change name of both processing url and make it unique. Also change in my jsp file.
Spring boot - how to configure multiple login pages?
Here is the result when I login as AM:
Result in netbeans. It enters the Controller but says "null"
Here is the result when I login as Customer:
Since there is no differentiation pattern between both http configuration Spring Security is taking the first one login as default, that is the reason why only admin login works, because it is part of the web security adapter declared as Order(1).
In order to separate both configuration properly it is necessary to define a pattern separation with .antMatcher.
here is one small example to give you an idea of how define both configuration
For admins (see the .antMatcher definition it forces to apply the http configuration only to admin/** urls.
#Override
protected void configure(HttpSecurity http) throws Exception
{
http
.antMatcher("/admin/**").authorizeRequests().anyRequest().authenticated().anyRequest().hasRole("ADMIN")
.and()
.formLogin()
.loginPage("/adminLogin")
.loginProcessingUrl("/admin/postLogin")
.defaultSuccessUrl("/admin/home")
.failureUrl("/adminLogin?error")
.and().logout().logoutUrl("/admin/logout").logoutSuccessUrl("/home")
.and()
.csrf().disable();
}
For customers (see the .antMatcher definition it forces to apply the http configuration only to customer/** urls.
#Override
protected void configure(HttpSecurity http) throws Exception
{
http
.antMatcher("/customer/**").authorizeRequests().anyRequest().authenticated().anyRequest().hasRole("USER")
.and()
.formLogin()
.loginPage("/customerLogin")
.loginProcessingUrl("/customer/postLogin")
.defaultSuccessUrl("/customer/home")
.failureUrl("/customerLogin?error")
.and()
.logout().logoutUrl("/customer/logout").logoutSuccessUrl("/home")
.and()
.csrf().disable();
}
There are other examples here: Example two login pages and visit the spring security documentation Multiple Http Security
Hope this information helps you.
According to the new configuration you have to do some changes, please review the following configuration, and compare with yours and you will see what is the difference (antMatcher is different of antMatchers)
#Configuration
#EnableWebSecurity
public class WebSecurityConfig
{
#Autowired
MyDBAuthenticationService myDBAuthenticationService;
#Autowired
public void configureGlobalSecurity(AuthenticationManagerBuilder auth) throws Exception
{
auth.userDetailsService(myDBAuthenticationService);
}
#Configuration
#Order(1)
public static class WebConfigurationAdapter1 extends WebSecurityConfigurerAdapter
{
#Override
protected void configure(HttpSecurity http) throws Exception
{
http
//.authorizeRequests().antMatchers("/am/**").access("hasRole('ROLE_AM')")
.antMatcher("/am/**").authorizeRequests().anyRequest().hasRole("AM")
.and()
.exceptionHandling()
.accessDeniedPage("/403")
.and()
.formLogin()
.loginPage("/amLogin")
.loginProcessingUrl("/am/postLogin")
.defaultSuccessUrl("/am/chatPage")
.failureUrl("/amLogin?error")
.and().logout().logoutUrl("/am/logout").logoutSuccessUrl("/amLogoutSuccessful")
.deleteCookies("JSESSIONID")
.and().csrf().disable();
System.out.println("1st Configurer");
}
}
#Configuration
#Order(2)
public static class WebConfigurationAdapter2 extends WebSecurityConfigurerAdapter
{
#Override
protected void configure(HttpSecurity http) throws Exception
{
http
//.authorizeRequests().antMatchers("/customer/**").access("hasRole('ROLE_CUSTOMER')")
.antMatcher("/admin/**").authorizeRequests().anyRequest().hasRole("CUSTOMER")
.and()
.exceptionHandling()
.accessDeniedPage("/403")
.and()
.formLogin()
.loginPage("/customerLogin")
.loginProcessingUrl("/customer/postLogin")
.defaultSuccessUrl("/customer/chatPage")
.failureUrl("/customerLogin?error")
.and().logout().logoutUrl("/customer/logout").logoutSuccessUrl("/customerLogoutSuccessful")
.and().csrf().disable();
System.out.println("2nd Configurer");
}
}
}
And finally remember the controller, you should have the following RequestMapping definition at least
#RequestMapping("/adminLogin"), #RequestMapping("/customerLogin"), #RequestMapping("/am/chatPage"), #RequestMapping("/customer/chatPage")
I've got a problem with my Spring Boot application in which im trying to implement dynamically configured multiple login pages.
In the database are stored prefixes for pages and I'm trying to get multiple paths for separate login pages.
I'm trying to do it in the following SecurityConfig class
(global.getPath() returns a plain prefix String):
#Configuration
#EnableGlobalMethodSecurity( securedEnabled = true )
#Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private GlobalSettingsService globalSettingsService;
#Override
protected void configure(HttpSecurity http) throws Exception {
List<GlobalSettings> globals = globalSettingsService.findAll();
http
.authorizeRequests()
.antMatchers("/css/**", "/index").permitAll()
.antMatchers("/js/**", "/").permitAll()
.antMatchers("/fonts/**", "/img/**").permitAll();
for (GlobalSettings global : globals) {
http.authorizeRequests()
.antMatchers("/"+global.getPath()+"/**").permitAll()
.antMatchers("/"+global.getPath()+"/admin/**").hasAnyRole("USER","ADMIN")
.and()
.formLogin().loginProcessingUrl("/"+global.getPath()+"/login")
.loginPage("/"+global.getPath()+"/login").permitAll()
.defaultSuccessUrl("/"+global.getPath()+"/admin")
.failureUrl("/"+global.getPath()+"/login?error").permitAll()
.and()
.logout()
.logoutRequestMatcher(new AntPathRequestMatcher("/"+global.getPath()+"/login?logout"))
.logoutSuccessUrl("/"+global.getPath()+"/login?logout")
.permitAll();
}
}
}
Login forms views are configured in another class (WebConfig) which extends WebMvcConfigureAdapter:
for (GlobalSettings global : globals) {
registry.addViewController("/"+global.getPath()+"/login").setViewName(global.getPath()+"-/login-form");
}
I've got 3 prefixes to configure and the last one configured in the loop is working correctly (propably with the highest order?) - I can log in and out without any troubles.
So the configuration works only for the last prefix which is called in the loop. Other prefixes are rendering proper login forms but returning 405 code after login attempt with following message:
o.s.web.servlet.PageNotFound: Request method 'POST' not supported
So I made custom POST method definition in one of my controllers:
#RequestMapping(value = "/{path}/login", method = RequestMethod.POST)
public ModelAndView getLoginPage(#PathVariable("path") String path, #RequestParam Optional<String> error) {
return new ModelAndView(path+"-front/login-form", "error", error);
}
But unfortunately it's not being recognized, still getting 'Method not supported' message, while the login request path is correct.
Besides, the paths are mapping correctly during application initialization so I don't know where the problem is.
I tried many ways such as adding hidden _csrf field to the login form and still getting nothing.
Is it possible to do it avoiding prefixes hardcoding?
Is it related with #Order annotation or something like this?
Thanks for your time
I resolved it by rebuilding SecurityConfig class making separate WebSecurityConfigurerAdapters for each of my prefix:
#Configuration
#EnableGlobalMethodSecurity( securedEnabled = true )
#Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private UserService userService;
#Autowired
private GlobalSettingsService globalSettingsService;
#Configuration
#Order(1)
public static class FirstPrefixWebSecurityConfigurationAdapter extends WebSecurityConfigurerAdapter {
protected void configure(HttpSecurity http) throws Exception {
http
.antMatcher("/app1/**")
.authorizeRequests()
.antMatchers("/app1/**").permitAll()
.antMatchers("/app1/login").permitAll()
.antMatchers("/app1/admin/**")
.hasAnyRole("ADMIN","USER")
.and()
.formLogin().loginProcessingUrl("/app1/login")
.loginPage("/app1/login").permitAll()
.defaultSuccessUrl("/app1/admin")
.failureUrl("/app1/login?error").permitAll()
.and()
.logout()
.logoutRequestMatcher(new AntPathRequestMatcher("/app1/login?logout"))
.logoutSuccessUrl("/app1/login?logout")
.permitAll();
}
}
#Configuration
#Order(2)
public static class SecondPrefixWebSecurityConfigurationAdapter extends WebSecurityConfigurerAdapter {
protected void configure(HttpSecurity http) throws Exception {
http
.antMatcher("/app2/**")
.authorizeRequests()
.antMatchers("/app2/**").permitAll()
.antMatchers("/app2/login").permitAll()
.antMatchers("/app2/admin/**")
.hasAnyRole("ADMIN","USER")
.and()
.formLogin().loginProcessingUrl("/app2/login")
.loginPage("/app2/login").permitAll()
.defaultSuccessUrl("/app2/admin")
.failureUrl("/app2/login?error").permitAll()
.and()
.logout()
.logoutRequestMatcher(new AntPathRequestMatcher("/app2/login?logout"))
.logoutSuccessUrl("/app2/login?logout")
.permitAll();
}
}
#Configuration
#Order(3)
public static class ThirdPrefixWebSecurityConfigurationAdapter extends WebSecurityConfigurerAdapter {
protected void configure(HttpSecurity http) throws Exception {
http
.antMatcher("/app3/**")
.authorizeRequests()
.antMatchers("/app3/**").permitAll()
.antMatchers("/app3/login").permitAll()
.antMatchers("/app3/admin/**")
.hasAnyRole("ADMIN","USER")
.and()
.formLogin().loginProcessingUrl("/app3/login")
.loginPage("/app3/login").permitAll()
.defaultSuccessUrl("/app3/admin")
.failureUrl("/app3/login?error").permitAll()
.and()
.logout()
.logoutRequestMatcher(new AntPathRequestMatcher("/app3/login?logout"))
.logoutSuccessUrl("/app3/login?logout")
.permitAll();
}
}
}
It isn't a dynamic solution but it's alright for now.