dg1cloud-core/pom.xml
.. .. @@ -53,6 +53,22 @@ 53 53 </dependency> 54 54 55 55 <dependency> 56 + <groupId>org.springframework.boot</groupId>57 + <artifactId>spring-boot-starter-thymeleaf</artifactId>58 + </dependency>59 +60 + <dependency>61 + <groupId>org.springframework.boot</groupId>62 + <artifactId>spring-boot-configuration-processor</artifactId>63 + <optional>true</optional>64 + </dependency>65 +66 + <dependency>67 + <groupId>org.apache.httpcomponents</groupId>68 + <artifactId>httpclient</artifactId>69 + </dependency>70 +71 + <dependency>56 72 <groupId>org.postgresql</groupId> 57 73 <artifactId>postgresql</artifactId> 58 74 </dependency> .. .. @@ -77,7 +93,19 @@ 77 93 <dependency> 78 94 <groupId>commons-codec</groupId> 79 95 <artifactId>commons-codec</artifactId> 80 - </dependency>96 + </dependency>97 +98 + <!-- bootstrap and jquery -->99 + <dependency>100 + <groupId>org.webjars</groupId>101 + <artifactId>bootstrap</artifactId>102 + <version>3.3.7</version>103 + </dependency>104 + <dependency>105 + <groupId>org.webjars</groupId>106 + <artifactId>jquery</artifactId>107 + <version>3.2.1</version>108 + </dependency>81 109 82 110 </dependencies> 83 111 dg1cloud-core/src/main/java/it/digione/dg1cloud/config/dg1cloud.properties
.. .. @@ -13,4 +13,9 @@ 13 13 14 14 server.servlet.context-path=/dg1cloud 15 15 16 -external.server.address.base.url=http://vannux.grupposistematica.it:8080/dg1cloud16 +external.server.address.base.url=http://vannux.grupposistematica.it:8080/dg1cloud17 +18 +google.recaptcha.enabled=false19 +google.recaptcha.url=https://www.google.com/recaptcha/api/siteverify20 +google.recaptcha.key=6LfCHmkUAAAAAFa1KmVtPFecItBriBHx1qmKHcVS21 +google.recaptcha.secret=6LfCHmkUAAAAAKXdXWO36daHnItKQwkEvXOpX6YYdg1cloud-core/src/main/java/it/digione/dg1cloud/controller/DownloadFileController.java
.. .. @@ -1,82 +1,40 @@ 1 1 package it.digione.dg1cloud.controller; 2 2 3 -import java.io.File;4 -import java.io.FileInputStream;5 3 import java.io.IOException; 6 4 7 -import javax.servlet.ServletContext;8 -9 -import org.apache.logging.log4j.util.Strings;10 5 import org.slf4j.Logger; 11 6 import org.slf4j.LoggerFactory; 12 7 import org.springframework.beans.factory.annotation.Autowired; 13 8 import org.springframework.core.io.InputStreamResource; 14 -import org.springframework.http.HttpHeaders;15 -import org.springframework.http.MediaType;16 9 import org.springframework.http.ResponseEntity; 17 10 import org.springframework.stereotype.Controller; 18 11 import org.springframework.web.bind.annotation.RequestMapping; 19 12 import org.springframework.web.bind.annotation.RequestParam; 20 13 21 -import it.digione.dg1cloud.model.RegDocument;22 -import it.digione.dg1cloud.repository.RegDocumentRepository;23 -import it.digione.dg1cloud.service.CloudService;14 +import it.digione.dg1cloud.recaptcha.CaptchaSettings;15 +import it.digione.dg1cloud.service.Utils;24 16 25 17 @Controller 26 18 public class DownloadFileController { 27 19 28 - private static final Logger logger = LoggerFactory.getLogger(CloudService.class);20 + private static final Logger logger = LoggerFactory.getLogger(DownloadFileController.class);29 21 30 - @Autowired private ServletContext servletContext;31 - @Autowired private RegDocumentRepository regDocumentRepository;22 + @Autowired private Utils utils;23 + @Autowired CaptchaSettings captchaSettings;32 24 33 25 @RequestMapping("/downloadFile") 34 26 public ResponseEntity<InputStreamResource> downloadFile(@RequestParam String fileName, 35 - @RequestParam long id,36 - @RequestParam(value = "secretKey", required = false) String secretKey) throws IOException {27 + @RequestParam long id,28 + @RequestParam(value = "secretKey", required = false) String secretKey) throws IOException {37 29 38 - logger.debug("Avvio download file {} con id {}, fileName, id");39 -40 - MediaType mediaType = MediaType.APPLICATION_OCTET_STREAM;41 - try {42 - mediaType = MediaType.parseMediaType(servletContext.getMimeType(fileName));43 - } catch (Exception e) {44 - logger.warn("Errore nello stabilire il mime type del file. VerrĂ usato " + mediaType.toString(), e);30 + if ( captchaSettings.isEnabled() == true ) {31 + String error = "Download diretto non ammesso. Usare la pagina di download tramite reCaptcha";32 + logger.error(error);33 + throw new RuntimeException("Download diretto non ammesso. Usare la pagina di download tramite reCaptcha");45 34 } 46 35 47 - RegDocument regDocument = regDocumentRepository.getOne(id);48 -49 - if (regDocument.getFileName().equalsIgnoreCase(fileName) == false ) {50 - logger.error("Il nome del file richiesto non corrisponde con quello referenziato dall'id");51 - throw new RuntimeException("Il nome del file richiesto non corrisponde con quello referenziato dall'id");52 - }53 -54 - if ( regDocument.getSecretKey() != null ) {55 - logger.debug("E' stata specificata una secretKey. Avvio le verifiche.");56 - if ( Strings.isEmpty(secretKey) == true ) {57 - logger.error("Non e' stata inviata la secretKey");58 - throw new RuntimeException("Per scaricare il file occorre specificare la secretKey");59 - } else {60 - logger.debug("Controllo corrispondenza della secretKey");61 - if (secretKey.equals(regDocument.getSecretKey()) == false ) {62 - logger.error("La secretKey inviata non corrisponde a quella impostata in fase di richiesta salvataggio del file");63 - throw new RuntimeException("La secretKey inviata non corrisponde a quella impostata in fase di richiesta salvataggio del file");64 - } else {65 - logger.debug("SecretKey verificata correttamente");66 - }67 - }68 - }69 -70 - File file = new File(regDocument.getFilePath());71 - FileInputStream fis = new FileInputStream(file);72 - InputStreamResource isr = new InputStreamResource(fis);73 - return ResponseEntity.ok()74 - // Content-Disposition75 - .header(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=" + file.getName())76 - // Content-Type77 - .contentType(mediaType)78 - // Contet-Length79 - .contentLength(file.length()) //80 - .body(isr);36 + return utils.getDownloadResponseEntity(fileName, id, secretKey);81 37 } 38 +39 +82 40 } dg1cloud-core/src/main/java/it/digione/dg1cloud/controller/DownloadPageController.java
.. .. @@ -0,0 +1,38 @@ 1 +package it.digione.dg1cloud.controller;2 +3 +import java.io.IOException;4 +5 +import org.slf4j.Logger;6 +import org.slf4j.LoggerFactory;7 +import org.springframework.beans.factory.annotation.Autowired;8 +import org.springframework.stereotype.Controller;9 +import org.springframework.web.bind.annotation.RequestMapping;10 +import org.springframework.web.bind.annotation.RequestParam;11 +import org.springframework.web.servlet.ModelAndView;12 +13 +import it.digione.dg1cloud.recaptcha.CaptchaSettings;14 +import it.digione.dg1cloud.recaptcha.DownloadFileCaptchaForm;15 +16 +@Controller17 +public class DownloadPageController {18 +19 + private static final Logger logger = LoggerFactory.getLogger(DownloadPageController.class);20 +21 + @RequestMapping("/downloadPage")22 + public ModelAndView downloadPage(@RequestParam String fileName, @RequestParam long id,23 + @RequestParam(value = "secretKey", required = false) String secretKey) throws IOException {24 +25 + logger.debug("Preparazione pagina download file {} con id {}", fileName, id);26 +27 + DownloadFileCaptchaForm downloadParams = new DownloadFileCaptchaForm();28 +29 + downloadParams.setFileName(fileName);30 + downloadParams.setId(id);31 + downloadParams.setSecretKey(secretKey);32 +33 + ModelAndView modelAndView = new ModelAndView("downloadFileCaptcha");34 + modelAndView.addObject("downloadFileCaptchaForm", downloadParams);35 +36 + return modelAndView;37 + }38 +}dg1cloud-core/src/main/java/it/digione/dg1cloud/recaptcha/CaptchaSettings.java
.. .. @@ -0,0 +1,46 @@ 1 +package it.digione.dg1cloud.recaptcha;2 +3 +import org.springframework.boot.context.properties.ConfigurationProperties;4 +import org.springframework.stereotype.Component;5 +6 +@Component7 +@ConfigurationProperties(prefix = "google.recaptcha")8 +public class CaptchaSettings {9 +10 + private boolean enabled;11 + private String url;12 + private String key;13 + private String secret;14 +15 + public boolean isEnabled() {16 + return enabled;17 + }18 +19 + public void setEnabled(boolean enabled) {20 + this.enabled = enabled;21 + }22 +23 + public String getUrl() {24 + return url;25 + }26 +27 + public void setUrl(String url) {28 + this.url = url;29 + }30 +31 + public String getKey() {32 + return key;33 + }34 +35 + public void setKey(String key) {36 + this.key = key;37 + }38 +39 + public String getSecret() {40 + return secret;41 + }42 +43 + public void setSecret(String secret) {44 + this.secret = secret;45 + }46 +}dg1cloud-core/src/main/java/it/digione/dg1cloud/recaptcha/DownloadFileCaptchaController.java
.. .. @@ -0,0 +1,44 @@ 1 +package it.digione.dg1cloud.recaptcha;2 +3 +import java.io.FileNotFoundException;4 +5 +import javax.validation.Valid;6 +7 +import org.springframework.beans.factory.annotation.Autowired;8 +import org.springframework.stereotype.Controller;9 +import org.springframework.validation.BindingResult;10 +import org.springframework.web.bind.annotation.ModelAttribute;11 +import org.springframework.web.bind.annotation.PostMapping;12 +import org.springframework.web.bind.annotation.RequestMapping;13 +import org.springframework.web.servlet.ModelAndView;14 +15 +import it.digione.dg1cloud.service.Utils;16 +17 +@Controller18 +@RequestMapping("/downloadFileCaptcha")19 +public class DownloadFileCaptchaController {20 +21 + @Autowired private Utils utils;22 +23 + @ModelAttribute("downloadFileCaptchaForm")24 + public DownloadFileCaptchaForm downloadFileCaptchaForm() {25 + return new DownloadFileCaptchaForm();26 + }27 +28 + @PostMapping29 + public Object handleDownloadFileCaptcha(@ModelAttribute("downloadFileCaptchaForm") @Valid DownloadFileCaptchaForm form,30 + BindingResult result) throws FileNotFoundException{31 +32 + ModelAndView modelAndView;33 + if (result.hasErrors()){34 + modelAndView = new ModelAndView("downloadFileCaptcha");35 + modelAndView.addObject(result);36 + modelAndView.addObject("downloadFileCaptchaForm", form);37 +38 + return modelAndView;39 + } else {40 + return utils.getDownloadResponseEntity(form.getFileName(), form.getId(), form.getSecretKey());41 + }42 +43 + }44 +}dg1cloud-core/src/main/java/it/digione/dg1cloud/recaptcha/DownloadFileCaptchaForm.java
.. .. @@ -0,0 +1,41 @@ 1 +package it.digione.dg1cloud.recaptcha;2 +3 +import javax.validation.constraints.NotEmpty;4 +import javax.validation.constraints.NotNull;5 +6 +public class DownloadFileCaptchaForm {7 +8 + @NotNull9 + private Long id;10 + private String fileName;11 + private String secretKey;12 + @NotEmpty13 + @ValidReCaptcha14 + private String reCaptchaResponse;15 +16 + public Long getId() {17 + return id;18 + }19 + public void setId(Long id) {20 + this.id = id;21 + }22 + public String getFileName() {23 + return fileName;24 + }25 + public void setFileName(String fileName) {26 + this.fileName = fileName;27 + }28 + public String getSecretKey() {29 + return secretKey;30 + }31 + public void setSecretKey(String secretKey) {32 + this.secretKey = secretKey;33 + }34 + public String getReCaptchaResponse() {35 + return reCaptchaResponse;36 + }37 + public void setReCaptchaResponse(String reCaptchaResponse) {38 + this.reCaptchaResponse = reCaptchaResponse;39 + }40 +41 +}dg1cloud-core/src/main/java/it/digione/dg1cloud/recaptcha/ReCaptchaConstraintValidator.java
.. .. @@ -0,0 +1,28 @@ 1 +package it.digione.dg1cloud.recaptcha;2 +3 +import org.springframework.beans.factory.annotation.Autowired;4 +5 +import javax.validation.ConstraintValidator;6 +import javax.validation.ConstraintValidatorContext;7 +8 +public class ReCaptchaConstraintValidator implements ConstraintValidator<ValidReCaptcha, String> {9 +10 + @Autowired11 + private ReCaptchaService reCaptchaService;12 +13 + @Override14 + public void initialize(ValidReCaptcha constraintAnnotation) {15 +16 + }17 +18 + @Override19 + public boolean isValid(String reCaptchaResponse, ConstraintValidatorContext context) {20 +21 + if (reCaptchaResponse == null || reCaptchaResponse.isEmpty()){22 + return true;23 + }24 +25 + return reCaptchaService.validate(reCaptchaResponse);26 + }27 +28 +}dg1cloud-core/src/main/java/it/digione/dg1cloud/recaptcha/ReCaptchaResponse.java
.. .. @@ -0,0 +1,103 @@ 1 +package it.digione.dg1cloud.recaptcha;2 +3 +import com.fasterxml.jackson.annotation.*;4 +5 +import java.util.Date;6 +import java.util.HashMap;7 +import java.util.Map;8 +9 +@JsonInclude(JsonInclude.Include.NON_NULL)10 +@JsonIgnoreProperties(ignoreUnknown = true)11 +@JsonPropertyOrder({12 + "success",13 + "challenge_ts",14 + "hostname",15 + "error-codes"16 +})17 +public class ReCaptchaResponse {18 +19 + @JsonProperty("success")20 + private boolean success;21 +22 + @JsonProperty("challenge_ts")23 + private Date challengeTs;24 +25 + @JsonProperty("hostname")26 + private String hostname;27 +28 + @JsonProperty("error-codes")29 + private ErrorCode[] errorCodes;30 +31 + @JsonIgnore32 + public boolean hasClientError() {33 + ErrorCode[] errors = getErrorCodes();34 + if(errors == null) {35 + return false;36 + }37 + for(ErrorCode error : errors) {38 + switch(error) {39 + case InvalidResponse:40 + case MissingResponse:41 + return true;42 + case InvalidSecret:43 + break;44 + case MissingSecret:45 + break;46 + default:47 + break;48 + }49 + }50 + return false;51 + }52 +53 + static enum ErrorCode {54 + MissingSecret, InvalidSecret,55 + MissingResponse, InvalidResponse;56 +57 + private static Map<String, ErrorCode> errorsMap = new HashMap<>(4);58 +59 + static {60 + errorsMap.put("missing-input-secret", MissingSecret);61 + errorsMap.put("invalid-input-secret", InvalidSecret);62 + errorsMap.put("missing-input-response", MissingResponse);63 + errorsMap.put("invalid-input-response", InvalidResponse);64 + }65 +66 + @JsonCreator67 + public static ErrorCode forValue(String value) {68 + return errorsMap.get(value.toLowerCase());69 + }70 + }71 +72 + public boolean isSuccess() {73 + return success;74 + }75 +76 + public void setSuccess(boolean success) {77 + this.success = success;78 + }79 +80 + public Date getChallengeTs() {81 + return challengeTs;82 + }83 +84 + public void setChallengeTs(Date challengeTs) {85 + this.challengeTs = challengeTs;86 + }87 +88 + public String getHostname() {89 + return hostname;90 + }91 +92 + public void setHostname(String hostname) {93 + this.hostname = hostname;94 + }95 +96 + public ErrorCode[] getErrorCodes() {97 + return errorCodes;98 + }99 +100 + public void setErrorCodes(ErrorCode[] errorCodes) {101 + this.errorCodes = errorCodes;102 + }103 +}dg1cloud-core/src/main/java/it/digione/dg1cloud/recaptcha/ReCaptchaResponseFilter.java
.. .. @@ -0,0 +1,75 @@ 1 +package it.digione.dg1cloud.recaptcha;2 +3 +import org.springframework.stereotype.Component;4 +5 +import javax.servlet.*;6 +import javax.servlet.http.HttpServletRequest;7 +import javax.servlet.http.HttpServletRequestWrapper;8 +import javax.servlet.http.HttpServletResponse;9 +import java.io.IOException;10 +import java.util.Collections;11 +import java.util.Enumeration;12 +import java.util.HashMap;13 +import java.util.Map;14 +15 +@Component16 +public class ReCaptchaResponseFilter implements Filter {17 +18 + private static final String RE_CAPTCHA_ALIAS = "reCaptchaResponse";19 + private static final String RE_CAPTCHA_RESPONSE = "g-recaptcha-response";20 +21 + @Override22 + public void init(FilterConfig filterConfig) throws ServletException {23 + }24 +25 + @Override26 + public void doFilter(ServletRequest servletRequest,27 + ServletResponse servletResponse,28 + FilterChain chain) throws IOException, ServletException {29 +30 + HttpServletRequest request = (HttpServletRequest) servletRequest;31 + HttpServletResponse response = (HttpServletResponse) servletResponse;32 +33 + if (request.getParameter(RE_CAPTCHA_RESPONSE) != null) {34 + ReCaptchaHttpServletRequest reCaptchaRequest = new ReCaptchaHttpServletRequest(request);35 + chain.doFilter(reCaptchaRequest, response);36 + } else {37 + chain.doFilter(request, response);38 + }39 + }40 +41 + @Override42 + public void destroy() {43 + }44 +45 + private static class ReCaptchaHttpServletRequest extends HttpServletRequestWrapper {46 +47 + final Map<String, String[]> params;48 +49 + ReCaptchaHttpServletRequest(HttpServletRequest request) {50 + super(request);51 + params = new HashMap<>(request.getParameterMap());52 + params.put(RE_CAPTCHA_ALIAS, request.getParameterValues(RE_CAPTCHA_RESPONSE));53 + }54 +55 + @Override56 + public String getParameter(String name) {57 + return params.containsKey(name) ? params.get(name)[0] : null;58 + }59 +60 + @Override61 + public Map<String, String[]> getParameterMap() {62 + return params;63 + }64 +65 + @Override66 + public Enumeration<String> getParameterNames() {67 + return Collections.enumeration(params.keySet());68 + }69 +70 + @Override71 + public String[] getParameterValues(String name) {72 + return params.get(name);73 + }74 + }75 +}dg1cloud-core/src/main/java/it/digione/dg1cloud/recaptcha/ReCaptchaService.java
.. .. @@ -0,0 +1,46 @@ 1 +package it.digione.dg1cloud.recaptcha;2 +3 +import org.slf4j.Logger;4 +import org.slf4j.LoggerFactory;5 +import org.springframework.beans.factory.annotation.Autowired;6 +import org.springframework.stereotype.Service;7 +import org.springframework.web.client.RestOperations;8 +9 +import javax.servlet.http.HttpServletRequest;10 +import java.net.URI;11 +12 +@Service13 +public class ReCaptchaService {14 +15 + private static final Logger log = LoggerFactory.getLogger(ReCaptchaService.class);16 +17 + @Autowired18 + private RestOperations restTemplate;19 +20 + @Autowired21 + private CaptchaSettings captchaSettings;22 +23 + @Autowired24 + private HttpServletRequest request;25 +26 + public boolean validate(String reCaptchaResponse){27 + URI verifyUri = URI.create(String.format(28 + captchaSettings.getUrl() + "?secret=%s&response=%s&remoteip=%s",29 + captchaSettings.getSecret(),30 + reCaptchaResponse,31 + request.getRemoteAddr()32 + ));33 +34 + try {35 + ReCaptchaResponse response = restTemplate.getForObject(verifyUri, ReCaptchaResponse.class);36 + return response.isSuccess();37 + } catch (Exception ignored){38 + log.error("", ignored);39 + // ignore when google services are not available40 + // maybe add some sort of logging or trigger that'll alert the administrator41 + }42 +43 + return true;44 + }45 +46 +}dg1cloud-core/src/main/java/it/digione/dg1cloud/recaptcha/RestTemplateConfig.java
.. .. @@ -0,0 +1,32 @@ 1 +package it.digione.dg1cloud.recaptcha;2 +3 +import org.apache.http.client.HttpClient;4 +import org.apache.http.impl.client.HttpClientBuilder;5 +import org.springframework.context.annotation.Bean;6 +import org.springframework.context.annotation.Configuration;7 +import org.springframework.http.client.ClientHttpRequestFactory;8 +import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;9 +import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;10 +import org.springframework.web.client.RestTemplate;11 +12 +@Configuration13 +public class RestTemplateConfig {14 +15 + @Bean16 + public RestTemplate restTemplate(ClientHttpRequestFactory httpRequestFactory) {17 + RestTemplate template = new RestTemplate(httpRequestFactory);18 + template.getMessageConverters().add(new MappingJackson2HttpMessageConverter());19 + return template;20 + }21 +22 + @Bean23 + public ClientHttpRequestFactory httpRequestFactory(HttpClient httpClient) {24 + return new HttpComponentsClientHttpRequestFactory(httpClient);25 + }26 +27 + @Bean28 + public HttpClient httpClient() {29 + return HttpClientBuilder.create().build();30 + }31 +32 +}dg1cloud-core/src/main/java/it/digione/dg1cloud/recaptcha/ValidReCaptcha.java
.. .. @@ -0,0 +1,25 @@ 1 +package it.digione.dg1cloud.recaptcha;2 +3 +import javax.validation.Payload;4 +import javax.validation.Constraint;5 +import java.lang.annotation.Documented;6 +import java.lang.annotation.Retention;7 +import java.lang.annotation.Target;8 +import static java.lang.annotation.ElementType.ANNOTATION_TYPE;9 +import static java.lang.annotation.ElementType.TYPE;10 +import static java.lang.annotation.ElementType.FIELD;11 +import static java.lang.annotation.RetentionPolicy.RUNTIME;12 +13 +@Documented14 +@Constraint(validatedBy = ReCaptchaConstraintValidator.class)15 +@Target({ TYPE, FIELD, ANNOTATION_TYPE })16 +@Retention(RUNTIME)17 +public @interface ValidReCaptcha {18 +19 + String message() default "Invalid ReCaptcha";20 +21 + Class<?>[] groups() default {};22 +23 + Class<? extends Payload>[] payload() default {};24 +25 +}dg1cloud-core/src/main/java/it/digione/dg1cloud/service/Utils.java
.. .. @@ -1,33 +1,44 @@ 1 1 package it.digione.dg1cloud.service; 2 2 3 3 import java.io.File; 4 +import java.io.FileInputStream;5 +import java.io.FileNotFoundException;4 6 import java.io.IOException; 5 7 import java.net.MalformedURLException; 6 8 import java.net.URL; 9 +10 +import javax.servlet.ServletContext;7 11 8 12 import org.apache.commons.io.FileUtils; 9 13 import org.apache.logging.log4j.util.Strings; 10 14 import org.slf4j.Logger; 11 15 import org.slf4j.LoggerFactory; 12 16 import org.springframework.beans.factory.annotation.Autowired; 17 +import org.springframework.core.io.InputStreamResource;18 +import org.springframework.http.HttpHeaders;19 +import org.springframework.http.MediaType;20 +import org.springframework.http.ResponseEntity;13 21 import org.springframework.stereotype.Service; 14 22 import org.springframework.web.util.UriBuilder; 15 23 import org.springframework.web.util.UriComponentsBuilder; 16 24 17 25 import it.digione.dg1cloud.config.AppConfig; 18 26 import it.digione.dg1cloud.model.RegDocument; 27 +import it.digione.dg1cloud.repository.RegDocumentRepository;19 28 20 29 @Service("utils") 21 30 public class Utils { 22 31 23 32 @Autowired private AppConfig appConfig; 33 + @Autowired private RegDocumentRepository regDocumentRepository;34 + @Autowired private ServletContext servletContext;24 35 25 36 private static final Logger logger = LoggerFactory.getLogger(CloudService.class); 26 37 27 38 public URL generateUrl(RegDocument regDocument) throws MalformedURLException { 28 39 logger.debug("Genero l'url per il record file {} con id {}", regDocument.getFileName(), regDocument.getDocumentId()); 29 40 UriBuilder uriBuilder = UriComponentsBuilder.fromUriString(appConfig.getExternalBaseUrl()); 30 - uriBuilder.path("/downloadFile");41 + uriBuilder.path("/downloadPage");31 42 uriBuilder.queryParam("fileName", regDocument.getFileName()); 32 43 uriBuilder.queryParam("id", regDocument.getDocumentId()); 33 44 if ( Strings.isEmpty(regDocument.getSecretKey()) == false ) { .. .. @@ -53,4 +64,51 @@ 53 64 logger.debug("La directory {} non e' vuota", directory.getAbsolutePath()); 54 65 } 55 66 } 67 +68 + public ResponseEntity<InputStreamResource> getDownloadResponseEntity(String fileName, long id, String secretKey)69 + throws FileNotFoundException {70 + logger.debug("Avvio download file {} con id {}", fileName, id);71 +72 + MediaType mediaType = MediaType.APPLICATION_OCTET_STREAM;73 + try {74 + mediaType = MediaType.parseMediaType(servletContext.getMimeType(fileName));75 + } catch (Exception e) {76 + logger.warn("Errore nello stabilire il mime type del file. VerrĂ usato " + mediaType.toString(), e);77 + }78 +79 + RegDocument regDocument = regDocumentRepository.getOne(id);80 +81 + if (regDocument.getFileName().equalsIgnoreCase(fileName) == false ) {82 + logger.error("Il nome del file richiesto non corrisponde con quello referenziato dall'id");83 + throw new RuntimeException("Il nome del file richiesto non corrisponde con quello referenziato dall'id");84 + }85 +86 + if ( regDocument.getSecretKey() != null ) {87 + logger.debug("E' stata specificata una secretKey. Avvio le verifiche.");88 + if ( Strings.isEmpty(secretKey) == true ) {89 + logger.error("Non e' stata inviata la secretKey");90 + throw new RuntimeException("Per scaricare il file occorre specificare la secretKey");91 + } else {92 + logger.debug("Controllo corrispondenza della secretKey");93 + if (secretKey.equals(regDocument.getSecretKey()) == false ) {94 + logger.error("La secretKey inviata non corrisponde a quella impostata in fase di richiesta salvataggio del file");95 + throw new RuntimeException("La secretKey inviata non corrisponde a quella impostata in fase di richiesta salvataggio del file");96 + } else {97 + logger.debug("SecretKey verificata correttamente");98 + }99 + }100 + }101 +102 + File file = new File(regDocument.getFilePath());103 + FileInputStream fis = new FileInputStream(file);104 + InputStreamResource isr = new InputStreamResource(fis);105 + return ResponseEntity.ok()106 + // Content-Disposition107 + .header(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=" + file.getName())108 + // Content-Type109 + .contentType(mediaType)110 + // Contet-Length111 + .contentLength(file.length()) //112 + .body(isr);113 + }56 114 } dg1cloud-core/src/main/resources/templates/downloadFileCaptcha.html
.. .. @@ -0,0 +1,48 @@ 1 +<!DOCTYPE html>2 +<html xmlns:th="http://www.thymeleaf.org">3 + <head>4 + <meta charset="utf-8"/>5 + <meta http-equiv="X-UA-Compatible" content="IE=edge"/>6 + <meta name="viewport" content="width=device-width, initial-scale=1"/>7 +8 + <link rel="stylesheet" type="text/css" th:href="@{/webjars/bootstrap/3.3.7/css/bootstrap.min.css}"/>9 + <link rel="stylesheet" type="text/css" th:href="@{/css/main.css}"/>10 +11 + <title>Link download file</title>12 + <script src='https://www.google.com/recaptcha/api.js'></script>13 + </head>14 + <body>15 + <div class="container">16 + <div class="row">17 + <div class="col-md-4 col-md-offset-4">18 + <div class="panel panel-default">19 + <div class="panel-body">20 + <div class="text-center">21 + <h3><i class="glyphicon glyphicon-lock" style="font-size:2em;"></i></h3>22 + <h2 class="text-center" th:text="*{downloadFileCaptchaForm.fileName}"></h2>23 + <div class="panel-body">24 + <form action="#" th:action="@{/downloadFileCaptcha}" th:object="${downloadFileCaptchaForm}" method="post">25 + <input type="hidden" th:field="*{id}" />26 + <input type="hidden" th:field="*{fileName}" />27 + <input type="hidden" th:field="*{secretKey}" />28 + <div class="form-group">29 + <div class="g-recaptcha" th:attr="data-sitekey=${@captchaSettings.getKey()}"></div>30 + <p class="error-message"31 + th:each="error: ${#fields.errors('reCaptchaResponse')}"32 + th:text="${error}">Errore validazione reCaptcha</p>33 + </div>34 + <div class="form-group">35 + <button name="downloadFile" type="submit" th:text="'Scarica il file ' + *{fileName} "></button>36 + </div>37 + </form>38 + </div>39 + </div>40 + </div>41 + </div>42 + </div>43 + </div>44 + </div>45 + <script type="text/javascript" th:src="@{/webjars/jquery/3.2.1/jquery.min.js/}"></script>46 + <script type="text/javascript" th:src="@{/webjars/bootstrap/3.3.7/js/bootstrap.min.js}"></script>47 + </body>48 +</html>