开始在新的Spring Boot 1.5.9应用程序上工作,该应用程序接收到一个肥皂请求,该请求需要针对LDAP,令牌验证和一些时间戳限制进行身份验证。每当我尝试将@PreAuthorize添加到我的端点时,都会出现“在SecurityContext中找不到身份验证对象”错误。
当前通过通过SoapUI发送消息并运行本地服务器进行测试。
我已将日志级别设置为TRACE,但仍然没有日志记录。
当我从端点中删除@PreAuthorize批注时,我确实在SoapUI中收到了正确的响应,但是那当然是不进行身份验证的。
@Endpoint
public class WidgetEndpoint {
private static final Logger LOGGER = LoggerFactory.getLogger(WidgetEndpoint.class);
public static final String NAMESPACE_URI = "http://www.widget.com/ws/widget";
public static final String NAMESPACE_URI_GD = "urn:Connect.WidgetApp/WSDL";
@PayloadRoot(namespace = NAMESPACE_URI_GD, localPart = "widgetGDRq")
@ResponsePayload
@PreAuthorize("hasRole('ROLE_ACCESS')")
public WidgetGDRs widgetGD(@RequestPayload WidgetGDRq request) {
LOGGER.info("Request Received: " + request.getData());
ObjectFactory factory = new ObjectFactory();
WidgetFormsGDRs response = factory.createWidgetGDRs();
response.setData("Congrates! You got Data: " + request.getData());
return response;
}
}
@EnableWs
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true, proxyTargetClass = true)
public class WebServiceConfig extends WsConfigurerAdapter {
@Value("${ldap.ur}")
@Value("${ldap.userName}")
@Value("${ldap.password}")
@Value("${ldap.baseDN}")
@Bean
public ServletRegistrationBean messageDispatcherServlet(ApplicationContext applicationContext) {
MessageDispatcherServlet servlet = new MessageDispatcherServlet();
servlet.setApplicationContext(applicationContext);
servlet.setTransformWsdlLocations(true);
return new ServletRegistrationBean(servlet, "/ws/*");
}
@Bean(name = "widget")
public Wsdl11Definition defaultWsdl11Definition() {
SimpleWsdl11Definition wsdl11Definition = new SimpleWsdl11Definition();
wsdl11Definition.setWsdl(new ClassPathResource("/ws/WidgetApp.wsdl"));
return wsdl11Definition;
}
public List<String> ldapURL() {
List<String> ldapUrlList = new ArrayList<String>();
ldapUrlList.add(ldapURL);
return ldapUrlList;
}
@Bean
public DefaultSpringSecurityContextSource ldapContextSource() {
DefaultSpringSecurityContextSource contextSource = new DefaultSpringSecurityContextSource(ldapURL(),
ldapBaseDN);
contextSource.setDirObjectFactory(CustomDirObjectFactory.class);
contextSource.setUserDn(ldapUserDN);
contextSource.setPassword(ldapPassword);
contextSource.setPooled(true);
return contextSource;
}
@Bean
public FilterBasedLdapUserSearch ldapUserSearch() {
FilterBasedLdapUserSearch filterBasedLdapUserSearch = new FilterBasedLdapUserSearch("", "(uid={0})",
ldapContextSource());
return filterBasedLdapUserSearch;
}
@Bean
public DefaultLdapAuthoritiesPopulator ldapAuthoritiesPopulator() {
DefaultLdapAuthoritiesPopulator defaultLdapAuthoritiesPopulator = new DefaultLdapAuthoritiesPopulator(
ldapContextSource(), "ou=Roles");
defaultLdapAuthoritiesPopulator.setGroupRoleAttribute("cn");
defaultLdapAuthoritiesPopulator.setGroupSearchFilter("(uniquemember={0})");
return defaultLdapAuthoritiesPopulator;
}
@Bean
public LdapUserDetailsService ldapUserDetailsService() {
LdapUserDetailsService ldapUserDetailsService = new LdapUserDetailsService(ldapUserSearch(),
ldapAuthoritiesPopulator());
return ldapUserDetailsService;
}
@Bean
public BindAuthenticator ldapBindAuthenticator() {
BindAuthenticator authinticator = new BindAuthenticator(ldapContextSource());
authinticator.setUserSearch(ldapUserSearch());
return authinticator;
}
@Bean
public LdapAuthenticationProvider ldapAuthenticationProvider() {
LdapAuthenticationProvider ldapAuthProvider = new LdapAuthenticationProvider(ldapBindAuthenticator(),
ldapAuthoritiesPopulator());
return ldapAuthProvider;
}
@Bean
public ProviderManager ldapAuthenticationManager() {
List<AuthenticationProvider> ldapProviderList = new ArrayList<AuthenticationProvider>();
ldapProviderList.add(ldapAuthenticationProvider());
ProviderManager ldapProviderManager = new ProviderManager(ldapProviderList);
return ldapProviderManager;
}
@Bean
public CallbackHandler ldapSecurityHandler() {
SimplePasswordValidationCallbackHandler handler = new SimplePasswordValidationCallbackHandler();
handler.setUsersMap(Collections.singletonMap(ldapUserDN, ldapPassword));
return handler;
}
@Bean
public SoapFaultMappingExceptionResolver exceptionResolver() {
SoapFaultMappingExceptionResolver soapFaultMappingExceptionResolver = new SoapFaultMappingExceptionResolver();
SoapFaultDefinition defaultDefinition = new SoapFaultDefinition();
defaultDefinition.setFaultCode(SoapFaultDefinition.SERVER);
soapFaultMappingExceptionResolver.setDefaultFault(defaultDefinition);
Properties errorMappings = new Properties();
errorMappings.setProperty("org.springframework.ws.soap.security.wss4j.Wss4jSecurityValidationException=CLIENT",
"Timestamp and/or user credentials are invalid and/or missing");
errorMappings.setProperty("org.springframework.security.core.AuthenticationException=CLIENT",
"User authentication failed");
errorMappings.setProperty("org.springframework.security.access.AccessDeniedException=CLIENT",
"User authorization failed");
errorMappings.setProperty("java.lang.Exception=SERVER", "Problem waiting for a response");
soapFaultMappingExceptionResolver.setExceptionMappings(errorMappings);
return soapFaultMappingExceptionResolver;
}
@Bean
public Wss4jSecurityInterceptor wss4jSecurityInterceptor() {
Wss4jSecurityInterceptor wssjInt = new Wss4jSecurityInterceptor();
wssjInt.setValidationActions(WSConstants.TIMESTAMP_TOKEN_LN + " " + WSConstants.USERNAME_TOKEN_LN );
wssjInt.setValidationActions("Timestamp");
wssjInt.setTimestampStrict(true);
wssjInt.setValidationTimeToLive(3000);
wssjInt.setValidationCallbackHandler(ldapSecurityHandler());
wssjInt.setExceptionResolver(exceptionResolver());
return wssjInt;
}
@Bean
public AnnotationActionEndpointMapping annotationActionEndpointMapping() {
AnnotationActionEndpointMapping aaeMapping = new AnnotationActionEndpointMapping();
aaeMapping.setPreInterceptors(new EndpointInterceptor[] { wss4jSecurityInterceptor() });
return aaeMapping;
}
}
更新:
我已经取得了一些进步,但是仍然遇到相同的错误。我在配置中添加了拦截器
@Override
public void addInterceptors(List<EndpointInterceptor> interceptors) {
LOGGER.info("addInterceptors");
interceptors.add(wss4jSecurityInterceptor());
}
我已将trace选项添加到我的application.propeties文件中,可以看到正在从LDAP中检索角色
2019-05-15 13:24:16.247调试5576 --- [nio-8080-exec-6] .s.s.l.u.DefaultLdapAuthoritiesPopulator:搜索角色:[ROLE_ACCESS,ROLE_WRITE] 2019-05-15 13:24:16.247调试5576 --- [nio-8080-exec-6] ossluLdapUserDetailsMapper:使用DN从上下文映射用户详细信息: , ,*** 2019-05-15 13:24:16.247 WARN 5576 --- [nio-8080-exec-6] o.s.w.s.s.w.Wss4jSecurityInterceptor:无法验证请求:无法对安全令牌进行身份验证或授权;嵌套的异常是org.apache.wss4j.common.ext.WSSecurityException:无法对安全令牌进行身份验证或授权