ActiveDirectoryLdapAuthenticationProvider:获取UserDetails

时间:2014-11-21 14:30:39

标签: java spring spring-mvc spring-security active-directory

我遵循以下教程,以使Spring和Rest能够使用完整的安全性和无状态令牌。

http://captechconsulting.com/blog/jens-alm/versioned-validated-and-secured-rest-services-spring-40-4

我现在正在尝试将身份验证机制转换为使用Active Directory(ActiveDirectoryLdapAuthenticationProvider)。我的问题是我无法弄清楚如何到达UserDetails,因此可以使用loadUserByUsername(userName)方法。

下面是导致我出现问题的方法,注释行为过滤器提供了用户详细信息服务,但我无法弄清楚如何使用Active Directory身份验证获取此信息。

 private Filter authenticationFilter() {
        HeaderAuthenticationFilter headerAuthenticationFilter = new HeaderAuthenticationFilter();

        //headerAuthenticationFilter.userDetailsService(userDetailsService());
        headerAuthenticationFilter.headerUtil(headerUtil);
        return headerAuthenticationFilter;
    }

以下是我的Spring Security配置和使用的课程。

SecurityConfig

@Configuration
@EnableWebMvcSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    private static final String ACCESS_DENIED_JSON = "{\"message\":\"You are not privileged to request this resource.\", \"access-denied\":true,\"cause\":\"AUTHORIZATION_FAILURE\"}";
    private static final String UNAUTHORIZED_JSON = "{\"message\":\"Full authentication is required to access this resource.\", \"access-denied\":true,\"cause\":\"NOT AUTHENTICATED\"}";

    @Autowired
    private HeaderUtil headerUtil;

//    @Autowired
//    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
//        auth.inMemoryAuthentication().
//
//                withUser("user").password("password").roles("USER").
//
//                and().
//
//                withUser("admin").password("password").roles("USER", "ADMIN");
//    }
//    
    @Bean
    public ActiveDirectoryLdapAuthenticationProvider activeDirectoryLdapAuthenticationProvider() {
        ActiveDirectoryLdapAuthenticationProvider provider = new ActiveDirectoryLdapAuthenticationProvider("domain.com", "ldap://ad.domain.com:389");
        provider.setConvertSubErrorCodesToExceptions(true);
        provider.setUseAuthenticationRequestCredentials(true);

        //provider.setAuthoritiesMapper( new NullAuthoritiesMapper()); // see http://comdynamics.net/blog/544/spring-security-3-integration-with-active-directory-ldap/


        return provider;
    }


    @Autowired
    protected void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth.authenticationProvider(activeDirectoryLdapAuthenticationProvider());
    }


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

        CustomAuthenticationSuccessHandler successHandler = new CustomAuthenticationSuccessHandler();
        successHandler.headerUtil(headerUtil);

        http.
                addFilterBefore(corsFilter(), LogoutFilter.class).
                addFilterBefore(authenticationFilter(), LogoutFilter.class).

                csrf().disable().

                formLogin().successHandler(successHandler).
                loginProcessingUrl("/login").

                and().

                logout().
                logoutSuccessUrl("/logout").

                and().

                sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).

                and().

                exceptionHandling().
                accessDeniedHandler(new CustomAccessDeniedHandler()).
                authenticationEntryPoint(new CustomAuthenticationEntryPoint()).

                and().

                authorizeRequests().
                antMatchers(HttpMethod.POST, "/login").permitAll().
                antMatchers(HttpMethod.POST, "/logout").authenticated().
//                antMatchers(HttpMethod.GET, "/**").hasRole("USER").
//                antMatchers(HttpMethod.POST, "/**").hasRole("ADMIN").
//                antMatchers(HttpMethod.DELETE, "/**").hasRole("ADMIN").
                antMatchers(HttpMethod.GET, "/**").authenticated().
                antMatchers(HttpMethod.POST, "/**").authenticated().
                antMatchers(HttpMethod.DELETE, "/**").authenticated().
                anyRequest().authenticated();

    }

    private Filter authenticationFilter() {
        HeaderAuthenticationFilter headerAuthenticationFilter = new HeaderAuthenticationFilter();

        //headerAuthenticationFilter.userDetailsService(userDetailsService());
        headerAuthenticationFilter.headerUtil(headerUtil);
        return headerAuthenticationFilter;
    }


    private Filter corsFilter() {
        return new SimpleCORSFilter();
    }

    private static class CustomAccessDeniedHandler implements AccessDeniedHandler {
        @Override
        public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException {

            response.setContentType(Versions.V1_0);
            response.setStatus(HttpServletResponse.SC_FORBIDDEN);
            PrintWriter out = response.getWriter();
            out.print(ACCESS_DENIED_JSON);
            out.flush();
            out.close();

        }
    }

    private static class CustomAuthenticationEntryPoint implements AuthenticationEntryPoint {
        @Override
        public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {

            response.setContentType(Versions.V1_0);
            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
            PrintWriter out = response.getWriter();
            out.print(UNAUTHORIZED_JSON);
            out.flush();
            out.close();
        }
    }

    private static class CustomAuthenticationSuccessHandler extends SimpleUrlAuthenticationSuccessHandler {

        private HeaderUtil headerUtil;

        @Override
        public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
                                            Authentication authentication) throws ServletException, IOException {
            try {
                String token = headerUtil.createAuthToken(((LdapUserDetailsImpl) authentication.getPrincipal()).getUsername());
                ObjectMapper mapper = new ObjectMapper();
                ObjectNode node = mapper.createObjectNode().put("x-auth-token", token);
                PrintWriter out = response.getWriter();
                out.print(node.toString());
                out.flush();
                out.close();
            } catch (GeneralSecurityException e) {
                throw new ServletException("Unable to create the auth token", e);
            }
            clearAuthenticationAttributes(request);

        }

        private void headerUtil(HeaderUtil headerUtil) {
            this.headerUtil = headerUtil;
        }
    }

}

HeaderAuthenticationFilter

public class HeaderAuthenticationFilter extends GenericFilterBean {


    private UserDetailsService userDetailsService;

    private HeaderUtil headerUtil;

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

        UserDetails userDetails = loadUserDetails((HttpServletRequest) request);
        SecurityContext contextBeforeChainExecution = createSecurityContext(userDetails);

        try {
            SecurityContextHolder.setContext(contextBeforeChainExecution);
            if (contextBeforeChainExecution.getAuthentication() != null && contextBeforeChainExecution.getAuthentication().isAuthenticated()) {
                String userName = (String) contextBeforeChainExecution.getAuthentication().getPrincipal();
                headerUtil.addHeader((HttpServletResponse) response, userName);
            }
            filterChain.doFilter(request, response);
        }
        finally {
            // Clear the context and free the thread local
            SecurityContextHolder.clearContext();
        }
    }

    private SecurityContext createSecurityContext(UserDetails userDetails) {
        if (userDetails != null) {
            SecurityContextImpl securityContext = new SecurityContextImpl();
            Authentication authentication = new UsernamePasswordAuthenticationToken(userDetails.getUsername(), userDetails.getPassword(), userDetails.getAuthorities());
            securityContext.setAuthentication(authentication);
            return securityContext;
        }
        return SecurityContextHolder.createEmptyContext();
    }

    private UserDetails loadUserDetails(HttpServletRequest request) {
        String userName = headerUtil.getUserName(request);

        return userName != null
                ? userDetailsService.loadUserByUsername(userName)
                : null;
    }

    public void userDetailsService(UserDetailsService userDetailsService2) {
        this.userDetailsService = userDetailsService2;
    }

    public void headerUtil(HeaderUtil headerUtil) {
        this.headerUtil = headerUtil;
    }
}

1 个答案:

答案 0 :(得分:0)

Spring LDAP有一个名为LdapUserDetailsService的东西,我将会说明这可能是你必须要做的事情。通常,Spring带有合理的默认值,我们只需连接正确的东西。