Spring thymeleaf模板在添加CORS配置时不起作用

时间:2019-12-17 07:34:13

标签: java spring-boot spring-mvc spring-security cors

我最近在springboot应用程序中添加了CORS配置。下面是此配置的代码。

package com.turtlemint.verticals.commonverticals;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.reactive.config.CorsRegistry;
import org.springframework.web.reactive.config.EnableWebFlux;
import org.springframework.web.reactive.config.WebFluxConfigurer;

/**
 * @author praveenkamath
 **/
@Configuration
@EnableWebFlux
public class CorsConfiguration implements WebFluxConfigurer {

    @Value("${cors.allowed.origins}")
    private String[]        corsSites;

    @Value("${cors.enabled}")
    private boolean         isCorsEnabled;


    @Override
    public void addCorsMappings(final CorsRegistry registry) {
        if(isCorsEnabled) {
            registry.addMapping("/api/device/**").allowedOrigins(corsSites).allowedMethods("*");
            registry.addMapping("/api/sehat/**").allowedOrigins(corsSites).allowedMethods("*");
            registry.addMapping("/api/dukandaar/**").allowedOrigins(corsSites).allowedMethods("*");
            return;
        } registry.addMapping("/**");
    }
}

我的application.properties

### CORS ###
cors.enabled=true
cors.allowed.origins=*
### CORS ###

添加后,我遇到了两个问题:

  1. 带有嵌套JSON的PUT请求给出以下错误
Internal Server Error","message":"Type definition error: [simple type, class com.turtlemint.verticals.commonverticals.common.containers.v1.collections.ReviewPayment]; nested exception is com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `com.turtlemint.verticals.commonverticals.common.containers.v1.collections.ReviewPayment` (no Creators, like default construct, exist): cannot deserialize from Object value (no delegate- or property-based Creator)\n at [Source: UNKNOWN; line: -1, column: -1] (through reference chain: com.turtlemint.verticals.commonverticals.dukandaar.containers.dto.DukandaarCheckoutDTO[\"reviewPayment\"])

ReviewPayment Java类:

package com.turtlemint.verticals.commonverticals.common.containers.v1.collections;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.turtlemint.verticals.commonverticals.common.enums.v1.ReviewPaymentStatusEnum;
import lombok.Data;

@Data
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonInclude(JsonInclude.Include.NON_NULL)
public class ReviewPayment {

    private ReviewPaymentStatusEnum status;

    private String rejectionReason;

    public ReviewPayment(ReviewPaymentStatusEnum status, String rejectionReason) {
        this.status = status;
        this.rejectionReason = rejectionReason;
    }
}

我在上面的类中添加了一个默认构造函数,并且可以正常工作。

  1. 从后端重定向到视图时出现以下错误
{
    "timestamp": 1576568268085,
    "path": "/api/dukandaar/v1/payment/callback/HDFC",
    "status": 500,
    "error": "Internal Server Error",
    "message": "Could not resolve view with name 'get_redirect'."
}

我的控制器:

package com.turtlemint.verticals.commonverticals.common.controllers.v1;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.turtle.enums.VerticalEnum;
import com.turtlemint.verticals.commonverticals.common.constants.v1.Constants;
import com.turtlemint.verticals.commonverticals.common.constants.v1.ThymeConstants;
import com.turtlemint.verticals.commonverticals.common.containers.v1.mappers.PaymentCallbackDTO;
import com.turtlemint.verticals.commonverticals.common.containers.v1.mappers.PaymentRedirectRequestDTO;
import com.turtlemint.verticals.commonverticals.common.containers.v1.mappers.ReviewStatusUpdateRequestDTO;
import com.turtlemint.verticals.commonverticals.common.containers.v1.mappers.ReviewStatusUpdateResponseDTO;
import com.turtlemint.verticals.commonverticals.common.containers.v1.mappers.notification.share.ShareRequestMapper;
import com.turtlemint.verticals.commonverticals.common.enums.v1.ReviewPaymentStatusEnum;
import com.turtlemint.verticals.commonverticals.common.services.CommonServiceFactory;
import com.turtlemint.verticals.commonverticals.common.utils.v1.BrokerUtils;
import com.turtlemint.verticals.commonverticals.common.utils.v1.MapUtils;
import com.turtlemint.verticals.commonverticals.deviceprotection.services.v1.DeviceProtectionServiceFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Mono;

import java.util.HashMap;
import java.util.Map;

/**
 * @author praveenkamath
 **/
@Controller
@RequestMapping("/api/{apiVertical}")
public class PaymentController {

    private static final Logger LOG = LoggerFactory.getLogger(PaymentController.class);

    private static final String REDIRECTION_PARAMS     = "redirectionParams";

    @Autowired
    private CommonServiceFactory    commonServiceFactory;

    @Autowired
    private DeviceProtectionServiceFactory deviceProtectionServiceFactory;

    @GetMapping(value = "/v1/payment/callback/{insurer}")
    public String processPayment(@PathVariable final String insurer, @PathVariable final String apiVertical, final Model model, final ServerHttpRequest serverRequest){
        LOG.info("[processPayment] request received {} for insurer {}",serverRequest.getQueryParams(), insurer);
        Map<String,Object> requestMap= MapUtils.convertMultiToRegularMap(serverRequest.getQueryParams());
        VerticalEnum verticalEnum = VerticalEnum.getValue(apiVertical);
        final String url = commonServiceFactory.getCheckoutService().processPayment(BrokerUtils.determineBroker(serverRequest.getURI().getHost()), requestMap, verticalEnum, insurer);
        final Map<String, String> redirectionParams = new HashMap<>();
        redirectionParams.put("url", url);
        model.addAttribute(REDIRECTION_PARAMS, redirectionParams);
        return ThymeConstants.REDIRECT_GET_TEMPLATE;
    }
}

public class ThymeConstants {

    private ThymeConstants() {}

    public static final String REDIRECT_GET_TEMPLATE   =   "get_redirect";
}

我的GET请求: https://<DOMAIN>/api/dukandaar/v1/payment/callback/HDFC?<query_params>

我注释掉了CORS配置,一切正常。

我仍在努力寻找第二个问题。一些帮助,将不胜感激。

1 个答案:

答案 0 :(得分:0)

最后找到了第二期的解决方案。必须覆盖百里香叶的配置。

CorsConfiguration现在看起来像这样:

package com.turtlemint.verticals.commonverticals.common.security.cors;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.reactive.config.CorsRegistry;
import org.springframework.web.reactive.config.EnableWebFlux;
import org.springframework.web.reactive.config.ViewResolverRegistry;
import org.springframework.web.reactive.config.WebFluxConfigurer;
import org.thymeleaf.spring5.ISpringWebFluxTemplateEngine;
import org.thymeleaf.spring5.SpringWebFluxTemplateEngine;
import org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver;
import org.thymeleaf.spring5.view.reactive.ThymeleafReactiveViewResolver;
import org.thymeleaf.templatemode.TemplateMode;

/**
 * @author praveenkamath
 **/
@Configuration
@EnableWebFlux
public class CorsConfiguration implements ApplicationContextAware, WebFluxConfigurer {

    @Value("${cors.allowed.origins}")
    private String[]        corsSites;

    @Value("${cors.enabled}")
    private boolean         isCorsEnabled;

    private ApplicationContext ctx;

    @Override
    public void setApplicationContext(ApplicationContext context) {
        this.ctx = context;
    }


    @Override
    public void addCorsMappings(final CorsRegistry registry) {
        if(isCorsEnabled) {
            registry.addMapping("/api/device/**").allowedOrigins(corsSites).allowedMethods("PUT", "PATCH", "DELETE", "OPTIONS");
            registry.addMapping("/api/sehat/**").allowedOrigins(corsSites).allowedMethods("PUT", "PATCH", "DELETE", "OPTIONS");
            registry.addMapping("/api/dukandaar/**").allowedOrigins(corsSites).allowedMethods("PUT", "PATCH", "DELETE", "OPTIONS");
            return;
        } registry.addMapping("/**");
    }

    @Bean
    SpringResourceTemplateResolver thymeleafTemplateResolver() {
        final SpringResourceTemplateResolver resolver = new SpringResourceTemplateResolver();
        resolver.setApplicationContext(this.ctx);
        resolver.setPrefix("classpath:/templates/");
        resolver.setSuffix(".html");
        resolver.setTemplateMode(TemplateMode.HTML);
        resolver.setCacheable(false);
        resolver.setCheckExistence(false);
        return resolver;

    }

    @Bean
    ISpringWebFluxTemplateEngine thymeleafTemplateEngine() {
        final SpringWebFluxTemplateEngine templateEngine = new SpringWebFluxTemplateEngine();
        templateEngine.setTemplateResolver(thymeleafTemplateResolver());
        return templateEngine;
    }

    @Bean
    ThymeleafReactiveViewResolver thymeleafChunkedAndDataDrivenViewResolver() {
        final ThymeleafReactiveViewResolver viewResolver = new ThymeleafReactiveViewResolver();
        viewResolver.setTemplateEngine(thymeleafTemplateEngine());
        viewResolver.setResponseMaxChunkSizeBytes(8192); // OUTPUT BUFFER size limit
        return viewResolver;
    }

    @Override
    public void configureViewResolvers(ViewResolverRegistry registry) {
        registry.viewResolver(thymeleafChunkedAndDataDrivenViewResolver());
    }
}