【问题标题】:Basic and form based authentication with Spring security Javaconfig使用 Spring security Javaconfig 进行基本和基于表单的身份验证
【发布时间】:2013-09-14 19:15:43
【问题描述】:

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

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

提前致谢。

这是我目前的配置:

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

【问题讨论】:

  • 你看到了什么结果?
  • 目前我只有表单身份验证,我找不到如何将基本身份验证添加到 /api/* 之类的 url 模式

标签: java spring spring-security


【解决方案1】:

显然,随着 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,则该配置将通过,下一个将尝试身份验证。这将一直持续到身份验证成功或失败。

【讨论】:

    【解决方案2】:

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

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

    可能有更优雅的方式来编写这个 - 我仍在努力了解这个构建器是如何在序列等方面工作的。但这行得通。

    【讨论】:

    • 这对我不起作用 - 访问 /api/ 的尝试被重定向到登录表单而不是基本身份验证。
    • @JamesBaker - OP 从来没有提到他需要被提示进行基本身份验证......但是基本身份验证,上面的,确实有效。如果您使用 HTTP 客户端并在您的请求中发送基本身份验证凭据,它确实有效。
    【解决方案3】:

    您可以通过在第一个配置中的 http 之后添加 .antMatcher("/api/**") 来解决此问题,以仅管理 /api 网址。您必须在第一个适配器上安装它:

    http
        .antMatcher("/api/*")
        .authorizeRequests()
            .antMatchers("^/api/.+$").hasRole("ADMIN")
        ....
    

    【讨论】:

      【解决方案4】:

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

      我的解决方法如下:

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

      【讨论】:

        【解决方案5】:

        我会说只是这样做。使用 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");
        }
        

        类似的东西应该可以。

        链接:HttpSecurityHttpBasicConfgurer

        【讨论】:

        • 没用,api 声称两次调用 authorizeUrls() 会覆盖之前的调用,因此可能无法这样做
        猜你喜欢
        • 2016-11-08
        • 2015-02-06
        • 2010-11-20
        • 2013-01-01
        • 2015-03-27
        • 2015-08-12
        • 2015-01-03
        • 2011-02-11
        • 2016-03-20
        相关资源
        最近更新 更多