2012-07-16 10 views
5

Mam aplikację internetową, która korzysta z formantu logowania asp.net. Ponadto używam również funkcji odzyskiwania hasła, aby użytkownicy mogli odzyskać swoje hasło. Po zakończeniu wprowadzania przez użytkownika danych szczegółowych w kontroli odzyskiwania, adres e-mail zawierający weryfikacyjny adres URL zostanie wysłany na adres e-mail użytkownika. Po kliknięciu adresu URL przekieruje użytkownika do UserProfile mojej aplikacji internetowej, która w środku pozwala użytkownikowi zmienić jego hasło.Nie pamiętam hasła Adres URL:

Problem polega na tym, że ustawiam regułę dostępu do UserProfile.aspx, aby odmawiać anonimowemu użytkownikowi, kiedy przekierowuję z adresu URL na stronę UserProfile.aspx, kieruje mnie to na stronę LoginPage (system rozpoznaje mnie jako anonimowy użytkownik).

Dlaczego tak jest? Czy istnieje gdziekolwiek, co mógłbym skierować na stronę userprofile po kliknięciu adresu URL (który zawiera wszystkie informacje o użytkowniku)?

URL wyglądać tak:

http://localhost:1039/Members/UserProfile.aspx?ID=56f74cc7-7680-4f1b-9207-0ab8dad63cad 

przypadku gdy ostatnia część adresu URL był rzeczywiście identyfikator użytkownika.

Oto kod dla userprofile aspx:

<asp:SqlDataSource ID="SqlDataSource1" runat="server" 
       ConnectionString="<%$ ConnectionStrings:ASPNETDBConnectionString1 %>" 
       SelectCommand="SELECT aspnet_Membership.Email, Details.CustName, Details.CustNum, Details.CustRole, Details.CustStatus, Details.PName, Details.PEmail, Details.PRole, Details.WedDate, aspnet_Users.UserName, Details.UserId FROM Details INNER JOIN aspnet_Membership ON Details.UserId = aspnet_Membership.UserId INNER JOIN aspnet_Users ON aspnet_Membership.UserId = aspnet_Users.UserId WHERE (Details.UserId = @UserId)" 


       UpdateCommand="update Details SET CustName = @CustName, CustNum = @CustNum, CustRole = @CustRole, CustStatus = @CustStatus, PName = @PName, PEmail = @PEmail, PRole = @PRole, WedDate = @WedDate WHERE [UserId] = @UserId 

          Update aspnet_Membership Set Email= @email WHERE [UserId] = @UserId" 

       DeleteCommand= "DELETE FROM Details WHERE UserId = @UserId;"> 

       <DeleteParameters> 
        <asp:ControlParameter ControlID="lblHidden" Name="UserId" PropertyName="Text" 
         Type="String" /> 
       </DeleteParameters> 

       <SelectParameters> 
        <asp:ControlParameter ControlID="lblHidden" Name="UserId" PropertyName="Text" /> 

       </SelectParameters> 

       <UpdateParameters> 
        <asp:Parameter Name="CustName" /> 
        <asp:Parameter Name="CustNum" /> 
        <asp:Parameter Name="CustRole" /> 
        <asp:Parameter Name="CustStatus" /> 
        <asp:Parameter Name="PName" /> 
        <asp:Parameter Name="PEmail" /> 
        <asp:Parameter Name="PRole" /> 
        <asp:Parameter Name="WedDate" /> 
        <asp:Parameter Name="UserId" /> 
        <asp:Parameter Name="email" /> 
       </UpdateParameters> 


      </asp:SqlDataSource> 
      <asp:DetailsView ID="DetailsView1" runat="server" AutoGenerateRows="False" 
       DataSourceID="SqlDataSource1" Height="50px" Width="125px"> 
       <Fields> 
        <asp:BoundField DataField="Email" HeaderText="Email" SortExpression="Email" /> 
        <asp:BoundField DataField="CustName" HeaderText="CustName" 
         SortExpression="CustName" /> 
        <asp:BoundField DataField="CustNum" HeaderText="CustNum" 
         SortExpression="CustNum" /> 
        <asp:BoundField DataField="CustRole" HeaderText="CustRole" 
         SortExpression="CustRole" /> 
        <asp:BoundField DataField="CustStatus" HeaderText="CustStatus" 
         SortExpression="CustStatus" /> 
        <asp:BoundField DataField="PName" HeaderText="PName" SortExpression="PName" /> 
        <asp:BoundField DataField="PEmail" HeaderText="PEmail" 
         SortExpression="PEmail" /> 
        <asp:BoundField DataField="PRole" HeaderText="PRole" SortExpression="PRole" /> 
        <asp:BoundField DataField="WedDate" HeaderText="WedDate" 
         SortExpression="WedDate" /> 
        <asp:BoundField DataField="UserName" HeaderText="UserName" 
         SortExpression="UserName" /> 
        <asp:BoundField DataField="UserId" HeaderText="UserId" 
         SortExpression="UserId" /> 
        <asp:CommandField ShowEditButton="True" /> 
       </Fields> 
      </asp:DetailsView> 
      <asp:Label ID="lblHidden" runat="server" Text="Label" Visible="False"></asp:Label> 



      <asp:Button ID="btnDelete" runat="server" onclick="btnDelete_Click" 
       Text="Delete" /> 

Oto kod za:

protected void Page_Load(object sender, EventArgs e) 
    { 
     MembershipUser currentUser = Membership.GetUser(); 
     lblHidden.Text = currentUser.ProviderUserKey.ToString(); 
    } 

    protected void SqlDataSource1_Selecting(object sender, SqlDataSourceSelectingEventArgs e) 
    { 
     // Get a reference to the currently logged on user 
     MembershipUser currentUser = Membership.GetUser(); 

     // Determine the currently logged on user's UserId value 
     // Assign the currently logged on user's UserId to the @UserId parameter 
     //access the parameter value using e.Command.Parameters 
     //programmatically set the @UserId: 
     e.Command.Parameters["@UserId"].Value = currentUser.ProviderUserKey.ToString(); 



    } 
    protected void btnDelete_Click(object sender, EventArgs e) 
    { 

     SqlConnection connection = new SqlConnection(); 
     connection.ConnectionString = ConfigurationManager.ConnectionStrings["ASPNETDBConnectionString1"].ConnectionString; 
     SqlCommand cmd = new SqlCommand(); 
     SqlCommand cmd1 = new SqlCommand(); 
     string userId = lblHidden.Text; 

     cmd.Connection = connection; 
     cmd.CommandText = "DELETE FROM Details WHERE UserId ='" + userId + "'"; 


     cmd1.Connection = connection; 
     cmd1.CommandText = "DELETE FROM aspnet_Membership WHERE UserId ='" + userId + "'"; 

     connection.Open(); 

     cmd.ExecuteNonQuery(); 
     cmd1.ExecuteNonQuery(); 


     connection.Close(); 


     Response.Redirect("Home.aspx"); 
    } 

drugie, czy jest jakiś sposób mogę ustawić wygaśnięcie do adresu URL? Jeśli adres URL kliknie po raz drugi, nie przekieruje użytkownika do żadnego miejsca. Widziałem wiele postów, większość z nich zaleca dodanie kolumny do bazy danych. Czy istnieje inny sposób, w jaki mogę ustawić wygaśnięcie bez dotykania bazy danych?

+0

Czy tworzyłeś role w swojej aplikacji? –

+0

Witam, nie utworzyłem żadnej roli w konfiguracji .Net. – user1529419

Odpowiedz

5

Rozważ osobną stronę dla linku changepassword. Czy ta strona ma unikalny identyfikator. Ten identyfikator powinien działać tylko jeden raz, mieć datę wygaśnięcia i być specyficzny dla tego użytkownika. Udostępnij tę stronę publicznie:

<location path="changepassword.aspx"> 
<system.web> 
    <authorization> 
    <allow users="*"/> 
    </authorization> 
</system.web> 
</location> 

Musisz przechowywać unikatowy identyfikator gdzieś w stosunku do użytkownika. Jeśli nie chcesz mieć wpływ na aktualny schemat, można utworzyć nową tabelę:

PK | Identifier | UserID        | expires 
1 | abcd  | ffffffff-ffff-ffff-ffff-ffffffffffff | 16-jul-2012 18:26 

Gdy strona jest wymagana, jeśli identyfikator jest wygasł nie pozwalają strona funkcjonować. Po zmianie hasła unieważnij identyfikator - usuń go lub ustaw datę ważności na coś z przeszłości (np. Teraz).

+0

Cześć, dziękuję za odpowiedź. Z postu zamieszczonego przez Chrisa poniżej "Dlaczego nie uwierzytelnić ich, a następnie wysłać na stronę profilu?" Tego właśnie używam. Po kliknięciu przez użytkownika adresu URL system powinien automatycznie uwierzytelnić użytkownika, dlatego może przejść do UserProfile.aspx (bez problemu z zasadą dostępu). Ale w jaki sposób mogę zezwolić użytkownikowi na automatyczne logowanie za pomocą formantu logowania asp.net? – user1529419

+0

@ user1529419. Dopóki używasz identyfikatora użytkownika do identyfikacji użytkownika, możesz równie dobrze pozwolić każdemu zmienić hasło dowolnego użytkownika (jak stwierdził Chris "to nie jest fajne"). Proponuję zachować uwierzytelnianie na stronie UserProfile.aspx. Ma inny cel niż "zmiana hasła". –

1

możesz spróbować zezwolić anonimowym użytkownikom na stronę profilu użytkownika, dodając następujące elementy do pliku web.config wewnątrz znacznika <configuration>.

<location path="userProfile.aspx"> 
    <system.web> 
     <authorization> 
     <allow users="?"/> 
     </authorization> 
    </system.web> 
    </location> 
+0

jeśli się nie mylę, to ten warunek pozwoli każdemu odwiedzić stronę? popraw mnie proszę –

+0

@waqar. Konieczne jest zezwolenie na wszystkich użytkowników, ponieważ użytkownik może odwiedzić stronę za pomocą linku "zresetuj hasło". Zobacz moją odpowiedź na bardziej bezpieczne podejście. –

+0

@flem Twoja odpowiedź jest prawidłowa bcz zezwalasz wszystkim użytkownikom na zmianę strony, ale sam pozwala wszystkim użytkownikom na UserProfilePage. –

2

To nie jest bezpośrednią odpowiedzią na pytanie zadane bardziej ogólnego komentarzu hasło strukturyzacji narzędzi resetowania ...

Podczas kodowania ta funkcjonalność Zrobiłbym parę rzeczy inaczej.

Dostęp do strony profilu lub po prostu zmienić hasło?

Po pierwsze, jeśli użytkownik musi zmienić hasło, nie musi mieć dostępu do strony profilu użytkownika tylko strony zmiany hasła.Zabrałbym je prosto na stronę "zmień hasło" i dostosuj ją do funkcji resetowania hasła, dzięki czemu będzie ona anonimowo dostępna bez żadnych problemów.

Dlaczego nie uwierzytelnić ich, a następnie wysłać na stronę profilu?

Inną alternatywą jest raczej niż bałagan z anonimowym dostępem do rzeczy po prostu zrobić automatyczne logowanie. Ten URL prowadziłby do strony docelowej, która automatycznie logowałaby danego użytkownika (mimo wszystko masz wszystkie dane użytkownika). Następnie mogą zostać przekierowani na stronę profilu i nie są już anonimowi, więc wszystko jest w porządku.

Problemy z prostym tekstem identyfikatory użytkowników

Trzeba użyć lepszego token. Jeśli ktoś może znaleźć identyfikator innego użytkownika (być może pojawi się w adresie URL, jeśli klikniesz, aby zobaczyć profil publiczny użytkownika), może zmienić hasło tej osoby. To nie jest fajne, bo jestem pewien, że wiesz.

Co używam zamiast identyfikatorów użytkowników w postaci zwykłego tekstu?

Losowe Żetony

Obie metody obejścia tego jest tworzenie losowe znaki, które są przechowywane w bazie danych, a następnie ich weryfikacji podczas ładowania strony. To oczywiście bardzo ułatwia ich unieważnienie, po prostu zmieniając coś w bazie danych, gdy chcesz je unieważnić. Możesz po prostu przechowywać losowy token (prawdopodobnie użyłbym zakodowanego w base64 ciągu o długości 16 znaków - efektywnie 96 bitów losowości) w DB wraz z wszelkimi niezbędnymi informacjami (np. Userid, data utworzenia (lub data wygaśnięcia) itp.). Jeśli chcesz, aby było to jedno użycie, możesz po prostu usunąć token z bazy danych, gdy zostanie raz zatwierdzony (lub oznaczyć pole, aby powiedzieć, że został użyty lub dowolną liczbę innych alternatyw).

Zaszyfrowane Żetony

Im bardziej bezpieczna metoda, która nie wymaga dotykania baza jest stworzenie szyfrowanego żeton, który można przekazać użytkownikowi. Ten token może zawierać identyfikator użytkownika i czas utworzenia tokena (oraz wszelkie inne informacje, na które masz ochotę) i zostanie umieszczony w wiadomości e-mail i zapomniany. Ponieważ jest to zaszyfrowane dane, a nie losowy token na poczcie zwrotnej, a nie sprawdzanie poprawności za pośrednictwem bazy danych, wystarczy odszyfrować dany token, aby fidn użytkownika i jak stary token.

Jeśli chcesz zrobić je jednokrotnie bez trafiania w bazę danych, to jest to nieco trudniejsze, ale prawdopodobnie zapisałbym wygenerowane tokeny w słowniku aplikacji serwera, a jeśli nie ma tam tokena, nie jest on i usuniesz go z listy, którą przechowujesz po jej użyciu. Regularnie rozjaśniasz stare tokeny, aby upewnić się, że nie przechowujesz zbyt wielu śmieci. Takie podejście ma również tę wadę, że jeśli aplikacja zostanie ponownie uruchomiona, wyczyścisz listę tokenów i tym samym unieważni je wszystkie. Jest to problem tylko wtedy, gdy potrzebujesz jednego strzału. Osobiście pozwoliłbym im zresetować hasło, które chcą, w dowolnym czasie, jaki uznasz za odpowiedni z pojedynczym tokenem. :)

Innym ostrzeżenie o tekstu jawnego identyfikatorów użytkowników w oryginalnym scenariuszu

Nie mogę podkreślić wystarczająco jak bardzo trzeba być z tylko umieszczenie identyfikatora w postaci zwykłego tekstu w url jako jedyna informacja przekazywana. Z chwilą, gdy ktoś wykryje identyfikator użytkownika innej osoby, jego konto zostanie skutecznie naruszone. Wystarczy, że umieścisz te osoby w adresie URL, a oni będą mogli zmienić swoje hasło.

Nawet jeśli nie masz nigdzie, co naraża identyfikatory innych użytkowników, musisz być w 100% pewny, że nigdy nie będziesz w przyszłości, co w praktyce jest niemożliwe do zagwarantowania.