2016-04-28 39 views
8

私は春4.2.5で動作するようにワッフルを取得するのに苦労しています。そして私は同じ状況で他人を助けるかもしれないと思った。Javaの設定を使用して春にワッフルを設定する方法

私たちはワッフルNTLMプロトコルで検証された後、ユーザーがデータベースに存在することを認証するカスタムpreWaffleおよびpostWaffleフィルターを使用します。

また、EnableGlobalMethodSecurityアノテーションを使用してユーザーアクションを承認する方法もあります。

春のJavaの設定でこれを動作させるには、問題を最小限に抑えることがいくつかありました。以下の答えで私たちの解決策を見つけることができます。私はそれが助けてくれることを願う

答えて

8

SpringConfiguration.java

// ... imports 
@Configuration 
@EnableWebMvc 
@EnableScheduling 
@PropertySources({ 
    @PropertySource("classpath:app.properties") 
    // ... Properties sources 
}) 
@EnableTransactionManagement 
@ComponentScan(basePackages = "com.our.package") 
public class SpringConfiguration extends WebMvcConfigurerAdapter { 

// Our Spring configuration ... 

} 

SecurityConfiguration.java

// ... imports 
@Configuration 
@EnableWebSecurity 
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true, proxyTargetClass = true) 
@Order(1) 
public class SecurityConfiguration extends WebSecurityConfigurerAdapter{ 

    // Authentication manager configuration 
    @Autowired 
    private WindowsAuthenticationProviderWrapper authProvider; 

    @Autowired 
    private AuthenticationManagerBuilder auth; 

    @Override 
    protected void configure(final AuthenticationManagerBuilder auth) throws Exception { 
    auth.authenticationProvider(authProvider); 
    } 

    @Bean 
    public AuthenticationManager authenticationManager() throws Exception { 
    return auth.getObject(); 
    } 

    // Waffle configuration 
    @Bean 
    public Filter customPreAuthSecurityFilter() { 
    return new CustomPreAuthSecurityFilter(); 
    } 

    @Bean 
    public Filter customNegotiateSecurityFilter() { 
    return new CustomNegotiateSecurityFilter(); 
    } 

    @Bean 
    public WindowsAuthProviderImpl waffleAuthProvider(){ 
    return new WindowsAuthProviderImpl(); 
    } 

    @Bean(name="negotiateSecurityFilterProvider") 
    @Autowired 
    public NegotiateSecurityFilterProvider negotiateSecurityFilterProvider(){ 
    NegotiateSecurityFilterProvider bean = new NegotiateSecurityFilterProvider(waffleAuthProvider()); 
    List<String> protocols = new ArrayList<>(); 
    protocols.add("Negotiate"); 
    bean.setProtocols(protocols); 
    return bean; 
    } 

    @Bean 
    public BasicSecurityFilterProvider basicSecurityFilterProvider(){ 
    return new BasicSecurityFilterProvider(waffleAuthProvider()); 
    } 

    @Bean(name="waffleSecurityFilterProviderCollection") 
    @Autowired 
    public waffle.servlet.spi.SecurityFilterProviderCollection negotiateSecurityFilterProviderCollection() { 
    final List<SecurityFilterProvider> lsp = new ArrayList<>(); 
    lsp.add(negotiateSecurityFilterProvider()); 
    lsp.add(basicSecurityFilterProvider()); 
    return new waffle.servlet.spi.SecurityFilterProviderCollection(lsp.toArray(new SecurityFilterProvider[]{})); 
    } 

    @Bean(name="negotiateSecurityFilterEntryPoint") 
    @Autowired 
    public waffle.spring.NegotiateSecurityFilterEntryPoint negotiateSecurityFilterEntryPoint() { 
    final waffle.spring.NegotiateSecurityFilterEntryPoint ep = new waffle.spring.NegotiateSecurityFilterEntryPoint(); 
    ep.setProvider(negotiateSecurityFilterProviderCollection()); 
    return ep; 
    } 

    @Bean(name="negotiateSecurityFilter") 
    @Autowired 
    public waffle.spring.NegotiateSecurityFilter waffleNegotiateSecurityFilter(){ 
    waffle.spring.NegotiateSecurityFilter bean = new waffle.spring.NegotiateSecurityFilter(); 
    bean.setRoleFormat("both"); 
    bean.setPrincipalFormat("fqn"); 
    bean.setAllowGuestLogin(false); 
    bean.setProvider(negotiateSecurityFilterProviderCollection()); 
    return bean; 
    } 

    // Static Mappings 
    @Override 
    public void configure(WebSecurity web) throws Exception { 
    web.ignoring().antMatchers("/assets/**"); 
    } 

    // Security filter chain 
    // The custom filters can be removed if you only use waffle 
    // but this is how we added them 
    @Override 
    protected void configure(HttpSecurity http) throws Exception { 
    // A user needs to have the role user and has to be authenticated 
    http.exceptionHandling() 
     .authenticationEntryPoint(negotiateSecurityFilterEntryPoint()).and() 
     .addFilterBefore(customPreAuthSecurityFilter(), BasicAuthenticationFilter.class) 
     .addFilterAfter(waffleNegotiateSecurityFilter(), BasicAuthenticationFilter.class) 
     .addFilterAfter(customNegotiateSecurityFilter(), BasicAuthenticationFilter.class) 
     .authorizeRequests().anyRequest().fullyAuthenticated(); 
    } 
    } 

は、私は、次のwrapperclassを作成したワッフルauthProviderをautowireすることができるようにします。

WindowsAuthenticationProviderWrapper.java

// ... imports 
// This class purpose is only to make the Windows authentication provider autowireable in spring. 
@Component 
public class WindowsAuthenticationProviderWrapper extends WindowsAuthenticationProvider{} 

要求として(一部のコードは、セキュリティ上のリスクに剥奪されました)。ここについて尋ねた人のために

CustomPreAuthFilter.java

import org.springframework.security.core.context.SecurityContext; 
import org.springframework.security.core.context.SecurityContextHolder; 
import org.springframework.web.filter.GenericFilterBean; 

import javax.servlet.FilterChain; 
import javax.servlet.ServletException; 
import javax.servlet.ServletRequest; 
import javax.servlet.ServletResponse; 
import javax.servlet.http.HttpServletRequest; 
import javax.servlet.http.HttpServletResponse; 
import java.io.IOException; 

/** 
* This filter removes the excess negoatiate header sent by IE. If the client 
* has already authenticated, strip the Authorization header from the request. 
*/ 
public class CustomPreAuthSecurityFilter extends GenericFilterBean { 
    @Override 
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { 
    SecurityContext sec = SecurityContextHolder.getContext(); 
    HttpServletRequest req = (HttpServletRequest) servletRequest; 

    if(sec != null && sec.getAuthentication() != null) { 
     req = new CustomServletRequestWrapper(req); 
    } 

    try { 
     filterChain.doFilter(req, servletResponse); 
    } catch (RuntimeException e) { 
     sendUnauthorized((HttpServletResponse) servletResponse); 
    } 
    } 

    private void sendUnauthorized(HttpServletResponse response) throws IOException { 
    logger.warn("error logging in user"); 
    SecurityContextHolder.clearContext(); 
    response.sendError(HttpServletResponse.SC_UNAUTHORIZED); 
    } 
} 

CustomNegotiateSecurityFilter.java

import org.slf4j.Logger; 
import org.slf4j.LoggerFactory; 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.core.env.Environment; 
import org.springframework.security.core.Authentication; 
import org.springframework.security.core.GrantedAuthority; 
import org.springframework.security.core.authority.SimpleGrantedAuthority; 
import org.springframework.security.core.context.SecurityContext; 
import org.springframework.security.core.context.SecurityContextHolder; 
import org.springframework.web.filter.GenericFilterBean; 
import waffle.servlet.WindowsPrincipal; 
import waffle.spring.WindowsAuthenticationToken; 

import javax.servlet.FilterChain; 
import javax.servlet.ServletException; 
import javax.servlet.ServletRequest; 
import javax.servlet.ServletResponse; 
import javax.servlet.http.HttpServletRequest; 
import javax.servlet.http.HttpServletResponse; 
import java.io.IOException; 
import java.util.Date; 

/** 
* Handle post NTLM authentication against system database 
*/ 
public class CustomNegotiateSecurityFilter extends GenericFilterBean { 

    @Autowired 
    private UserDAO userDAO; 

    @Autowired 
    Environment env; 

    private static final Logger LOGGER = LoggerFactory.getLogger(CustomNegotiateSecurityFilter.class); 

    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { 
    final HttpServletRequest request = (HttpServletRequest) req; 
    final HttpServletResponse response = (HttpServletResponse) res; 
    SecurityContext sec = SecurityContextHolder.getContext(); 
    Authentication authentication = sec.getAuthentication(); 

    // Continue filter chain if we are anonymously authenticated or if DB authentication has already happened. 
    if (authentication != null && authentication.getClass() == WindowsAuthenticationToken.class) { 

     // The user is Authenticated with NTLM but needs to be checked against the DB. 
     User user; 

     try { 
     // fetch user from DB ... 
     } catch (Exception e) { 
     // The could not be found in the DB. 
     sendUnauthorized(response); 
     return; 
     } 

     // The user was found in the DB. 
     WindowsPrincipal principal = (WindowsPrincipal)authentication.getPrincipal(); 
     final CustomAuthenticationToken token = new CustomAuthenticationToken(principal); // This class extends WindowsAuthenticationToken 

     // add roles to token ... 

     sec.setAuthentication(token); 
    } 

    chain.doFilter(request, response); 
    } 

    private void sendUnauthorized(HttpServletResponse response) throws IOException { 
    logger.warn("Could not log in user"); 
    SecurityContextHolder.clearContext(); 
    response.sendError(HttpServletResponse.SC_UNAUTHORIZED); 
    } 

    private void addRoleToAuthentication(WindowsAuthenticationToken authentication, String role) { 
     for(GrantedAuthority authority : authentication.getAuthorities()) { 
     if(authority.getAuthority().equals(role)) { 
      return; 
     } 
     } 
     authentication.getAuthorities().add(new SimpleGrantedAuthority(role)); 
    } 
} 

EDIT

1つの実装です。 CustomServletRequestWrapper:あなたはより多くの情報が必要な場合

class CustomServletRequestWrapper extends HttpServletRequestWrapper { 


    public CustomServletRequestWrapper(HttpServletRequest request) { 
     super(request); 
    } 
    public String getHeader(String name) { 
     if(name.equals("Authorization")) 
      return null; 
     String header = super.getHeader(name); 
     return (header != null) ? header : super.getParameter(name); // Note: you can't use getParameterValues() here. 
    } 

    public Enumeration getHeaderNames() { 
     List<String> names = Collections.list(super.getHeaderNames()); 

     names.addAll(Collections.list(super.getParameterNames())); 
     names.remove("Authorization"); 
     return Collections.enumeration(names); 
    } 

} 

依頼するhessitateはありません。

+0

あなたのコードを実装しようとしていますが、私が取得しているIm:Factoryメソッド 'springSecurityFilterChain'が例外をスローしました。入れ子にされた例外はorg.springframework.security.config.annotation.AlreadyBuiltExceptionです:このオブジェクトは既に構築されています – naoru

+0

私はコードベースにアクセスできないため、チェックできません。私は似たような問題を覚えています。私はあなたがすでにオブジェクトを作成しているからです。それが2回作成された理由を確認してください。何らかの欠陥が見つかった場合は、ここに報告してください。 –

+0

@PabloJomer - ありがとうございました。しかし、 "waffle.spring.NegotiateSecurityFilter:正常にログインしたユーザー:domain \ username"と "waffle.spring.NegotiateSecurityFilter:ユーザーのログインエラー:com.sun.jna.platform.win32.Win32Exception:関数が無効です "というエラーメッセージが表示されます。ブラウザの更新後は正常に動作します。 – JHS

関連する問題