Uzyskanie lokalizacji skrótu adresu URL i użycie go w jQuery

135

Chciałbym uzyskać wartość po krzyżyku w adresie URL bieżącej strony, a następnie móc zastosować ją w nowej funkcji ... np.

Może to być adres URL

www.example.com/index.html#foo

Chciałbym tego użyć w połączeniu z następującym fragmentem kodu

$('ul#foo:first').show();

Zakładam / mam nadzieję, że jest jakiś sposób na złapanie tego i przekształcenie w zmienną, której mogę następnie użyć w drugim fragmencie kodu.

Robbie White
źródło
8
Nie mam dla ciebie żadnego kodu, ale powinieneś upewnić się, że wyczyściłeś dane wejściowe, ponieważ wydaje się, że jest gotowy do wstrzyknięcia kodu.
Nate B
Zrozumienie, że to pytanie ma prawie dekadę, 'ul#foo:first'nie ma sensu, ponieważ identyfikatory muszą być unikalne, dlatego dodawanie :firstdo selektora jest zbędne, chyba że powielasz identyfikatory, które są nieprawidłowe. Zwróć uwagę, że nawet dziesięć lat temu powtarzane identyfikatory były nadal nieprawidłowe.
j08691
Dziesięć lat temu nadal się myliłem
Douglas,

Odpowiedzi:

280

Uwaga edytora: poniższe podejście ma poważne konsekwencje dla bezpieczeństwa i, w zależności od używanej wersji jQuery, może narazić użytkowników na ataki XSS. Aby uzyskać więcej informacji, zapoznaj się z omówieniem możliwego ataku w komentarzach do tej odpowiedzi lub w tym wyjaśnieniu dotyczącym programu Security Stack Exchange .

Możesz użyć tej location.hashwłaściwości, aby pobrać hash bieżącej strony:

var hash = window.location.hash;
$('ul'+hash+':first').show();

Zauważ, że ta właściwość zawiera już #symbol na początku.

Właściwie nie potrzebujesz :firstpseudo-selektora, ponieważ używasz selektora ID , zakłada się, że identyfikatory są unikalne w ramach DOM.

W przypadku, gdy chcesz uzyskać hash z ciągu adresu URL, możesz użyć String.substringmetody:

var url = "http://example.com/file.htm#foo";
var hash = url.substring(url.indexOf('#')); // '#foo'

Rada: pamiętaj, że użytkownik może zmienić hash, jak chce, wstrzykując cokolwiek do twojego selektora, powinieneś sprawdzić hash przed jego użyciem.

CMS
źródło
30
Zauważ, że selektory jQuery mogą być używane do wykonywania niestandardowego kodu javascript, więc używanie nieanityzowanych skrótów jest strasznie, strasznie niepewne. W ostatnich wersjach jQuery jest na to niewielka poprawka dla selektorów, które zawierają znak # przed wstrzykniętym kodem, ale nadal istnieje ryzyko, jeśli usuniesz znak # z początku lokalizacji.hash. E. g. var hash = location.hash.slice(1); $('ul.item'+hash).show().append($('#content'));spowoduje to wykonanie tagu skryptu umieszczonego w hashu. Lepiej jest używać $('body').find('ul'+hash+':first')zamiast $('ul'+hash+':first').
Tgr
40
Niektóre przeglądarki zwracają symbol krzyżyka, a inne nie, więc bezpieczniej jest używać:var hash = location.hash.replace('#', '');
Tim
12
Alice prowadzi witrynę internetową, Bob ją odwiedza, uwierzytelnia i otrzymuje sesyjny plik cookie. (Może minąć trochę czasu, Bob może nawet zamknąć przeglądarkę). Charlie wysyła do Boba wiadomość z napisem „sprawdź ten fajny link!”. Bob otwiera link, który prowadzi do witryny kontrolowanej przez Charliego. Strona przekierowuje przeglądarkę Boba na stronę w witrynie Alicji z ładunkiem ataku w hashu. Ładunek jest wykonywany, a ponieważ przeglądarka nadal pamięta pliki cookie, może po prostu wysłać je do Charliego.
Tgr,
2
@Tgr, dziękuję za rozwinięcie i połączenie kropek. Ten konkretny przykład sprawia, że ​​ja (i miejmy nadzieję, że inni) bardziej skłaniam się do czujności w zapewnianiu bezpieczeństwa.
snapfractalpop
2
@buffer: $(userInput)jest ogólnie niebezpieczny, ponieważ $jest przeciążony i może albo wyszukiwać istniejące węzły, albo tworzyć nowe w zależności od tego, czy ciąg zawiera <>znaki. $(document).find(userInput)będzie zawsze szukać istniejących węzłów, więc jest to mniej niebezpieczne. Mimo to najlepszą praktyką jest zawsze oczyszczanie danych wejściowych użytkownika, np. Jeśli używasz identyfikatorów alfanumerycznych, upewnij się, że są one alfanumeryczne.
Tgr
35

location.hash nie jest bezpieczny dla IE , w przypadku IE (w tym IE9), jeśli Twoja strona zawiera iframe, to po ręcznym odświeżeniu wewnątrz treści iframe uzyskaj wartość location.hash jest stara (wartość dla pierwszej strony załadowanej). podczas gdy ręcznie pobierana wartość różni się od location.hash, więc zawsze pobieraj ją za pośrednictwem document.URL

var hash = document.URL.substr(document.URL.indexOf('#')+1) 
Deepak Patil
źródło
7
Aktualizacja: document.URL nie zawiera wartości skrótu w przeglądarce Firefox 3.6, więc location.href jest bezpieczny var hash = location.href.substr (location.href.indexOf ('#') + 1)
Deepak Patil
4

Dla tych, którzy szukają czystego rozwiązania javascript

 document.getElementById(location.hash.substring(1)).style.display = 'block'

Mam nadzieję, że zaoszczędzi ci to trochę czasu.

Matas Vaitkevicius
źródło
3

Od wersji jQuery 1.9 :targetselektor będzie pasował do skrótu adresu URL. Więc możesz zrobić:

$(":target").show(); // or $("ul:target").show();

Który wybrałby element z identyfikatorem pasującym do skrótu i ​​pokazałby go.

j08691
źródło
czy istnieje sposób na wyodrębnienie skrótu jako ciągu zamiast identyfikatora dopasowania?
ina
@ina Czy masz na myśli pobrać hash z jQuery :targetjako ciąg? Jeśli tak, to nie sądzę.
j08691
1

Sugerowałbym najpierw lepiej cek, jeśli bieżąca strona ma hash. W przeciwnym razie tak będzie undefined.

$(window).on('load', function(){        
    if( location.hash && location.hash.length ) {
       var hash = decodeURIComponent(location.hash.substr(1));
       $('ul'+hash+':first').show();;
    }       
});
Chetabahana
źródło
1

Używam tego, aby rozwiązać wpływ na bezpieczeństwo odnotowany w odpowiedzi @ CMS.

// example 1: www.example.com/index.html#foo

// load correct subpage from URL hash if it exists
$(window).on('load', function () {
    var hash = window.location.hash;
    if (hash) {
        hash = hash.replace('#',''); // strip the # at the beginning of the string
        hash = hash.replace(/([^a-z0-9]+)/gi, '-'); // strip all non-alphanumeric characters
        hash = '#' + hash; // hash now equals #foo with example 1

        // do stuff with hash
        $( 'ul' + hash + ':first' ).show();
        // etc...
    }
});
squarecandy
źródło