Sandra Lewandowska

Witaj w mojej przestrzeni!

Angular 6 + Spring Boot + reCAPTCHA w przesyłanym formularzu

Po pierwsze należy wygenerować indywidulany dla domeny (może być też localhost dla testów lokalnych) sitekey i secret –> Google reCAPTCHA

Integracja po stronie klienta
W formularzu dodajemy kod reCAPTCHA z wygenerowanym sitekey

<div class="form-group">
<div class="g-recaptcha" data-sitekey="6Lf7anUUAAAAAHobMeDJkbR_xxxasasasa"></div>
</div>

Następnie w komponencie z formularzem w metodzie ngOnInit() dodajemy do strony skrypt z api reCAPTCHA. Jeśli skrypt zostałby dodany do index.html, to reCAPTCHA pojawiałaby się tylko po odświeżeniu strony.

ngOnInit(){ this.addScript(); }
	addScript() {
    let script = document.createElement('script');
    script.src = 'https://www.google.com/recaptcha/api.js';
    script.async = true;
    script.defer = true;
    document.body.appendChild(script);
}

Przed wysłaniem formularza należy sprawdzić czy pole “Nie jestem robotem” zostało zaznaczone.

onSubmit() {
    this.submitted = true;
	 const response = grecaptcha.getResponse();
         if (response.length === 0) {
            alert('Recaptcha not verified.');
            return;
        }
    this.save(); 
  }
	
	save() { 
    this.accountService.createNewUser(this.registerForm.value, grecaptcha.getResponse())
    .subscribe(
        data => { console.log(data); },
        error => { console.log(error); })
 }

Integracja po stronie serwera – tutaj przyda się przydzielony wcześniej kod secret

@PostMapping("/new")
	    @ResponseStatus(HttpStatus.CREATED)
		public void  createUser(@RequestBody UserDTO user, @RequestParam(name="response") String recaptchaResponse) {
	    	captchaVerification.verify(recaptchaResponse);
			userRepository.findByEmailIgnoreCase(user.getEmail())
			.ifPresent(u -> {throw new ResourceExistsException("User with login: "+user.getEmail()+" exist");});
	   	  	User createdUser = userService.createUser(user);
		}

Przed dodaniem nowego użytkownika do bazy danych należy sprawdzić poprawność recaptchaResponse, wysyłając zapytanie przez recaptcha api.

import java.net.URI;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

@Service("captchaVerification")
public class CaptchaVerification {

	 	@Autowired
	    private CaptchaSettings captchaSettings;

	 	public void verify(String response) {
       
        URI verifyUri = URI.create(String.format(
          "https://www.google.com/recaptcha/api/siteverify?secret=%s&response=%s",
          captchaSettings.getSecret(), response));
        
        RestTemplate restTemplate = new RestTemplate();
        GoogleResponse googleResponse = restTemplate.getForObject(verifyUri, GoogleResponse.class);
 
        if(!googleResponse.isSuccess()) {
            throw new InvalidRecaptchaException();
        }
    }
}

Sitekey i Secret umieszczone są w application.properties

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

@Component
@ConfigurationProperties(prefix = "google.recaptcha.key")
public class CaptchaSettings {
 
    private String site;
    private String secret;
    
	public String getSite() {
		return site;
	}
	public void setSite(String site) {
		this.site = site;
	}
	public String getSecret() {
		return secret;
	}
	public void setSecret(String secret) {
		this.secret = secret;
	}

}

Klasa GoogleResponse jest schematem reprezentującym odpowiedź przesłaną od Google Api i pomaga stwierdzić poprawność walidacji reCAPRTCHA.

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

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;

@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonPropertyOrder({
    "success",
    "challenge_ts",
    "hostname",
    "error-codes"
})
public class GoogleResponse {

	 @JsonProperty("success")
	    private boolean success;
	     
	    @JsonProperty("challenge_ts")
	    private String challengeTs;
	     
	    @JsonProperty("hostname")
	    private String hostname;
	     
	    @JsonProperty("error-codes")
	    private ErrorCode[] errorCodes;
	 
	    @JsonIgnore
	    public boolean hasClientError() {
	        ErrorCode[] errors = getErrorCodes();
	        if(errors == null) {
	            return false;
	        }
	        for(ErrorCode error : errors) {
	            switch(error) {
	                case InvalidResponse:
	                case MissingResponse:
	                    return true;
	            }
	        }
	        return false;
	    }
	 
	    static enum ErrorCode {
	        MissingSecret,     InvalidSecret,
	        MissingResponse,   InvalidResponse;
	 
	        private static Map<String, ErrorCode> errorsMap = new HashMap<String, ErrorCode>(4);
	 
	        static {
	            errorsMap.put("missing-input-secret",   MissingSecret);
	            errorsMap.put("invalid-input-secret",   InvalidSecret);
	            errorsMap.put("missing-input-response", MissingResponse);
	            errorsMap.put("invalid-input-response", InvalidResponse);
	        }
	 
	        @JsonCreator
	        public static ErrorCode forValue(String value) {
	            return errorsMap.get(value.toLowerCase());
	        }
	    }

		public boolean isSuccess() {
			return success;
		}

		public void setSuccess(boolean success) {
			this.success = success;
		}

		public String getChallengeTs() {
			return challengeTs;
		}

		public void setChallengeTs(String challengeTs) {
			this.challengeTs = challengeTs;
		}

		public String getHostname() {
			return hostname;
		}

		public void setHostname(String hostname) {
			this.hostname = hostname;
		}

		public ErrorCode[] getErrorCodes() {
			return errorCodes;
		}

		public void setErrorCodes(ErrorCode[] errorCodes) {
			this.errorCodes = errorCodes;
		}
	     
}

Powyższe fragmenty kodu są też zawarte w projekcie Clinic (clinic-server, clinic-client) na GitHub >>tutaj<<

Wstęp — czym jest steganografia?

Ciągle postępująca informatyzacja społeczeństwa sprawiła, że coraz większa część naszego życia jest związana z globalnym przesyłem danych przez sieć internetową. Internet stał się istotnym medium komunikacyjnym, wykorzystywanym nie tylko na polu prywatnym, ale również w kontaktach służbowych lub oficjalnych sprawach urzędowych. W zaistniałej sytuacji głównym priorytetem stało się bezpieczeństwo udostępnianych treści. Konieczność ograniczenia grona odbiorców przesyłanych treści poprzez wprowadzenie elementu identyfikacji naszej tożsamości wpłynęła na powszechność stosowania kryptografii — dziedziny dbającej o szyfrowanie danych do postaci niezrozumiałej dla osób niepowołanych. Skuteczność ochrony udostępnianych informacji zależy więc od algorytmu szyfrowania.

Steganografia w odróżnieniu od kryptografii obejmuje obszar ukrywania danych w taki sposób, aby uniknąć podejrzeń, że jakiekolwiek informacje są ukryte. Głównym elementem zabezpieczenia tajnej wiadomości jest zachowanie w tajemnicy samego faktu jej istnienia.To sprawia, że steganografia nadaje się do zadań, w których nie jest wykorzystywane szyfrowanie, na przykład oznaczanie praw autorskich. Samo dodanie do pliku informacji o prawach autorskich może być łatwo usunięte. Dopiero osadzenie tych danych w treści pliku utrudnia ich identyfikację i usunięcie.

Samo hasło “steganografia” wywodzi się z języka greckiego i jest połączeniem słów steganos, czyli potajemny, ukryty oraz grapho – piszę, rysuję.

Steganografia to dziedzina nauki zajmująca się przeprowadzeniem komunikacji w taki sposób, aby fakt istnienia przekazywanej wiadomości był niemożliwy do wykrycia przez postronnego obserwatora [1].

Techniki steganograficzne były stosowane już w starożytności. W czasie wojen zdarzało się, że poufne informacje przekazywano na drewnianych tabliczkach, pokrytych następnie woskiem. Samo pojęcie steganografii nie jest więc niczym nowym, jednak ciągły rozwój technologii informatycznych pozwala na rozszerzenie sposobów jej zastosowania. Niezliczona ilość współistniejących ze sobą treści multimedialnych w globalnej sieci internetowej, daje ogromny potencjał ukrywania informacji w publicznie dostępnych plikach, nie wzbudzając przy tym podejrzeń. Wykorzystanie plików graficznych lub dźwiękowych jako nośniki danych do zamaskowania tajnych informacji jest jedną z najpopularniej stosowanych metod. Steganografia nie ogranicza się tylko do plików cyfrowych, ale daje również możliwość utworzenia ukrytych kanałów komunikacyjnych w protokołach sieciowych lub kanałów podprogowych w algorytmach stosowanych do podpisu cyfrowego. Różnorodność sposobów stosowania steganografii nie narzuca stałych reguł działania według schematów, ale pozwala na kreatywne modyfikowanie oraz udoskonalanie algorytmów pod kątem rozmiaru ukrywanych danych, trudności ich wykrycia lub trwałości po wprowadzeniu modyfikacji.

Wzrost znaczenie steganografii wpłynął na rozwój technik pokrewnych takich jak stosowanie znaków wodnych w plikach cyfrowych do oznaczenia praw autorskich. Znaki wodne (ang. Watermarking) są powszechnie spotykane na zdjęciach lub w plikach muzycznych. Mogą znajdować się w widocznym dla odbiorcy miejscu i jasno informować o autorze danego dzieła albo być ukryte w strukturze wewnętrznej pliku i pełnić funkcję niewidzialnego „odcisku palca”. Zamieszczenie w taki sposób numerów seryjnych lub innego zbioru cech odróżniających kopię od oryginału, pozwala wykryć osoby łamiące prawa autorskie.

Masowy przepływ cyfrowych informacji przez Internet dodatkowo wpływa na trudność w wychwyceniu i sklasyfikowaniu konkretnych działań jako świadome zatajanie danych. Dlatego steganografia bywa wykorzystywana przez agentów tajnych służb lub grupy przestępcze. Istnieje podejrzenie, że steganografia pomaga również w komunikacji terrorystów [2]. Uprawnione organizacje, czuwające nad bezpieczeństwem, mają duże powodzenie odszyfrowania przechwyconych danych kryptograficznych, jednak wychwycenie potajemnej komunikacji w gąszczu wymienianych informacji cyfrowych w sieci, wcale nie jest zadaniem trywialnym. W 2001 r. Uniwersytet w Michigan przeprowadził badanie na popularnym serwisie aukcyjnym eBay, gdzie sprawdzono ponad 2 mln plików graficznych. Ponad 17 tys. z nich uznano za podejrzane pod względem zastosowania steganografii.

Steganografia zapewnia poufność i integralność danych przy jednoczesnej ich dostępności. Pliki mogą znajdować się w kanale otwartym jak na przykład forum internetowe, ale jednocześnie dostęp do sekretnych informacji i możliwość ich modyfikacji mają tylko wybrani. Negatywnym aspektem stosowania takiej metody jest fakt, że informację może odczytać każdy, kto o niej wie i zna algorytm ukrywania danych. Problem ten można jednak rozwiązać, szyfrując wiadomość przed jej osadzeniem. Jeśli ktoś odnajdzie steganogram, nie będzie w stanie go odczytać. Z drugiej strony, jeśli ktoś chociażby podejrzewa użycie steganografii, to może łatwo zniszczyć ukrytą informację i nie dopuścić do jej odczytania przez odbiorcę.

Rozwój technologiczny znacząco wpłynął na rozbudowę dziedziny steganografii. Jest to nauka, która zdecydowanie ma przed sobą potencjał na dalsze poszerzanie zakresu działania wraz z wprowadzeniem nowych rozwiązań informatycznych.


Bibliografia

  1. C. Cachin, An information-theoretic model for steganography w Aucsmith D.(eds) Information Hiding. Springer, Berlin, Heidelberg, 2th edition, November 1998
  2. L. Grochowski, B. Hołyst, Steganografia a zagrożenia cyberterrorystyczne.