我的Spring Boot应用程序出了问题,我试图实现动态配置的多个登录页面。
在数据库中存储了页面的前缀,我正在尝试获取单独登录页面的多个路径。
我正在尝试在以下SecurityConfig类中执行此操作 ( global.getPath()返回普通前缀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();
}
}
}
登录表单视图在另一个类(WebConfig)中配置,该类扩展了WebMvcConfigureAdapter:
for (GlobalSettings global : globals) {
registry.addViewController("/"+global.getPath()+"/login").setViewName(global.getPath()+"-/login-form");
}
我有3个前缀要配置,并且循环中配置的最后一个正常工作(可能是最高顺序?) - 我可以毫无困难地登录和退出。
因此配置仅适用于循环中调用的最后一个前缀。其他前缀正在呈现正确的登录表单,但在登录尝试后返回405代码,并显示以下消息:
o.s.web.servlet.PageNotFound: Request method 'POST' not supported
所以我在我的一个控制器中进行了自定义POST方法定义:
@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);
}
但遗憾的是,当登录请求路径正确时,它仍未被识别,仍然收到“方法不受支持”消息。
此外,在应用程序初始化期间路径正确映射,因此我不知道问题出在哪里。 我尝试了很多方法,比如在登录表单中添加隐藏的_csrf字段,但仍然没有任何结果。
是否可以避免前缀硬编码? 它与@Order注释有关吗?
感谢您的时间
答案 0 :(得分:0)
我通过重建SecurityConfig类来解决它,为每个前缀创建单独的WebSecurityConfigurerAdapters:
@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();
}
}
}
这不是一个动态的解决方案,但现在也没问题。