【问题标题】:Spring Boot @RestController rejects a POST requestSpring Boot @RestController 拒绝 POST 请求
【发布时间】:2015-11-06 17:33:12
【问题描述】:

POST 请求

http://localhost:9278/submitEnrollment

封装外部 SOAP 调用的 Spring Boot 应用程序会产生以下结果:

{
  "timestamp": 1439480941381,
  "status": 401,
  "error": "Unauthorized",
  "message": "Full authentication is required to access this resource",
  "path": "/submitEnrollment"
}

这似乎不是正常行为,我想知道我需要放松/禁用哪些 Spring Boot 配置以防止此客户端身份验证。

以下是相关代码:

应用程序的配置(需要所有必要的管道以通过 SSL 发送安全的 SOAP 调用,并且应该影响 Web 层):

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

}

应用:

public static void main(String[] args) throws Throwable {
    SpringApplication app = new SpringApplication(SubmitEnrollmentApplication.class);
    //app.addListeners(new ApplicationPidFileWriter());
    ApplicationContext ctx = app.run(args);

控制器:

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

【问题讨论】:

  • 如果你的项目中有 spring security,spring boot 可能会默认设置它。您是否在日志输出中看到 spring boot 设置的用户名和密码?
  • 请编辑您的问题,以便为盲人读者提供正确的想法。
  • @gyoder - 确实如此,不,我在日志输出中看不到用户名和密码

标签: security web configuration spring-boot spring-restcontroller


【解决方案1】:

主 Spring 配置文件的以下添加帮助我实现了我所需要的:

@Configuration
    static class WebSecurityConfig extends WebSecurityConfigurerAdapter{
        @Override
        public void configure(WebSecurity web) throws Exception {
             web.ignoring().antMatchers("/**");
        }
    }

【讨论】:

  • 太棒了!谢谢!
【解决方案2】:

您的问题是,您的其余端点已通过 Spring Security 进行身份验证。因此错误消息清楚地表明,您希望在发送请求之前对自己进行身份验证。您可以忽略身份验证,直到确保一切正常。你需要的是这样的东西。

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.authorizeRequests().antMatchers("/submitEnrollment").permitAll().and().csrf().disable();
}

您可以从here 找到一个好的配置。如果您需要更复杂的配置,请通过这个 jhipster project,特别是这个 file

最好你也可以通过thesedocs。希望这会有所帮助。

【讨论】:

    猜你喜欢
    • 2015-06-13
    • 2023-01-13
    • 2016-06-27
    • 2021-09-08
    • 2017-01-14
    • 1970-01-01
    • 2021-10-07
    • 1970-01-01
    • 2019-01-01
    相关资源
    最近更新 更多