8

我正在尝试为不同的 url 模式定义两种不同的安全配置,其中一种使用表单登录,另一种使用 api 的基本身份验证。

我正在寻找的解决方案类似于此处解释的解决方案http://meera-subbarao.blogspot.co.uk/2010/11/spring-security-combining-basic-and.html但我想这样做使用 java 配置。

提前致谢。

这是我目前的配置:

@Configuration
@EnableWebSecurity
public class AppSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private UserService userService;

    @Override
    protected void registerAuthentication(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userService);
    }

    @Override
    public void configure(WebSecurity web) throws Exception {
        // Ignore any request that starts with "/resources/".
        web.ignoring().antMatchers("/resources/**");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeUrls().antMatchers("/", "/index", "/user/**", "/about").permitAll()
        .antMatchers("/admin/**").hasRole("ADMIN")
        .anyRequest().authenticated()
        .and().formLogin()
        .loginUrl("/login")
        .failureUrl("/login-error")
        .loginProcessingUrl("/security_check")
        .usernameParameter("j_username").passwordParameter("j_password")
        .permitAll();

        http.logout().logoutUrl("/logout");
        http.rememberMe().rememberMeServices(rememberMeServices()).key("password");
    }

    @Bean
    public RememberMeServices rememberMeServices() {
        TokenBasedRememberMeServices rememberMeServices = new TokenBasedRememberMeServices("password", userService);
        rememberMeServices.setCookieName("cookieName");
        rememberMeServices.setParameter("rememberMe");
        return rememberMeServices;
    }
}
4

5 回答 5

12

我找到的解决方案是在第一个类中创建另一个扩展 WebSecurityConfigurerAdapter 的类,如https://github.com/spring-projects/spring-security-javaconfig/blob/master/samples-web.md#sample-multi所述-http-web-配置

我的解决方案如下:

@Configuration
@EnableWebSecurity
public class AppSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private UserService userService;

    @Override
    protected void registerAuthentication(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userService);
    }

    @Override
    public void configure(WebSecurity web) throws Exception {
        // Ignore any request that starts with "/resources/".
        web.ignoring().antMatchers("/resources/**");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeUrls().antMatchers("/", "/index", "/user/**", "/about").permitAll()
            .antMatchers("/admin/**").hasRole("ADMIN")
            .anyRequest().authenticated()
            .and().formLogin()
            .loginUrl("/login")
            .failureUrl("/login-error")
            .loginProcessingUrl("/security_check")
            .usernameParameter("j_username").passwordParameter("j_password")
            .permitAll();

        http.logout().logoutUrl("/logout");
        http.rememberMe().rememberMeServices(rememberMeServices()).key("password");
    }

    @Bean
    public RememberMeServices rememberMeServices() {
        TokenBasedRememberMeServices rememberMeServices = new TokenBasedRememberMeServices("password", userService);
        rememberMeServices.setCookieName("cookieName");
        rememberMeServices.setParameter("rememberMe");
        return rememberMeServices;
    }

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

        @Override
        protected void registerAuthentication(AuthenticationManagerBuilder auth) throws Exception {
            auth.inMemoryAuthentication().withUser("api").password("pass").roles("API");
        }

        protected void configure(HttpSecurity http) throws Exception {
            http.authorizeUrls()
                .antMatchers("/api/**").hasRole("API")
                .and()
                .httpBasic();
        }
    }
}
于 2013-09-11T22:31:17.023 回答
2

我会说只是这样做。使用 authorizeUrls() 指定第二行,但用于基本身份验证所需的 URL。而不是formLogin()使用httpBasic()

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.authorizeUrls().antMatchers("/", "/index", "/user/**", "/about").permitAll()
    .antMatchers("/admin/**").hasRole("ADMIN")
    .anyRequest().authenticated()
    .and().formLogin()
    .loginUrl("/login")
    .failureUrl("/login-error")
    .loginProcessingUrl("/security_check")
    .usernameParameter("j_username").passwordParameter("j_password")
    .permitAll();

    http.authorizeUrls().antMatchers("/api/*").hasRole("YOUR_ROLE_HERE").and().httpBasic();

    http.logout().logoutUrl("/logout");
    http.rememberMe().rememberMeServices(rememberMeServices()).key("password");
}

像这样的东西应该工作。

链接:HttpSecurity, HttpBasicConfgurer.

于 2013-09-11T07:20:37.340 回答
0

您可以通过在第一个配置中添加.antMatcher("/api/**")仅管理url 来解决它。您必须在第一个适配器上安装它:http/api

http
    .antMatcher("/api/*")
    .authorizeRequests()
        .antMatchers("^/api/.+$").hasRole("ADMIN")
    ....
于 2015-03-24T09:29:52.997 回答
0

显然,随着 Spring 的更新,它们的适用性往往会逐渐减弱。运行 spring cloud starter security 1.4.0.RELEASE 这是我的解决方案。我的用例有点不同,因为我试图使用云配置的基本身份验证来保护刷新端点,并使用带有 spring 会话的网关在所有其他实例中传递身份验证。

@EnableWebSecurity
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    public void configureGlobal1(AuthenticationManagerBuilder auth) throws Exception {
        //try in memory auth with no users to support the case that this will allow for users that are logged in to go anywhere
        auth.inMemoryAuthentication();
    }

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

    @Bean
    public BCryptPasswordEncoder encoder() {
        return new BCryptPasswordEncoder(11);
    }

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

        @Autowired
        private AuthenticationProvider customAuthenticationProvider;

        @Autowired
        protected void configureGlobal2(AuthenticationManagerBuilder auth) throws Exception {
            auth
                    .authenticationProvider(customAuthenticationProvider);
        }

        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http
                .httpBasic()
                    .and()
                .authorizeRequests()
                    .antMatchers(HttpMethod.POST, "/refresh").hasRole("SUPER")
                    .and()
                .csrf().disable();
        }
    }
}

有关进一步说明,请参阅 spring 安全文档:Spring Security

基本思想是 @Order 注释将指示身份验证方案的运行顺序。没有@Order 意味着它是最后一个。如果 authorizeRequests() 部分无法匹配传入的 URL,则该配置将通过,下一个将尝试身份验证。这将一直持续到身份验证成功或失败。

于 2016-08-23T06:02:19.883 回答
-1

authorizeUrls这里的其他答案相对较旧,例如,我在 Spring 4 中找不到。

在 SpringBoot 1.4.0 / Spring 4 中,我实现了基本/表单登录,如下所示:

@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter
{
   protected void configure (HttpSecurity aHttp) throws Exception
   {    
      aHttp.authorizeRequests ().antMatchers (("/api/**")).fullyAuthenticated ().and ().httpBasic ();

      aHttp.formLogin ()
         .loginPage ("/login").permitAll ()
         .and ().logout ().permitAll ();
   }
}

可能有更优雅的方式来写这个——我仍在努力理解这个构建器是如何在序列等方面工作的。但这有效。

于 2016-08-13T14:03:14.503 回答