A POST request
http://localhost:9278/submitEnrollment
to a Spring Boot application that encapsulates an external SOAP call results in the following:
{
"timestamp": 1439480941381,
"status": 401,
"error": "Unauthorized",
"message": "Full authentication is required to access this resource",
"path": "/submitEnrollment"
}
This doesn't seem to be a normal behavior, I'm wondering what Spring Boot configurations I need to relax/disable to prevent this client authentication.
Here are relevant pieces of code:
Configuration for the app (that entails all the necessary plumbing to send a secured SOAP call over SSL and should affect web tier):
@Configuration
@ComponentScan({"a.b.c.d", "com.submit.enrollment"})
@PropertySource("classpath:/submit-enrollment.properties")
public class SubmitEnrollmentConfig {
@Value("${marshaller.contextPaths}")
private String[] marshallerContextPaths;
@Value("${default.Uri}")
private String defaultUri;
@Bean
public FfmSoapClient connectivityClient() throws Throwable {
FfmSoapClient client = new FfmSoapClient();
client.setWebServiceTemplate(webServiceTemplate());
return client;
}
@Bean
public KeyStore keyStore() throws Throwable {
KeyStoreFactoryBean keyStoreFactory = new KeyStoreFactoryBean();
keyStoreFactory.setPassword("!zxy!36!");
keyStoreFactory.setLocation(new ClassPathResource("zxy.jks"));
keyStoreFactory.setType("jks");
keyStoreFactory.afterPropertiesSet();
return keyStoreFactory.getObject();
}
@Bean
public KeyManager[] keyManagers() throws Throwable{
KeyManagersFactoryBean keyManagerFactory = new KeyManagersFactoryBean();
keyManagerFactory.setKeyStore(keyStore());
keyManagerFactory.setPassword("!zxy!36!");
keyManagerFactory.afterPropertiesSet();
return keyManagerFactory.getObject();
}
@Bean
public HttpsUrlConnectionMessageSender httpsUrlSender() throws Throwable {
HttpsUrlConnectionMessageSender sender = new HttpsUrlConnectionMessageSender();
sender.setSslProtocol("TLS");
sender.setKeyManagers(keyManagers());
return sender;
}
@Bean
public WebServiceTemplate webServiceTemplate() throws Throwable {
WebServiceTemplate webServiceTemplate = new WebServiceTemplate();
webServiceTemplate.setMarshaller(marshaller());
webServiceTemplate.setUnmarshaller(marshaller());
webServiceTemplate.setDefaultUri(defaultUri);
webServiceTemplate.setMessageFactory(messageFactory());
webServiceTemplate.setMessageSender(/*new HttpComponentsMessageSender()*/httpsUrlSender());
webServiceTemplate.setInterceptors(new ClientInterceptor[] { wss4jSecurityInterceptor(), new LogbackInterceptor() }); //order matters
webServiceTemplate.setMessageSender(httpsUrlSender());
return webServiceTemplate;
}
@Bean
public Jaxb2Marshaller marshaller() {
Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
marshaller.setContextPaths(marshallerContextPaths);
return marshaller;
}
@Bean
public SaajSoapMessageFactory messageFactory() {
SaajSoapMessageFactory messageFactory = new SaajSoapMessageFactory();
messageFactory.setSoapVersion(SoapVersion.SOAP_12);
return messageFactory;
}
@Bean
public Wss4jSecurityInterceptor wss4jSecurityInterceptor() throws Throwable{
Wss4jSecurityInterceptor wss4jSecurityInterceptor = new Wss4jSecurityInterceptor();
wss4jSecurityInterceptor.setSecurementActions(/*"UsernameToken"*/WSHandlerConstants.USERNAME_TOKEN + " "+ WSHandlerConstants.TIMESTAMP);
//wss4jSecurityInterceptor.setSecurementActions("Signature");
wss4jSecurityInterceptor.setSecurementUsername("07.ZIP.NJ*.390.639");
wss4jSecurityInterceptor.setSecurementPassword("oLD@cDh$(dKnCM");
wss4jSecurityInterceptor.setSecurementPasswordType(/*"PasswordDigest"*/WSConstants.PW_DIGEST);
wss4jSecurityInterceptor.setSecurementEncryptionCrypto(crypto());
wss4jSecurityInterceptor.setSecurementEncryptionKeyIdentifier("DirectReference");
//wss4jSecurityInterceptor.setValidationActions("Signature");
//wss4jSecurityInterceptor.setValidationSignatureCrypto( crypto() );
wss4jSecurityInterceptor.setSecurementTimeToLive(300);
return wss4jSecurityInterceptor;
}
@Bean
public Crypto crypto() throws Throwable {
CryptoFactoryBean cryptoFactoryBean = new CryptoFactoryBean();
cryptoFactoryBean.setKeyStoreLocation(new ClassPathResource("zipari.jks"));
cryptoFactoryBean.setKeyStorePassword("!zxy!36!");
cryptoFactoryBean.afterPropertiesSet();
Crypto crypto = cryptoFactoryBean.getObject();
System.out.println("created crypto store: "+ crypto);
return crypto;
}
@Configuration
static class DatabaseConfig {
@Bean @Lazy
DataSource dataSource() {
return null;
}
}
}
Application:
public static void main(String[] args) throws Throwable {
SpringApplication app = new SpringApplication(SubmitEnrollmentApplication.class);
//app.addListeners(new ApplicationPidFileWriter());
ApplicationContext ctx = app.run(args);
Controller:
@RestController
public class SubmitEnrollmentController {
private final Logger logger = LoggerFactory.getLogger(SubmitEnrollmentController.class);
//@Autowired @Qualifier("brokerService")private BrokerService service;
@RequestMapping(value = "/submitEnrollment", method = RequestMethod.POST, consumes="application/json")
public String submitEnrollment(@RequestBody String jsonIn){
logger.info("Received submit enrollment request: {}, start processing...", jsonIn);
The following addition to the main Spring config file helped me achieve what I needed:
@Configuration
static class WebSecurityConfig extends WebSecurityConfigurerAdapter{
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/**");
}
}