【问题标题】:Spring Security 3 Active Directory Authentication, Database AuthorizationSpring Security 3 Active Directory 身份验证、数据库授权
【发布时间】:2012-03-02 23:46:01
【问题描述】:

我正在尝试使用 AD 身份验证访问我的应用程序并从我的数据库中获取授权角色。

这是我的配置

<beans:bean id="activeDirectoryAuthenticationProvider"
        class="org.springframework.security.ldap.authentication.ad.ActiveDirectoryLdapAuthenticationProvider">
    <beans:constructor-arg value="mydomain" />
    <beans:constructor-arg value="ldap://my URL :389" />
    <beans:property name="convertSubErrorCodesToExceptions" value="true"/>
</beans:bean>

我尝试添加

  <beans:constructor-arg>
    <beans:bean class="org.springframework.security.ldap.populator.UserDetailsServiceLdapAuthoritiesPopulator">
      <beans:constructor-arg ref="myUserDetailsService"/>
    </beans:bean>
  </beans:constructor-arg>

但它没有用。有什么帮助吗?

非常感谢!!

【问题讨论】:

    标签: spring authentication active-directory spring-security


    【解决方案1】:

    ActiveDirectoryLdapAuthenticationProvider 不使用LdapAuthoritiesPopulator(检查构造函数的 API)。

    您可以使用委托模型,在其中包装提供者并分别加载权限,然后返回包含它们的新令牌:

    public class MyAuthoritySupplementingProvider implements AuthenticationProvider {
        private AuthenticationProvider delegate;
    
        public MyAuthoritySupplementingProvider(AuthenticationProvider delegate) {
            this.delegate = delegate;
        }
    
        public Authentication authenticate(Authentication authentication) {
            final Authentication a = delegate.authenticate(authentication);
    
            // Load additional authorities and create an Authentication object
            final List<GrantedAuthority> authorities = loadRolesFromDatabaseHere(a.getName());
    
            return new AbstractAuthenticationToken(authorities) {
                public Object getCredentials() {
                    throw new UnsupportedOperationException();
                }
    
                public Object getPrincipal() {
                    return a.getPrincipal();
                }
            };
        }
    
        @Override
        public boolean supports(Class<?> authentication) {
            return delegate.supports(authentication);
        }
    }
    

    这门课是期末课,主要是因为我对 Active Directory 的基本了解以及人们想要使用它的不同方式。

    【讨论】:

    • 非常感谢。我该怎么做?我对这种技术很陌生,我找不到任何使用 ActiveDirectoryLdapAuthenticationProvider 和自定义 loadUserAuthorities 的示例
    • 只需扩展类,调用您的数据库以获取角色并根据方法签名将它们作为List&lt;GrantedAuthority&gt; 返回。您可以使用SimpleGrantedAuthority 类来包装各个角色。
    • 我试图扩展它,但我得到了错误:不能继承最终类 ActiveDirectoryLdapAuthenticationProvider
    • 糟糕,抱歉。我忘记了。您必须使用委托而不是继承。我已经修改了我的答案以建议如何完成。
    【解决方案2】:

    让我们把它分成两部分。第一个是您的 spring security xml 配置,第二部分是覆盖 spring security 提供的 UserContextMapper。

    您的安全 xml 配置将是

    <bean id="adAuthenticationProvider"
        class="org.springframework.security.ldap.authentication.ad.ActiveDirectoryLdapAuthenticationProvider">
       <constructor-arg value="my.domain.com" />
        <constructor-arg value="ldap://<adhostserver>:<port>/" />
        <property name="convertSubErrorCodesToExceptions" value="true" />
        <property name="userDetailsContextMapper" ref="myUserDetailsContextMapper" />
    </bean>
    
    <bean id="myUserDetailsContextMapper" class="com.mycompany.sme.workflow.controller.MyDbAuthorizationFetcher">
    <property name="dataSource" ref="dataSource" />
    

    MyDbAuthorizationFetcher 是您将在其中实现 UserContextMapper 类以从 DB 获取权限的类

    public class MyDbAuthorizationFetcher implements UserDetailsContextMapper {
    
    private JdbcTemplate jdbcTemplate;
    @Autowired
    private DataSource dataSource;
    
    public JdbcTemplate getJdbcTemplate() {
        return jdbcTemplate;
    }
    
    public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }
    
    public DataSource getDataSource() {
        return dataSource;
    }
    
    public void setDataSource(DataSource dataSource) {
        this.dataSource = dataSource;
    }
    
    // populating roles assigned to the user from AUTHORITIES table in DB
    private List<SimpleGrantedAuthority> loadRolesFromDatabase(String username) {
    
        DbRole role = new DbRole();
        String sql = "select * from user where user_id = ?";
        jdbcTemplate = new JdbcTemplate(getDataSource());
        role = jdbcTemplate.queryForObject(sql, new Object[] { username }, new DbRoleMapper());
    
    
        try {
            dataSource.getConnection().setAutoCommit(true);
        } catch (SQLException e) {
    
        }
        List<SimpleGrantedAuthority> authoritiess = new ArrayList<SimpleGrantedAuthority>();
        SimpleGrantedAuthority auth = new SimpleGrantedAuthority(String.valueOf(role.getRoleId()));
        authoritiess.add(auth);
        return authoritiess;
    
       }
    
    @Override
    public UserDetails mapUserFromContext(DirContextOperations ctx,
            String username, Collection<? extends GrantedAuthority> authorities) {
    
        List<SimpleGrantedAuthority> allAuthorities = new ArrayList<SimpleGrantedAuthority>();
          for (GrantedAuthority auth : authorities) {
            if (auth != null && !auth.getAuthority().isEmpty()) {
               allAuthorities.add((SimpleGrantedAuthority) auth);
            }
          }
          // add additional roles from the database table
          allAuthorities.addAll(loadRolesFromDatabase(username));
          return new User(username, "", true, true, true, true, allAuthorities);
    }
    
    @Override
    public void mapUserToContext(UserDetails user, DirContextAdapter ctx) {
        // TODO Auto-generated method stub
    }
    
    }
    

    【讨论】:

    • 我认为这是更简洁的解决方案,如果您需要,它还可以让您访问用户的 AD 属性。
    【解决方案3】:

    需要在AbstractAuthenticationToken中将authenticated flag设置为true,除非它不认为是成功

    【讨论】:

      猜你喜欢
      • 2013-09-21
      • 1970-01-01
      • 2021-02-24
      • 2020-04-08
      • 2015-04-17
      • 2019-10-04
      • 2011-01-12
      • 2014-05-11
      • 2010-11-22
      相关资源
      最近更新 更多