使用 javaconfig 使用 Spring Security 对身份验证进行摘要

Posted

技术标签:

【中文标题】使用 javaconfig 使用 Spring Security 对身份验证进行摘要【英文标题】:Digest auth with Spring Security using javaconfig 【发布时间】:2013-08-13 16:23:41 【问题描述】:

所以我试图在documentation 尝试翻译Java 要求中的xml“要求”之后创建一个摘要身份验证弹簧。

假设我们有文档中的 xml:

<bean id="digestFilter" class=
    "org.springframework.security.web.authentication.www.DigestAuthenticationFilter">
  <property name="userDetailsService" ref="jdbcDaoImpl"/>
  <property name="authenticationEntryPoint" ref="digestEntryPoint"/>
  <property name="userCache" ref="userCache"/>
</bean>

<bean id="digestEntryPoint" class=
    "org.springframework.security.web.authentication.www.DigestAuthenticationEntryPoint">
  <property name="realmName" value="Contacts Realm via Digest Authentication"/>
  <property name="key" value="acegi"/>
  <property name="nonceValiditySeconds" value="10"/>
</bean>

这是我当前的 javaconfig:

@Configuration
@Profile("integration", "release")
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter


  @Resource(authenticationType = Resource.AuthenticationType.CONTAINER, mappedName = "jdbc/db")
  private DataSource datasource;

  @Override
  protected void registerAuthentication (AuthenticationManagerBuilder auth) throws Exception
  
    auth.jdbcAuthentication().dataSource(datasource)
        .usersByUsernameQuery("SELECT ID_USER, PASSWORD, ACTIVE FROM USERS WHERE ID_USER = ?;")
        .authoritiesByUsernameQuery("SELECT ID_USER, ID_ROLE FROM USER_ROLES WHERE ID_USER = ?");
  

  @Bean
  public BasicAuthenticationEntryPoint entryPoint ()
  

    BasicAuthenticationEntryPoint basicAuthenticationEntryPoint = new BasicAuthenticationEntryPoint();
    basicAuthenticationEntryPoint.setRealmName("Basic WF Realm");
    return basicAuthenticationEntryPoint;
  

  @Bean
  public DigestAuthenticationEntryPoint digestEntryPoint ()
  
    DigestAuthenticationEntryPoint digestAuthenticationEntryPoint = new DigestAuthenticationEntryPoint();
    digestAuthenticationEntryPoint.setKey("mykey");
    digestAuthenticationEntryPoint.setRealmName("Digest WF Realm");
    return digestAuthenticationEntryPoint;
  

  public DigestAuthenticationFilter digestAuthenticationFilter (
      DigestAuthenticationEntryPoint digestAuthenticationEntryPoint)
  
    DigestAuthenticationFilter digestAuthenticationFilter = new DigestAuthenticationFilter();
    digestAuthenticationFilter.setAuthenticationEntryPoint(digestEntryPoint());
//    digestAuthenticationFilter.setAuthenticationDetailsSource(authenticationDetailsSource);
    return digestAuthenticationFilter;
  

  @Override
  protected void configure (HttpSecurity http) throws Exception
  
        // basic auth - it works!
        // http.exceptionHandling().authenticationEntryPoint(entryPoint()).and()
    http            
    .authorizeUrls().antMatchers("/firstres/*").permitAll()
        .antMatchers("/secondres/*").permitAll()
        .antMatchers("/resources/*").permitAll()
        .antMatchers("/**").hasAnyAuthority("first_role", "second_role").and()//.httpBasic();
    .addFilter(digestAuthenticationFilter(digestEntryPoint()));
  


我刚刚收到 403 - 拒绝访问。 使用 httpBasic 正在工作。你能告诉我我错过了什么吗?

【问题讨论】:

不要使用摘要认证。一开始它的安全性很弱,但最重要的是,它要求服务器按原样存储密码材料(如果您的服务器受到威胁,攻击者可以以任何用户的身份登录)。 【参考方案1】:

我不确定您何时收到 403 Access Denied,但如果您在通过身份验证之前请求受保护的资源时发生这种情况,那么您需要这个:

@Override
protected void configure (HttpSecurity http) throws Exception

  http
      .exceptionHandling()
          // this entry point handles when you request a protected page and
          // you are not yet authenticated
          .authenticationEntryPoint(digestEntryPoint())
          .and()
      .authorizeUrls()
          .antMatchers("/firstres/*").permitAll()
          .antMatchers("/secondres/*").permitAll()
          .antMatchers("/resources/*").permitAll()
          .antMatchers("/**").hasAnyAuthority("first_role", "second_role").and()
      // the entry point on digest filter is used for failed authentication attempts
      .addFilter(digestAuthenticationFilter(digestEntryPoint()));


@Override
@Bean
public UserDetailsService userDetailsServiceBean() 
    return super.userDetailsServiceBean();


public DigestAuthenticationFilter digestAuthenticationFilter (
    DigestAuthenticationEntryPoint digestAuthenticationEntryPoint)

  DigestAuthenticationFilter digestAuthenticationFilter = new DigestAuthenticationFilter();
  digestAuthenticationFilter.setAuthenticationEntryPoint(digestEntryPoint());
  digestAuthenticationFilter.setUserDetailsService(userDetailsServiceBean());
  return digestAuthenticationFilter;

【讨论】:

嗨,罗伯。使用您的代码,我可以弹出访问权限,但是当我这样做时,我会在 org.springframework.security.web.authentication.www.DigestAuthenticationFilter.doFilter(DigestAuthenticationFilter.java:144) 上获得 NullPointerException。它是 userDetailService.loadByUsername。如果您看到我的代码,那是注释掉的部分。我应该将什么传递给 setAuthenticationDetailsS​​ource ? 不是AuthenticationDetailsS​​ource,而是UserDetailsS​​ervice。您需要覆盖 userDetailsS​​erviceBean 方法并将其公开为 bean。然后你可以在你的配置中引用它。有关详细信息,请参阅我的更新

以上是关于使用 javaconfig 使用 Spring Security 对身份验证进行摘要的主要内容,如果未能解决你的问题,请参考以下文章

使用 JavaConfig 使用 Spring 应用程序的 HSQLDB 新手

使用JavaConfig方式-Spring 基础学习

使用 javaconfig 使用 Spring Security 对身份验证进行摘要

Spring的Xml和JavaConfig 扩展你选哪一个?

Spring重温--Spring JavaConfig

Spring JavaConfig实例