Kirjautuminen

Haku

Tehtävät

Keskustelu: Ohjelmointikysymykset: JavaScript, PHP: Salasanan varmistaminen

Sivun loppuun

Macro [10.07.2011 16:04:46]

#

Moro

Nettimateriaalin perusteella kasasin lausekkeen, jonka pitäisi tarkistaa salasanan kelpoisuus.

/([a-z]+)([A-Z]+)([0-9]+)([`~!@#$%^&\*()\ \_\+\-=\{\}\|\\\:\";\'<>\?,\.]+)/

Tämän pitäisi vaatia, että salasanassa on vähintään yksi pieni kirjain, yksi iso kirjain, yksi numero ja yksi erikoismerkki. Jostain syystä läpi ei mene esimerkiksi aA1!gf54# tai vastaavat.

Mimmoista korjausta tuohon pitäisi laittaa? Pituus tarkistetaan erikseen.

Käytän sitä formin kentän onblur-tapahtumasta seuraavasti

function checkPW() {
    if(document.forms["rekisteroidy"].elements["salasana1"].value.length == 0)
        return;

    var re = new RegExp('/([a-z]+)([A-Z]+)([0-9]+)([`~!@#$%^&\*()\ \_\+\-=\{\}\|\\\:";\'<>\?,\.]+)/');
    if(document.forms["rekisteroidy"].elements["salasana1"].value.match(re) && document.forms["rekisteroidy"].elements["salasana1"].value.length > 7)
        document.getElementById("salasanahint2").innerHTML = "Salasana on tarpeeksi vahva";
    else
        document.getElementById("salasanahint2").innerHTML = "<span class=\"nomatch\">Salasana on liian heikko.</span>";
}

Kun teen saman PHP:llä, niin tarkastus toimii oikein.

<?php
$salasana = "aA1!gf54#";

if(preg_match('/([a-z]+)([A-Z]+)([0-9]+)([`~!@#$%^&\*()\ \_\+\-=\{\}\|\\\:";\'<>\?,\.]+)/', "aA1!gf54#") && strlen($salasana) >= 8)
    echo "true";
else
    echo "false";
?>

Teuro [10.07.2011 16:09:53]

#

Kyllä mulla ainakin tuo sinun esimerkkisi 'aA1!' menee läpi, mutta mikään muu järjestys ei kelpaa, koska vaadit, että ensin tulee pieni aakkonen sitten iso aakkonen, seuraavaksi numero ja lopuksi erikoismerkki. Säännöllinen lauseke ei välttämättä sovellu erityisen hyvin tuohon tehtävään.

Macro [10.07.2011 16:12:48]

#

Muokkasin hiukan tuota aloitusviestiäni.

Mimmoinen tarkistus olisi parempi tuohon tehtävään samoilla vaatimuksilla? Onhan näitä kaikenmaailman virityksiä netti pullollaan, kiinnostaisi vaan tehdä tähän työhön se itse, jottei toisen materiaalia joudu käyttämään.

Teuro [10.07.2011 16:33:30]

#

No jotakin tällaista voisi kokeilla? Mutta sitten se ei ole kyllä sun kirjoittamaa :)

<DOCTYPE html>
<html>
	<head>
		<title>Salasanan testaus</title>
		<script type="text/javascript">
			function tarkista(teksti) {
				if (teksti.match(/[a-z]/)) {
					document.getElementById("pienaakkonen").style.color="green";
				} else {
					document.getElementById("pienaakkonen").style.color="red";
				}

				if (teksti.match(/[A-Z]/)) {
					document.getElementById("suuraakkonen").style.color="green";
				} else {
					document.getElementById("suuraakkonen").style.color="red";
				}

				if (teksti.match(/[0-9]/)) {
					document.getElementById("numeraali").style.color="green";
				} else {
					document.getElementById("numeraali").style.color="red";
				}

				if (teksti.match(/[#%&_?*+]/)) {
					document.getElementById("erikois").style.color="green";
				} else {
					document.getElementById("erikois").style.color="red";
				}

				if (teksti.length > 8) {
					document.getElementById("pituus").style.color="green";
				} else {
					document.getElementById("pituus").style.color="red";
				}
			}
		</script>
	</head>
	<body>
		<input type="text" onKeyUp="tarkista(this.value)" />

		<ul>
			<li id="pienaakkonen" style="color: red;">a-z</li>
			<li id="suuraakkonen" style="color: red;">A-Z</li>
			<li id="numeraali" style="color: red;">0-9</li>
			<li id="erikois" style="color: red;">#%&_?*+</li>
			<li id="pituus" style="color: red;">Pituus enemmän kuin 8-merkkiä</li>
		</ul>
	</body>
</html>

-tossu- [10.07.2011 16:36:29]

#

Voi olla, että JavaScriptissä on valmis funktio, joilla tarkistus hoituu kätevästi, mutta tämä ainakin toimii:

function salasanaKelpaa (teksti, merkit) {
	for (i = 0; i < merkit.length; i++) {
		eiloydy = true;
		for (j = 0; j < merkit [i].length; j++) {
			if (teksti.indexOf (merkit [i].charAt (j)) != -1) {
				eiloydy = false;
				break;
			}
		}
		if (eiloydy)
			return false;
	}
	return true;
}

alert (salasanaKelpaa ("foo#bar1", ["%&#/", "0123456789"]));

Funktiolle annetaan parametriksi salasana sekä merkkiryhmät. Funktio palauttaa true, jos salasanassa on ainakin yksi merkki jokaisesta ryhmästä.

Edit: Jos et halua käyttää toisten antamaa koodia, miten sinua sitten pitäisi auttaa?

Macro [10.07.2011 16:51:33]

#

Kiitos Teurolle, noin se alkoi toimia kun paloittelin kyselyn paloihin. Samalla keksin tuon matchin, tuo RegExp olisi ollut hankalampi noin monessa tarkistuksessa.

Juu, ei ole mun kirjoittamaa, mutta teinkin siitä oman versioni.

function checkPW() {
    salasana = document.forms["rekisteroidy"].elements["salasana1"].value;
    if(salasana.match("/[a-z]/") && salasana.match("/[A-Z]/") && salasana.match("/[0-9]/") && salasana.match("/[`~!@#$%^&\*()\ \_\+\-=\{\}\|\\\:\";\'<>\?,\.]/") && salasana.length >= 8)
        document.getElementById("salasanahint2").innerHTML = "<span class=\"match\">Salasana on tarpeeksi vahva.</span>";
    else
        document.getElementById("salasanahint2").innerHTML = "<span class=\"nomatch\">Salasana on liian heikko.</span>";
}

-tossu-, voihan sitä oppia korjaamaan ongelmansa ilman toisen koodia. Ei yhtään copy-paste-riviä Teuron koodista, vain ajatus, että tarkistukset pitää tehdä erikseen.

Teuro [10.07.2011 16:53:56]

#

Macro: Ei toimi noin, koska nyt riittää, että mikä tahansa ehto toteutuu.

Macro [10.07.2011 16:56:14]

#

Muokataan sitten tai-ehdot ja-ehdoiksi (Korjasin ylös). Kiitos vinkistä, jäi nuo kun tarkistus oli alunperin toisinpäin.

-tossu- [10.07.2011 17:11:25]

#

Oletko testannut tuota koodia? RegExpejä ei kuulu laittaa lainausmerkkien sisään, joten koodi ei toimi tuollaisena. Viimeisessä ehdossa ei edes ole ryhmittelyä, joten se toteutuu vain, jos salasanassa on kaikki merkit, ja ne ovat oikeassa järjestyksessä.

Macro [10.07.2011 17:26:29]

#

Tuota lainausmerkkijuttua en tiennyt, mutta kyllä minulla ainakin toimi tuo ihan tuollaisena. Korjaan ne sitten tuonne. Tekemällä oppii..

-tossu- [10.07.2011 17:38:17]

#

Mitä selainta käytät? Testasin Operan Dragonflyllä, eikä se ainakaan hyväksy lainausmerkeissä olevaa RegExpiä.

>>> "foo".match("/[a-z]/")
null
>>> "foo".match(/[a-z]/)
Array["f"]

Macro [10.07.2011 17:54:03]

#

Chromea käytän, eikä sen Scripts-konsoli (tai mikä lie debug-paneeli onkaan) näyttänyt virhettä siihen.

The Alchemist [10.07.2011 18:37:10]

#

Ei taida JS:ssä tulla regexit hipsuihin.

Antti Laaksonen [10.07.2011 18:49:46]

#

Macro kirjoitti:

Tämän pitäisi vaatia, että salasanassa on vähintään yksi pieni kirjain, yksi iso kirjain, yksi numero ja yksi erikoismerkki.

Tästä tulisi tosiaan hankala säännöllinen lauseke. Suunnilleen tällainen:

.*([0-9].*[a-z].*[A-Z].*[^0-9a-zA-Z]|[0-9].*[a-z].*[^0-9a-zA-Z].*[A-Z]|[0-9].*[A-Z].*[a-z].*[^0-9a-zA-Z]|[0-9].*[A-Z].*[^0-9a-zA-Z].*[a-z]|[0-9].*[^0-9a-zA-Z].*[a-z].*[A-Z]|[0-9].*[^0-9a-zA-Z].*[A-Z].*[a-z]|[a-z].*[0-9].*[A-Z].*[^0-9a-zA-Z]|[a-z].*[0-9].*[^0-9a-zA-Z].*[A-Z]|[a-z].*[A-Z].*[0-9].*[^0-9a-zA-Z]|[a-z].*[A-Z].*[^0-9a-zA-Z].*[0-9]|[a-z].*[^0-9a-zA-Z].*[0-9].*[A-Z]|[a-z].*[^0-9a-zA-Z].*[A-Z].*[0-9]|[A-Z].*[0-9].*[a-z].*[^0-9a-zA-Z]|[A-Z].*[0-9].*[^0-9a-zA-Z].*[a-z]|[A-Z].*[a-z].*[0-9].*[^0-9a-zA-Z]|[A-Z].*[a-z].*[^0-9a-zA-Z].*[0-9]|[A-Z].*[^0-9a-zA-Z].*[0-9].*[a-z]|[A-Z].*[^0-9a-zA-Z].*[a-z].*[0-9]|[^0-9a-zA-Z].*[0-9].*[a-z].*[A-Z]|[^0-9a-zA-Z].*[0-9].*[A-Z].*[a-z]|[^0-9a-zA-Z].*[a-z].*[0-9].*[A-Z]|[^0-9a-zA-Z].*[a-z].*[A-Z].*[0-9]|[^0-9a-zA-Z].*[A-Z].*[0-9].*[a-z]|[^0-9a-zA-Z].*[A-Z].*[a-z].*[0-9]).*

Lisätehtävänä voi miettiä lauseketta, joka varmistaa edellisten lisäksi, että salasanassa on ainakin kahdeksan kirjainta.

Metabolix [10.07.2011 20:08:07]

#

Kun nyt kuitenkin puhutaan JS:n säännöllisistä lausekkeista eikä tietojenkäsittelijöiden teoreettisista lausekkeista, homma hoituu helpomminkin:

/(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[^a-zA-Z0-9]).{8}/

Viimeinen .{8} lausekkeessa varmistaa merkkien vähimmäismäärän.

Macro [11.07.2011 10:18:31]

#

Joo, tuollainen pitkä lauseke on ehkä vähän turhaa, eikä tosta muista tunnin päästä mitä siinä tehdään. Metabolixin lauseke on vielä ihan hyvissä mitoissa.

Muuten, voikohan matchilla verrata muuttujaa muuttujaan, vai onko siihen omaa funktiotaan? Tarkoitus olisi verrata salasanaa käyttäjän antamiin muihin tietoihin, kuten oma nimi, tunnus, sähköpostiosoite ja asuinpaikka. Salasana ei saisi sisältää näitä. Kokeilin jo salasana.match(tunnus) jne, mutta tässä on pari ongelmaa. Saako tuo olla tuossa muodossa, ilman kauttaviivoja? Se ainakin tuottaa väärän tuloksen tyhjällä muuttujalla. /tunnus/ tuottaa väärän tuloksen (vertaa merkkijonoon "tunnus"), ja / + tunnus + / tekee jotain ihan muuta. Lueskelin Googlen kautta näitä juttuja, ja moni oli neuvonut laittamaan lausekkeen osat lainausmerkkeihin ja lisäämään sitten plussilla sen muuttujan sinne väliin. Jos muuttuja on tuossa tapauksessa tyhjä, niin lausekkeestahan tulee //. Onko se silloin validi säännöllinen lauseke, ei taida olla?

kinnala [11.07.2011 10:54:25]

#

W3schoolsissa on ihan hyvät referenssit noista JS:n metodeista. Tein tuon perusteella minuutissa sulle esimerkin

var username = "kinnala";
var password = "jeekinnala";
var pattern = new RegExp(username);

if(password.match(pattern)!=null)
        document.write("Password not valid.");
else
        document.write("Password OK!");

Ja jos haluat toiminnallisuuden myös tyhjällä muuttujalla, niin voit lisätä tuohon simppelin ehtolauseen.

Macro [11.07.2011 11:10:26]

#

Jep, kiitos tosta.

Macro [11.07.2011 14:32:24]

#

Mitenköhän muuten http-linkin varmistaminen onnistuisi? Koodivinkeistä löytyy jotain, mutta ne päästävät läpi ihan kummallisiakin osoitteita.

Hennkka [11.07.2011 14:37:48]

#

Filttereillä?

Macro [11.07.2011 16:43:17]

#

Selvä. Entäs Javascriptin puolella?

kinnala [12.07.2011 10:42:42]

#

Yksi keino on varmistaa sivun olemassaolo HTTP-kyselyllä. RegExpillä onnistuu tietysti URLin validointi, mutta se ei tietenkään takaa, että kyseinen sivu on oikeasti olemassa.

Antti Laaksonen [12.07.2011 11:17:34]

#

Minusta riittäisi katsoa, että osoitteen alussa on http://. Jos joku haluaa antaa väärän osoitteen, hän onnistuu siinä, vaikka olisi millainen tarkistus.

Yucca [12.07.2011 13:16:18]

#

Antti Laaksonen kirjoitti:

Minusta riittäisi katsoa, että osoitteen alussa on http://.

Eiköhän kuitenkin ole syytä sallia myös https://. Ja onko varmaa, että ftp:// ei koskaan tule kyseeseen?

Jos käyttäjältä kysytään URLia, kannattaa käyttää input-elementtiä, jossa on type=url. Jotkin uudet selainversiot osaavat jo tarkistaa, että sellaista vastaava syöte on muodollisesti oikea URL (myös kun Javascript ei ole käytössä). Vanhemmissa selaimissa määritteestä ei ole haittaa, koska ne toimivat ikään kuin määrite olisi type=text.

Sen lisäksi voi toki rakennella Javascriptillä tehtävän tarkistuksen. Mutta on hyvä huomata, että tällaiset asiat eivät ole ollenkaan niin triviaaleja kuin voisi luulla. Yleensä väärät negatiiviset (tarkistus hylkää URLin, joka on oikea) ovat isompi riski kuin väärät positiiviset.

lainaus:

Jos joku haluaa antaa väärän osoitteen, hän onnistuu siinä, vaikka olisi millainen tarkistus.

Aivan. Hän voi antaa muodollisesti moitteettoman URLin, joka myös toimii – mutta viittaa ties mihin sivuun, ei sellaiseen, jonka URL haluttaisiin. Tarkistusten mielekkyys on lähinnä siinä, että ne auttavat välttämään tahattomia käyttäjän virheitä.


Sivun alkuun

Vastaus

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

Tietoa sivustosta