有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java Spring启动多个登录页面,动态添加路径405'POST'不受支持

我的Spring Boot应用程序有一个问题,我试图实现动态配置的多个登录页面

数据库中存储了页面的前缀,我试图为单独的登录页面获取多个路径

我试图在下面的SecurityConfig类中实现这一点 (global.getPath()返回一个普通前缀字符串):

@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);
}

但不幸的是,它没有被识别,仍然会收到“Method not supported”(方法不受支持)消息,而登录请求路径是正确的

此外,路径在应用程序初始化期间映射正确,因此我不知道问题出在哪里。 我尝试了很多方法,比如在登录表单中添加隐藏的_csrf字段,但仍然一无所获

可以避免前缀硬编码吗? 它与@Order annotation或类似的东西有关吗

谢谢你抽出时间


共 (1) 个答案

  1. # 1 楼答案

    我通过重建SecurityConfig类解决了这个问题,为我的每个前缀创建了单独的WebSecurity配置适配器:

    @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();
    
    
            }
        }
    
    }
    

    这不是一个动态的解决方案,但目前还可以