除了基于令牌的身份验证之外,还允许使用http basic auth的Rest api端点

时间:2014-11-14 00:37:56

标签: java spring-security spring-boot jhipster

我最近创建了一个带有以下.yo-rc.json

的jhipster应用程序
{
    "generator-jhipster": {
    "baseName": "cmpayments",
    "packageName": "au.com.cmx.myapp",
    "packageFolder": "au/com/cmx/myapp",
    "authenticationType": "token",
    "hibernateCache": "no",
    "clusteredHttpSession": "no",
    "websocket": "no",
    "databaseType": "sql",
    "devDatabaseType": "postgresql",
    "prodDatabaseType": "postgresql",
    "useCompass": false,
    "buildTool": "maven",
    "frontendBuilder": "gulp",
    "javaVersion": "8"
  }
}

我喜欢在webapp上进行基于令牌的身份验证,但我希望服务器只使用http基本身份验证来公开REST api调用。我已经和我争吵了一段时间,但我对Spring安全完全不熟悉,我希望有人已经这样做了,可以帮助我。

我尝试按照此处的解决方案: Basic and form based authentication with Spring security Javaconfig

我在SecurityConfiguration.java中使用@Order(1)创建了第二个配置,如此

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


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

    protected void configure(HttpSecurity http) throws Exception {
        http
            .csrf()
            .disable()
            .authorizeRequests()
            .antMatchers("/basicAuthApi/**").hasRole("API")
            .and()
            .httpBasic();
    }
}

这很有效。如果我在/ basicAuthApi下使用api / pass凭证以外的其他任何一个端点,我得到401. Yay。

然而,在此之后,当我以admin / admin(或用户/用户)身份登录webapp时,我以anonymousUser身份登录。如果我在SecurityConfiguration.java中注释掉额外的@Configuration并重新启动应用程序,那么问题就会消失,我会以管理员(或用户)的身份正确登录。

有趣的是,我尝试将第二个@Configuration的顺序更改为@Order(101),因为我在其中一个基类中看到了某个@Order(100)。在这种情况下,webapp上的管理员和用户登录工作。但其余的api调用不再安全,即使密码错误也能成功。

有谁知道我做错了什么?

由于 dalyc

3 个答案:

答案 0 :(得分:2)

替换原来的SecurityConfiguration.configure:

http
        .csrf()
        .ignoringAntMatchers("/websocket/**")
    .and()
        .addFilterAfter(new CsrfCookieGeneratorFilter(), CsrfFilter.class)
        .exceptionHandling()
        .authenticationEntryPoint(authenticationEntryPoint)
    .and()
        .rememberMe()
        .rememberMeServices(rememberMeServices)
        .rememberMeParameter("remember-me")
        .key(env.getProperty("jhipster.security.rememberme.key"))
    .and()
        .formLogin()
        .loginProcessingUrl("/api/authentication")
        .successHandler(ajaxAuthenticationSuccessHandler)
        .failureHandler(ajaxAuthenticationFailureHandler)
        .usernameParameter("j_username")
        .passwordParameter("j_password")
        .permitAll()
    .and()
        .logout()
        .logoutUrl("/api/logout")
        .logoutSuccessHandler(ajaxLogoutSuccessHandler)
        .deleteCookies("JSESSIONID")
        .permitAll()
    .and()
        .headers()
        .frameOptions()
        .disable()
    .and()
        .authorizeRequests()
        .antMatchers("/api/register").permitAll()
        .antMatchers("/api/activate").permitAll()
        .antMatchers("/api/authenticate").permitAll()
        .antMatchers("/api/account/reset_password/init").permitAll()
        .antMatchers("/api/account/reset_password/finish").permitAll()
        .antMatchers("/api/logs/**").hasAuthority(AuthoritiesConstants.ADMIN)
        .antMatchers("/api/**").authenticated()
        .antMatchers("/metrics/**").hasAuthority(AuthoritiesConstants.ADMIN)
        .antMatchers("/health/**").hasAuthority(AuthoritiesConstants.ADMIN)
        .antMatchers("/trace/**").hasAuthority(AuthoritiesConstants.ADMIN)
        .antMatchers("/dump/**").hasAuthority(AuthoritiesConstants.ADMIN)
        .antMatchers("/shutdown/**").hasAuthority(AuthoritiesConstants.ADMIN)
        .antMatchers("/beans/**").hasAuthority(AuthoritiesConstants.ADMIN)
        .antMatchers("/configprops/**").hasAuthority(AuthoritiesConstants.ADMIN)
        .antMatchers("/info/**").hasAuthority(AuthoritiesConstants.ADMIN)
        .antMatchers("/autoconfig/**").hasAuthority(AuthoritiesConstants.ADMIN)
        .antMatchers("/env/**").hasAuthority(AuthoritiesConstants.ADMIN)
        .antMatchers("/trace/**").hasAuthority(AuthoritiesConstants.ADMIN)
        .antMatchers("/api-docs/**").hasAuthority(AuthoritiesConstants.ADMIN)
        .antMatchers("/protected/**").authenticated();

这一个:

http
        .csrf()
        .ignoringAntMatchers("/websocket/**")
    .and()
        .csrf()
        .ignoringAntMatchers("/basicAuthApi/**")
    .and()
        .addFilterAfter(new CsrfCookieGeneratorFilter(), CsrfFilter.class)
        .exceptionHandling()
        .authenticationEntryPoint(authenticationEntryPoint)
    .and()
        .rememberMe()
        .rememberMeServices(rememberMeServices)
        .rememberMeParameter("remember-me")
        .key(env.getProperty("jhipster.security.rememberme.key"))
    .and()
        .formLogin()
        .loginProcessingUrl("/api/authentication")
        .successHandler(ajaxAuthenticationSuccessHandler)
        .failureHandler(ajaxAuthenticationFailureHandler)
        .usernameParameter("j_username")
        .passwordParameter("j_password")
        .permitAll()
    .and()
        .logout()
        .logoutUrl("/api/logout")
        .logoutSuccessHandler(ajaxLogoutSuccessHandler)
        .deleteCookies("JSESSIONID")
        .permitAll()
    .and()
        .headers()
        .frameOptions()
        .disable()
    .and()
        .authorizeRequests()
        .antMatchers("/api/register").permitAll()
        .antMatchers("/api/activate").permitAll()
        .antMatchers("/api/authenticate").permitAll()
        .antMatchers("/api/account/reset_password/init").permitAll()
        .antMatchers("/api/account/reset_password/finish").permitAll()
        .antMatchers("/api/logs/**").hasAuthority(AuthoritiesConstants.ADMIN)
        .antMatchers("/api/**").authenticated()
        .antMatchers("/metrics/**").hasAuthority(AuthoritiesConstants.ADMIN)
        .antMatchers("/health/**").hasAuthority(AuthoritiesConstants.ADMIN)
        .antMatchers("/trace/**").hasAuthority(AuthoritiesConstants.ADMIN)
        .antMatchers("/dump/**").hasAuthority(AuthoritiesConstants.ADMIN)
        .antMatchers("/shutdown/**").hasAuthority(AuthoritiesConstants.ADMIN)
        .antMatchers("/beans/**").hasAuthority(AuthoritiesConstants.ADMIN)
        .antMatchers("/configprops/**").hasAuthority(AuthoritiesConstants.ADMIN)
        .antMatchers("/info/**").hasAuthority(AuthoritiesConstants.ADMIN)
        .antMatchers("/autoconfig/**").hasAuthority(AuthoritiesConstants.ADMIN)
        .antMatchers("/env/**").hasAuthority(AuthoritiesConstants.ADMIN)
        .antMatchers("/trace/**").hasAuthority(AuthoritiesConstants.ADMIN)
        .antMatchers("/api-docs/**").hasAuthority(AuthoritiesConstants.ADMIN)
        .antMatchers("/protected/**").authenticated()
    .and()
        .authorizeRequests()
        .antMatchers("/basicAuthApi/**")
        .hasAuthority(AuthoritiesConstants.USER).and().httpBasic();

我只是补充道:

.and()
        .csrf()
        .ignoringAntMatchers("/basicAuthApi/**")

和:

.and()
        .authorizeRequests()
        .antMatchers("/basicAuthApi/**")
        .hasAuthority(AuthoritiesConstants.USER).and().httpBasic()

您还可以创建一个只能访问这些Web服务的新权限。

答案 1 :(得分:0)

我找到了一个适合我的解决方案。我意识到我不需要另一个@Configuration,因为默认的jhipster配置没有重定向到登录页面以进行未经身份验证的访问 - 它返回一个401,这也是我想要的REST api。 所以我只是注册了一个用户,其中包含我想用于REST API的用户名和密码,并将以下行添加到

中的configure方法的底部

OAuth2ServerConfiguration.ResourceServerConfiguration

            `.antMatchers("/basicAuthApi/**").hasAuthority(AuthoritiesConstants.USER).and().httpBasic();`

我现在将尝试通过创建API角色并将该角色提供给需要调用REST API的用户来改进这一点

如果有人知道,我仍然想知道为什么我最初的尝试会遇到这些问题。

干杯 dalyc

答案 2 :(得分:0)

关于订单的介绍:如果您没有指定一个默认订单,则是可能的最大数字,它映射到可能的最低优先级(因为较低的顺序转换为较高的优先级)。因此,当您添加order = 1的配置时,您有两个配置,其中order = 1的新配置具有更高的优先级并首先进行检查。

在描述两种配置存在的场景中,会发生以下情况: 您尝试以admin / admin(或用户/用户)身份登录webapp,但spring security首先检查order = 1的配置,该配置包含ant匹配器" .antMatchers("/basicAuthApi/**").hasRole("API")"。它显然不匹配,因为您指向的网址是网站的网址,但是安全性不会因为您缺少.anyRequest().authenticated()而失败,以便对于未能成功的用户进行安全检查认证。如果没有这个,您实际上会通过安全检查,尽管您未经过身份验证,即您被视为具有匿名用户访问权限的匿名用户。由于该配置的Spring安全性成功,因此它甚至不会检查与该网站相关的另一个。