Spring安全性Ldap从用于身份验证的编码cookie中获取用户名密码

时间:2017-05-17 06:57:13

标签: spring spring-security spring-ldap spring-security-ldap

目前我已经编写了一个带有http基本登录的Spring Ldap身份验证和授权模块,但现在我需要从请求中的cookie中获取用户名和密码,并将它们绑定到ldap进行身份验证。

以下是我的websecurity配置类

@Configuration
@EnableWebSecurity
public class LdapSecurity extends WebSecurityConfigurerAdapter {

    @Autowired
    CustomLdapAuthoritiesPopulator customLdapAuthoritiesPopulator;

    @Value("${ldap.config.url:ldap://192.168.1.50:389}")
    private String LDAP_URL;

    @Value("${ldap.config.managerdn:uid=admin,cn=users,cn=accounts,dc=example,dc=test}")
    private String MANAGER_DN;

    @Value("${ldap.config.managerpwd:admin123}")
    private String MANAGER_PWD;

    @Value("${ldap.config.basedn:cn=users,cn=accounts,dc=example,dc=test}")
    private String SEARCH_BASE;

    @Override
    protected void configure(HttpSecurity httpSecurity) throws Exception {

        httpSecurity.httpBasic().
        and().authorizeRequests().
                anyRequest().permitAll().
                and().
                csrf().disable().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
    }

    @Override
    protected void configure(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception {
        authenticationManagerBuilder
            .ldapAuthentication().contextSource().url(LDAP_URL)
            .managerDn(MANAGER_DN)
             .managerPassword(MANAGER_PWD)
                .and()
                    .userSearchBase(SEARCH_BASE)
                    .userSearchFilter("uid={0}")
                    .ldapAuthoritiesPopulator(customLdapAuthoritiesPopulator);            
    }

}

以下是我的CustomLdapAuthoritiesPopulator类

@Component
public class CustomLdapAuthoritiesPopulator implements LdapAuthoritiesPopulator {


    public Collection<? extends GrantedAuthority> getGrantedAuthorities(DirContextOperations userData, String username) {

        String[] groups = userData.getStringAttributes("memberof");

        List<String> wordList = Arrays.asList(groups);       

        List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();

        for (String string : wordList) {

            if(string.toLowerCase().contains("cn=permissions")){
                String parts[] = string.split(",");
                String autho[]=parts[0].split("cn=");
                System.out.println(autho[1]);   
                authorities.add(new SimpleGrantedAuthority(autho[1]));
            }

        }

        return authorities;
    } 

}

提前致谢

1 个答案:

答案 0 :(得分:2)

最后,我通过在BasicAuthenticationFilter之前使用Filter来解决这个问题。以下是我修改过的LdapSecurity类。

@Configuration
@EnableWebSecurity
public class LdapSecurity extends WebSecurityConfigurerAdapter {

    @Autowired
    CustomLdapAuthoritiesPopulator customLdapAuthoritiesPopulator;

    @Autowired
    AuthFilter authFilter;


    @Value("${ldap.config.url:ldap://192.168.1.50:389}")
    private String LDAP_URL;

    @Value("${ldap.config.managerdn:uid=admin,cn=users,cn=accounts,dc=example,dc=test}")
    private String MANAGER_DN;

    @Value("${ldap.config.managerpwd:admin123}")
    private String MANAGER_PWD;

    @Value("${ldap.config.basedn:cn=users,cn=accounts,dc=example,dc=test}")
    private String SEARCH_BASE;

    @Override
    protected void configure(HttpSecurity httpSecurity) throws Exception {

        httpSecurity.addFilterBefore(authFilter,BasicAuthenticationFilter.class);

        httpSecurity.httpBasic().and().
            authorizeRequests().
                anyRequest().authenticated().
                and().
                csrf().disable().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
    }

    @Override
    protected void configure(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception {
        authenticationManagerBuilder
            .ldapAuthentication().contextSource().url(LDAP_URL)
            .managerDn(MANAGER_DN)
             .managerPassword(MANAGER_PWD)
                .and()
                    .userSearchBase(SEARCH_BASE)
                    .userSearchFilter("uid={0}")
                    .ldapAuthoritiesPopulator(customLdapAuthoritiesPopulator);            
    }

}

以下是扩展GenericFilter的自定义AuthFilter类

@Component
public class AuthFilter extends GenericFilter{

    private static final long serialVersionUID = 1L;

    @Override
    public void destroy() {

    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {

        HttpServletRequest req = (HttpServletRequest) request;
        MutableHttpServletRequest mutableRequest = new MutableHttpServletRequest(req);

        Cookie[] cookies = mutableRequest.getCookies();
        if(cookies!=null)
            for (int i = 0; i < cookies.length; i++) {
                if(cookies[i].getName().equals("nginxauth")){
                    String auth=cookies[i].getValue().replace("\"", "");
                    System.out.println(auth);
                    mutableRequest.putHeader("Authorization","Basic "+auth);                    
                }
            }

        chain.doFilter(mutableRequest, response);

    }

}

下面是MutableRequestClass

final class MutableHttpServletRequest extends HttpServletRequestWrapper {

    // holds custom header and value mapping
    private final Map<String, String> customHeaders;

    public MutableHttpServletRequest(HttpServletRequest request){
        super(request);
        this.customHeaders = new HashMap<String, String>();
    }

    public void putHeader(String name, String value){
        this.customHeaders.put(name, value);
    }

    public String getHeader(String name) {
        // check the custom headers first
        String headerValue = customHeaders.get(name);

        if (headerValue != null){
            return headerValue;
        }
        // else return from into the original wrapped object
        return ((HttpServletRequest) getRequest()).getHeader(name);
    }

    public Enumeration<String> getHeaderNames() {
        // create a set of the custom header names
        Set<String> set = new HashSet<String>(customHeaders.keySet());

        // now add the headers from the wrapped request object
        Enumeration<String> e = ((HttpServletRequest) getRequest()).getHeaderNames();
        while (e.hasMoreElements()) {
            // add the names of the request headers into the list
            String n = e.nextElement();
            set.add(n);
        }

        // create an enumeration from the set and return
        return Collections.enumeration(set);
    }

}