【问题标题】:ActiveDirectoryLdapAuthenticationProvider: Getting UserDetailsActiveDirectoryLdapAuthenticationProvider:获取用户详细信息
【发布时间】:2014-11-21 14:30:38
【问题描述】:

为了让 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 配置和使用的类。

安全配置

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

【问题讨论】:

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


    【解决方案1】:

    Spring LDAP 有一个叫做LdapUserDetailsService 的东西,我会冒昧地说这可能是你必须要做的。通常,Spring 带有合理的默认值,我们只是连接正确的东西。

    【讨论】:

    • 所以 UserDetailsS​​ervice 并没有被原始地自动装配。这是我为了解决我的问题而添加的。我也尝试过使用 LdapUserDetailsS​​ervice 但我不确定如何正确获取它的实例。当前的 UserDetailsS​​ervice 对象是在创建安全配置时定义的,并使用 @EnableWebMvcSecurity 标记证明的方法。
    猜你喜欢
    • 2014-03-30
    • 1970-01-01
    • 1970-01-01
    • 2021-06-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多