Spring security Ldap 从编码的 cookie 中获取用户名密码以进行身份​​验证

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

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

下面是我的网络安全配置类

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

}

提前致谢

最佳答案

最后我通过在 BasicAuthenticationFilter 之前有一个过滤器解决了这个问题。下面是我修改后的 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);
    }

}

关于Spring security Ldap 从编码的 cookie 中获取用户名密码以进行身份​​验证,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44017685/

相关文章:

java - 无法通过 LDAP 更新 Active Directory 中的员工 ID

java - 编辑 LDAP 照片属性,spring-ldap InvalidAttributeValueException

java - Spring 5 LDAP 身份验证和 JWT token 作为响应

spring - 如何替换默认的 SortArgumentResolver

java - 在 jar 文件 Java Spring 中加载资源

java - Maven:尝试使用依赖项将一个项目包含在另一个项目中时找不到 Artifact

java - 从简单的 JSP spring MVC 页面获取值(value)

java - 尽管有正确的凭据,Spring Security 仍给出 403

spring-mvc - 如何在 Spring 启动时使用keycloak获取userinfo?

Spring 启动+ thymeleaf : get logged in user