Java spring-boot 在单个 Web 应用程序路径上设置基本身份验证?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/24658285/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-14 13:53:37  来源:igfitidea点击:

spring-boot setup basic auth on a single web app path?

javaspring-mvcspring-securitybasic-authenticationspring-boot

提问by Aaron Zeckoski

I am trying to setup a single path (/basic) in my spring-boot spring MVC based application to be basic auth protected. I am just going to configure this using my own custom configuration parameters so the username and password are simply "admin" and "admin".

我正在尝试在基于 spring-boot spring MVC 的应用程序中设置单个路径 (/basic) 以进行基本身份验证保护。我只是要使用我自己的自定义配置参数来配置它,因此用户名和密码只是“admin”和“admin”。

This currently works for the /basic path (I am prompted and can login correctly). The problem is that logout does not work (and I am not sure why) and also other paths (like /other shown) are being asked for basic auth credentials (before always being denied).

这目前适用于 /basic 路径(我得到提示并且可以正确登录)。问题是注销不起作用(我不知道为什么)并且还要求其他路径(如 /other 所示)提供基本身份验证凭据(在总是被拒绝之前)。

static class MyApplicationSecurity extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests().antMatchers("/open").permitAll();
        http.authorizeRequests().antMatchers("/other").denyAll(); // Block it for now
         http.authorizeRequests().antMatchers("/basic").authenticated().and().httpBasic().and().logout().logoutUrl("/basic/logout").invalidateHttpSession(true).logoutSuccessUrl("/");
    }
}

I expected /other to always be denied but I don't get why basic auth is coming up for it. /open works as expected. I also don't understand why /basic/logout does not log me out (it also does not produce error messages). I do have a simple bit of code as a placeholder for the logout endpoint but if I do not have that then I get a 404. The "home" view is my web app root so I just want to send the user there after logout.

我希望 /other 总是被拒绝,但我不明白为什么会出现基本身份验证。/open 按预期工作。我也不明白为什么 /basic/logout 不会让我退出(它也不会产生错误消息)。我确实有一些简单的代码作为注销端点的占位符,但如果我没有它,那么我会得到 404。“主页”视图是我的 Web 应用程序根,所以我只想在注销后将用户发送到那里。

@RequestMapping("/logout")
public ModelAndView logout() {
    // should be handled by spring security
    return new ModelAndView("home");
}

UPDATE: Here is the solution that seemed to work in the end (except the logout part, still not working):

更新:这是最终似乎有效的解决方案(除了注销部分,仍然无效):

@Configuration
@Order(1) // HIGHEST
public static class OAuthSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.antMatcher("/oauth").authorizeRequests().anyRequest().denyAll();
    }
}

@Configuration
public static class BasicAuthConfigurationAdapter extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.antMatcher("/basic").authorizeRequests().anyRequest().authenticated().and().httpBasic();
        http.logout().permitAll().logoutUrl("/logout").logoutSuccessUrl("/").invalidateHttpSession(true);
        //.and().logout().logoutUrl("/basic/logout").invalidateHttpSession(true).logoutSuccessUrl("/");
    }
}

采纳答案by Chris DaMour

i'm not sure about the logout, but we had a similar problem with having some of our site under basic and some of it not. Our solution was to use a second nested configuration class only for the paths that needed http basic. We gave this config an @Order(1)..but i'm not sure if that was necessary or not.

我不确定注销,但我们遇到了类似的问题,我们的一些网站处于基本状态,而有些则不是。我们的解决方案是仅对需要 http basic 的路径使用第二个嵌套配置类。我们给这个配置一个@Order(1)..但我不确定这是否有必要。

Updated with code

用代码更新

@Configuration
@EnableWebMvcSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig {
    private static final Logger LOG = LoggerFactory.getLogger(SecurityConfig.class);

    @Autowired
    public void registerAuthentication(AuthenticationManagerBuilder auth, Config appConfig) throws Exception {
        auth.inMemoryAuthentication()
            .withUser(appConfig.getString(APIConfig.CONFIG_KEY_MANAGEMENT_USER_NAME))
            .password(appConfig.getString(APIConfig.CONFIG_KEY_MANAGEMENT_USER_PASS))
            .roles(HyperAPIRoles.DEFAULT, HyperAPIRoles.ADMIN);        
    }



    /**
     * Following Multiple HttpSecurity approach:
     * http://docs.spring.io/spring-security/site/docs/3.2.x/reference/htmlsingle/#multiple-httpsecurity 
     */
    @Configuration
    @Order(1)
    public static class ManagerEndpointsSecurityConfig extends WebSecurityConfigurerAdapter {

        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http
            .antMatcher("/management/**").authorizeRequests().anyRequest().hasRole(HyperAPIRoles.ADMIN).and()
            .httpBasic();
        }
    }

    /**
     * Following Multiple HttpSecurity approach:
     * http://docs.spring.io/spring-security/site/docs/3.2.x/reference/htmlsingle/#multiple-httpsecurity 
     */
    @Configuration
    public static class ResourceEndpointsSecurityConfig extends WebSecurityConfigurerAdapter {        



       @Override
       protected void configure(HttpSecurity http) throws Exception {                  

            http
            //fyi: This adds it to the spring security proxy filter chain
            .addFilterBefore(createBBAuthenticationFilter(), BasicAuthenticationFilter.class)
            ;      
       }
    }
}

this seems to secure the actuator endpoints at /management with basic auth while the others work with a custom auth token header. We do not prompt for credentials (no challenge issued) though for anything..we'd have to register some other stuff to get that going (if we wanted it).

这似乎使用基本身份验证保护 /management 处的执行器端点,而其他人使用自定义身份验证令牌标头。我们不会提示输入凭据(没有发出任何挑战),但我们必须注册一些其他东西才能实现(如果我们想要的话)。

Hope this helps

希望这可以帮助

回答by user7695590

only one path will be protected

只有一条路径会受到保护

@Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter {

@Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter {

@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth)
        throws Exception
{
    auth.inMemoryAuthentication()
            .withUser("user").password(passwordEncoder().encode("user"))
            .roles("USER");
}

@Configuration
@Order(1)
public static class ManagerEndpointsSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/add/**").authenticated()
                .anyRequest().permitAll()
                .and()
                .httpBasic()
                .and().csrf().disable();
    }
}

@Bean
public PasswordEncoder passwordEncoder() {
    return new BCryptPasswordEncoder();
}

}

}