Kirjautuminen

Haku

Tehtävät

Keskustelu: Nettisivujen teko: Verkkosivut ja liitteet PHP

Sivun loppuun

verkko2022 [02.03.2022 16:50:25]

#

PHP/html

Olen tehnyt html-kielellä ensimmäisen verkkosivuni. Kaikki toimii, mutta yksi asia aiheuttaa ongelmia, mihin en ole löytänyt ratkaisua mistään.

Sivulleni on mahdollista kirjautua, jolloin on mahdollista käydä lukemassa pdf-dokumentteja. Vain kirjautumalla voit päästä näkemään osoitteen, missä pdf-dokumentti on. Leikitään ajatuksella, että en antaisi henkilölle A enää mahdollisuutta kirjauta sivulleni, niin se ei estäisi häntä pääsemästä käsiksi tuohon dokumenttiin, jos muistaa sen osoitteen. Miten siis voin suojata asiakirjat, jotta vain kirjautuneena niihin voi päästä käsiksi? En ole vielä hyvä tässä, joten toivon yksinkertaista neuvoa, jos sellainen on olemassa. Kiittäen.

PS. Tärkein on pdf, mutta toki käytän muitakin... jpg, jne.....

Grez [02.03.2022 16:55:57]

#

Sinänsä toki asialla on lienee vain marginaalinen merkitys, sillä käyttäjäthän voi joka tapauksessa ladata pdf:t, jpg:t sun muut omalle koneelleen.

Mutta siis...

verkko2022 kirjoitti:

Miten siis voin suojata asiakirjat, jotta vain kirjautuneena niihin voi päästä käsiksi? En ole vielä hyvä tässä, joten toivon yksinkertaista neuvoa, jos sellainen on olemassa. Kiittäen.

Kun ei tiedä yhtään millainen kirjautumissysteemi siellä on, niin tähän on vähän vaikea vastata.

verkko2022 [02.03.2022 18:36:43]

#

Hei, asia on kyllä tärkeä ja uskoisin tällaisen mahdollisuuden olevan olemassa?

Kirjautuminen tapahtuu lomakkeella .html, joka johdattaa eteenpäin .php

<?php

if (isset($_POST['name']) and ($_POST['pass'] ))
{
    if ($_POST['name'] == 'nimi' and $_POST['pass'] == '123')
         {include("osa1.php");
        include("osa2.php");
        }

Tämän jälkeen myöhemmin sivu johdattaa linkkiin ja linkistä .pdf tiedostoon.

Metabolix [04.03.2022 10:15:39]

#

Ensinnäkin, pelkästään osoitteeseen perustuva kirjautuminen ei ole turvallinen. Esimerkiksi jos tuossa käyttäjä kirjoittaisi osoitteeksi osa1.php, hän pääsisi kyseiseen osaan sivua ilman kirjautumista.

Yleensä kirjautumiseen käytetään evästeitä. PHP:ssä helpoin on istuntojen käyttö:

<?php
// kirjaudu.php
session_start();
if (@$_POST["name"] !== "nimi" || @$_POST["pass"] !== "123") {
  http_response_code(403);
  die("Kirjautuminen ei onnistunut!");
}

// Kirjautuminen onnistui, merkitään se istuntoon.
$_SESSION["kirjautunut"] = $_POST["name"];
header("Location: salaiset-sivut.php");
<?php
// salaiset-sivut.php
session_start();
if (empty($_SESSION["kirjautunut"])) {
  http_response_code(403);
  die("Pääsy kielletty! Mene <a href='/'>etusivulle</a> kirjautumaan.");
}

// Kirjautuminen on voimassa, tähän voi kirjoittaa salaisen sivun sisällön.
echo "Onneksi olkoon, olet kirjautunut salaisille sivuille!";

Tästä päästään tiedostojen suojaamiseen. Et voi estää PHP:llä sellaisten tiedostojen lataamista, joita PHP ei käsittele. Tietysti palvelimeen (Apache tms.) voi tehdä rajoituksia, mutta näiden ylläpito ja varsinkin siirto uudelle palvelimelle on vaivalloisempaa. Yleensä ratkaisu on se, että suojattavan tiedoston osoite onkin esimerkiksi lataa.php?tiedosto=salainen.txt, minkä jälkeen lataa.php voi toimia tähän tyyliin:

<?php
session_start();
if (empty($_SESSION["kirjautunut"])) {
  http_response_code(403);
  die("Pääsy kielletty! Mene etusivulle kirjautumaan.");
}

$salapolku = "../salaiset-kansiot";
// Määrätyt tiedostot:
$sallitut_tiedostot = ["salainen.txt"];
// Tai koko salakansion sisältö:
$sallitut_tiedostot = array_map("basename", glob($salapolku . "/*.*"));

$tiedosto = $_POST["tiedosto"] ?? "";
if (!in_array($tiedosto, $sallitut_tiedostot)) {
  http_response_code(404);
  die("Tiedostoa ei löydy.");
}

$polku = $salapolku . "/" . $tiedosto;

// TODO: Tunnista tiedostonimen pääte, ilmoita oikea tyyppi.
header("Content-Type: application/octet-stream");
header("Content-Disposition: attachment; filename=" . $tiedosto);
header("Content-Length: " . filesize($polku));
readfile($polku);

Tietysti salaiset tiedostot pitää myös laittaa niin, ettei PHP:tä voi ohittaa. Turvallisinta on laittaa nämä johonkin varsinaisten nettisivujen ulkopuolelle, eli jos sivujen polku on /var/www/public_html, niin salaisten tiedostojen paikka on vaikka /var/www/salaiset-kansiot.

Salasanan turvallisemmasta käsittelystä katso vinkki password-funktioiden käytöstä.

verkko2022 [04.03.2022 11:15:49]

#

Tarkoittaako esimerkkisi sitä, että kirjautuneena pääsee tuohon .txt tiedostoon, mutta sen ulkopuolelta ei pääse, vaikka tietäisikin oikean polun?

Metabolix [04.03.2022 11:41:26]

#

verkko2022 kirjoitti:

Tarkoittaako esimerkkisi sitä, että kirjautuneena pääsee tuohon .txt tiedostoon, mutta sen ulkopuolelta ei pääse, vaikka tietäisikin oikean polun?

Kuten sanoin, salaiset tiedostot pitää laittaa nettisivujen ulkopuolelle. Kun pidät palvelinta, kyllä sinun pitää tietää, mitä tiedostoja se palvelin jakaa. Jos palvelin jakaa kaikki tiedostot polusta /var/www, niin silloin sinne ei pidä laittaa mitään salaisia tiedostoja. Jos palvelin jakaa tiedostot polusta /var/www/public_html, niin silloin /var/www/salaiset-kansiot on turvassa.

Tai toisin sanoen: jos on olemassa sellainen nettiosoite (kuten https://example.com/tiedosto.txt), jolla tiedostoon pääsee käsiksi, niin silloin tietenkin siihen pääsee myös ilman kirjautumista. Tiedostot pitää laittaa paikkaan, jolle ei ole olemassa nettiosoitetta.

verkko2022 [04.03.2022 12:24:20]

#

Kävin koodiasi läpi ja kokeilin sitä. Ohjelma haki tuon .txt sivun sisällön, mutta ei avannut itse sivua näytölle. Esimerkkinä jos tiedosto olisi esimerkki.pdf, niin selaimella sivu näkyisi normaalisti, mutta tässä tapauksessa ei.

Eikö tämä toimi kuten:

$polku='xxxxxxx';
$lines_string=file_get_contents($polku);
echo htmlspecialchars($lines_string);

Metabolix [04.03.2022 13:38:22]

#

Kuten koodin kommentissa lukee, sitä pitäisi täydentää tunnistamalla tiedostopääte ja tarjoamalla se oikeassa muodossa kuten image/jpeg, text/plain jne. Tämän lisäksi, jos haluat näyttää tiedoston selaimessa, ota Content-Disposition-rivi pois.

Tiedoston lukeminen ja näyttö htmlspecialcharsin kanssa ei tuota ollenkaan samaa lopputulosta oikeastaan mistään näkökulmasta. Tekstitiedoston sisältöä voi saada sillä kyllä näkyviin, mutta siitäkin häviää mm. rivitys.

verkko2022 [04.03.2022 13:47:00]

#

Hei, nyt sain pdf-tiedoston näkymään hyvällä tavalla:-)

echo "<iframe src=\"file.pdf\" width=\"100%\" style=\"height:100%\"></iframe>";

Metabolix [04.03.2022 13:52:47]

#

verkko2022 kirjoitti:

Hei, nyt sain pdf-tiedoston näkymään hyvällä tavalla:-)

Hieno homma, mutta iframella tehtynä tuossa ei ole minkäänlaista suojausta, vaan osoitteella file.pdf kuka tahansa pystyy lukemaan sen.

Jos puuttuu perusymmärrys nettisivujen toiminnasta (kuten mitä iframe tekee), ehkä kannattaa (a) hyväksyä, että tiedostoja ei ole suojattu, tai (b) etsiä jostain valmis ohjelmisto, jossa on tarpeelliset ominaisuudet kirjautumiseen ja tiedostojen käsittelyyn.

Sinänsä, kuten Grez alussa sanoi, käyttäjä voi joka tapauksessa tallentaa tiedoston ja jakaa sitä sitten muualla, joten kirjautumisen merkitys on siinä mielessä aika pieni.

verkko2022 [04.03.2022 14:00:42]

#

Nyt ei sentään osoite lue suoraan osoitekentässä..
Kiitos kuitenkin, mutta jatkan yrittämistä. Sen osaan tehdä, että dokumenttia ei saa auki, vaikka osoitteen tietäisikin. Jotenkin vain pitäisi keksiä, miten luvan voisi antaa kirjautuneelle.

Metabolix [04.03.2022 14:22:02]

#

verkko2022 kirjoitti:

Jotenkin vain pitäisi keksiä, miten luvan voisi antaa kirjautuneelle.

Niin no tähän on jo vastauksia: (a) Käytä pelkkää htaccessia ilman PHP:tä, kuten toisessa keskustelussa vastattiin. (b) Tarjoile tiedosto PHP:llä, kuten yllä. Netistä löytyy listaa oikeista MIME-tyypeistä. Voit soveltaa edellä olevaan koodiin oikean Content-Typen valintaa vaikka näin:

$mimelista = [
  ".txt" => "text/plain; charset=UTF-8",
  ".png" => "image/png",
  ".jpg" => "image/jpeg",
  ".pdf" => "application/pdf",
  "" => "application/octet-stream"
];
foreach ($mimelista as $pääte => $mime) {
  if (str_ends_with($tiedosto, $pääte)) {
    header("Content-Type: $mime");
  }
}

verkko2022 [04.03.2022 14:40:16]

#

Tuli vielä sellainen mieleen, että onko mahdollista:

-Kun sivulle kirjautuu, niin ohjelma luo välikaisen kansion minne kopioituu haluttuja tiedostoja, mitä voi käyttää sitten niin kauan kun pysyy kirjautuneena.

Grez [04.03.2022 14:55:01]

#

Tottakai se on mahdollista.

Ja siihen olennaisempaan, kysymättä jääneeseen, kysymykseen voisi vastata: Ei, siinä ei olisi mitään järkeä.

Metabolix [04.03.2022 15:06:34]

#

Ennen uusien purkkaviritelmien keksimistä kannattaisi tutkia tämä jo tarjottu ratkaisu perusteellisesti ja selittää, mikä siinä on omasta mielestä vikana eli miksi tarvitsee miettiä muita ideoita.

Tiedostojen kopiointi on helppoa, mutta käyttäjän poistumisesta ei tule mitään ilmoitusta, joten poistaminen vaatii suunnittelua ja järjestelyä.

Astetta yksinkertaisempi purkkaviritelmä olisi sellainen, jossa kopioidaan yksi tiedosto kerrallaan ja poistetaan yli minuutin vanhat tiedostot. Kopioinnin sijaan voi tietysti käyttää vaikka symbolisia linkkejä, ettei turhaan rassata kovalevyä.

Eli tyyliin:

<?php
// $tiedosto = $_POST["tiedosto"] ja sallittujen tiedostojen rajaus kuten edellä.
$tiedosto = "salainen.pdf";

@mkdir("kopiot");
$kopio = bin2hex(random_bytes(16)) . "-" . $tiedosto;
shell_exec("find kopiot -type l,f -mmin +5 -delete");
symlink("salaiset/".$tiedosto, "kopiot/".$kopio);
header("Location: kopiot/".$kopio);

Alkuperäiseen ehdottamaani PHP-ratkaisuun nähden tässä on taas uusia virheen mahdollisuuksia, ja viimeinen tiedosto jää kaikkien ladattavaksi, kunnes PHP-skripti ajetaan seuraavan kerran.

mpni [04.03.2022 16:03:07]

#

Kannattaa huomata, että pdf-dokumentteja on myös mahdollista salata:
https://helpx.adobe.com/fi/acrobat/using/securing-pdfs-passwords.html

Yksi vaihtoehto on siis vain suojata dokumenttien avauksen salasanaa. Salasana voisi olla tarjolla ainoastaan onnistuneesti kirjautuneille käyttäjille. Pdf-suojauksen purkaminen ilman salasanaa on sitten toki ihan oma lukunsa. Kuvia voi puolestaan salata pakkaamalla salattuun zip-pakettiin.

muuskanuikku [05.03.2022 12:14:29]

#

verkko2022 kirjoitti:

Tuli vielä sellainen mieleen, että onko mahdollista:

-Kun sivulle kirjautuu, niin ohjelma luo välikaisen kansion minne kopioituu haluttuja tiedostoja, mitä voi käyttää sitten niin kauan kun pysyy kirjautuneena.

Kannattaisi opetella ohjelmoimaan sillä tavoin, että nettiselaimessa näkyvällä urlilla ei ole mitään tekemistä palvelimella sijaitsevien tiedostojen "järjestykseen". Tämä pätee niin PHP-sovelluksen koodiin kuin myös näihin ladattaviin tiedostoihin.

Tarkoitan siis sitä, että jos käyttäjä on surffannut osoitteeseen "www.munsivut.fi/pelit/lepakkoluola.php", niin palvelimella ei kuitenkaan ole levyllä sellaista hakemistoa kuin "pelit" eikä siellä tiedostoa "lepakkoluola.php", vaan sovellus käyttää omaa sisäistä logiikkaansa suorittaakseen oikean toiminnon tiettyyn www-osoitteeseen siirtyessä.

Samoin ladattavien tiedostojen kanssa sinun pitäisi ennemmin kirjoittaa tietokantaan lista osoitteista, jotka linkittävät käyttäjän yhteen levyllä sijaitsevaan tiedostoon. Tiedostojen kopiointi on tyhmää, ns. linkkien käyttö paljon fiksumpaa.

Linkkilista voisi siis näyttää esimerkiksi tältä:

/kuvat/salaiset/pekka/koira.jpeg -> /srv/files/photos/dog.jpeg
/kuvat/salaiset/nappe/koira.jpeg -> /srv/files/photos/dog.jpeg

Ja nyt aina kun käyttäjä navigoi osoitteeseen "/kuvat/salaiset/nappe/koira.jpeg", niin sen sijaan että levyllä on oikeasti tuollainen tiedostopolku olemassa, niin sovellus tietää että sen pitääkin lukea data sijainnista "/srv/files/photos/dog.jpeg".

verkko2022 [06.03.2022 22:52:16]

#

Kiitos kaikille, sain tämän toimimaan:-)


Sivun alkuun

Vastaus

Aihe on jo aika vanha, joten et voi enää vastata siihen.

Tietoa sivustosta