如何使用java配置在spring中配置waffle

我一直在努力使用spring java配置来解决使用spring 4.2.5的问题。 我想我也可以在同样的情况下帮助别人。

我们使用自定义preWaffle和postWafflefilter来validation用户在通过华夫饼NTLM协议validation后存在于我们的数据库中。

我们还有使用EnableGlobalMethodSecurity批注授权用户操作的方法。

为了让它在Spring中工作,java配置至少可以说有些麻烦。 您可以在下面的答案中找到我们的解决方案。 我希望它会有所帮助。

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 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 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(); } } 

为了能够自动assembly华夫cookiesauthProvider,我创建了以下包装类。

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

编辑

对于那些在这里询问的人是一个实现。 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 names = Collections.list(super.getHeaderNames()); names.addAll(Collections.list(super.getParameterNames())); names.remove("Authorization"); return Collections.enumeration(names); } } 

如果您需要更多信息,请不要犹豫。