2012-07-16 12 views
5

Tengo una aplicación web que usa un control de inicio de sesión asp.net. Además, también utilizo un control de recuperación de contraseña para que los usuarios recuperen su contraseña. Una vez que el usuario haya terminado de ingresar sus datos en el control de recuperación, un correo electrónico que contenga una URL de verificación se enviará a la dirección de correo electrónico del usuario. Al hacer clic en la URL, se dirige al usuario al perfil de usuario de mi aplicación web, que en el interior permite al usuario cambiar su contraseña.Olvidé mi contraseña URL

Ahora el problema es que, debido a que establecí una regla de acceso a UserProfile.aspx para denegar un usuario anónimo, cuando redirijo la URL a la página UserProfile.aspx, me dirige a la página de inicio de sesión (el sistema me reconoce como un usuario anónimo).

¿Por qué es así? ¿Hay algún lugar que pueda dirigir a la página de perfil de usuario una vez que se hace clic en la URL (que incluye toda la información del usuario)?

La mirada URL como esta:

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

Cuando la última parte del URL era en realidad el ID de usuario.

Este es el código para aspx de perfil de usuario:

<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" /> 

Aquí está el código subyacente:

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"); 
    } 

En segundo lugar, ¿hay alguna manera de que pudiera establecer una caducidad a la URL? Si la URL se está haciendo clic la segunda vez, no redirigiría al usuario a ningún lugar. Vi muchas publicaciones, la mayoría de ellas recomiendan agregar una columna a la base de datos. ¿Hay alguna otra manera en la que pueda establecer el vencimiento sin tocar la base de datos?

+0

¿has creado roles en tu aplicación? –

+0

hola, no creé ninguna función en la configuración .Net. – user1529419

Respuesta

5

Considere una página separada para el enlace changepassword. Haga que esta página tome un identificador único. Este identificador debería funcionar solo una vez, tener una fecha de caducidad y ser específico para ese usuario. Haga que esta página sea pública:

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

Debe almacenar el identificador único en algún lugar contra el usuario. Si no desea afectar su esquema actual, puede crear una nueva tabla:

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

Cuando se solicita la página, si el identificador ha caducado no permiten la página funcione. Una vez que la contraseña ha sido cambiada, invalide el identificador, ya sea elimínelo o configure la fecha de caducidad como algo anterior (por ejemplo, ahora).

+0

Hola, gracias por responder. De la publicación de Chris a continuación: "¿Por qué no autenticarlos y luego enviarlos a la página de perfil?" Esto es lo que estoy usando actualmente ... Una vez que el usuario hace clic en la URL, el sistema debe autenticar automáticamente al usuario, es por eso que puede proceder a UserProfile.aspx (sin el problema de la regla de acceso). Pero, ¿cómo puedo permitir que el usuario inicie sesión automáticamente con el control de inicio de sesión asp.net? – user1529419

+0

@ user1529419. Siempre que use ID de usuario para identificar al usuario, también puede permitir que alguien cambie la contraseña de alguien (según lo declarado por Chris "eso no es genial"). Propongo que mantenga la autenticación en su página UserProfile.aspx. Tiene un propósito diferente a "cambiar contraseña". –

1

puede tratar de permitir a los usuarios anónimos en su página de perfil de usuario agregando lo siguiente a su web.config dentro de la etiqueta <configuration>.

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

si no me equivoco, ¿esta condición permitirá que cualquiera visite la página? corrígeme por favor –

+0

@waqar. Es necesario permitir a todos los usuarios porque el usuario puede visitar a través de un enlace de correo electrónico "restablecer contraseña". Vea mi respuesta para un enfoque más seguro. –

+0

@flem su respuesta es correcta, ya que permite a todos los usuarios cambiar la contraseña, pero Sam permite a todos los usuarios utilizar UserProfilePage. –

2

Esto no es una respuesta directa a la pregunta formulada, pero un comentario más general sobre las herramientas de restablecimiento de contraseña estructuración ...

Al codificar esta funcionalidad me gustaría hacer un par de cosas de manera diferente.

¿Tiene acceso a la página de perfil o simplemente cambia la contraseña?

En primer lugar, si el usuario solo necesita cambiar su contraseña, no necesita acceder a la página del perfil del usuario solo la página de cambio de contraseña.Los llevaría directamente a una página de "cambio de contraseña" y haría esto específico para la funcionalidad de restablecimiento de la contraseña y así tendría disponibilidad anónima sin problemas.

¿Por qué no autenticarlos y luego enviarlos a la página de perfil?

La otra alternativa es, en lugar de perder el tiempo con el acceso anónimo a las cosas solo hacer un inicio de sesión automático. Esa url conduciría a una página de inicio que registraría automáticamente al usuario dado (después de todo, tiene todos los detalles del usuario). Luego pueden ser redirigidos a la página de perfil y ya no son anónimos, así que todo está bien.

Los problemas con los identificadores de usuario de texto sin formato

Es necesario utilizar una mejor señal. Si alguien puede encontrar la identificación de usuario de otro usuario (tal vez aparece en la url si hace clic para ver el perfil público de un usuario), entonces puede cambiar la contraseña de esa persona. Eso no es genial, estoy seguro de que lo sabes.

¿Qué debo usar en lugar de los ID de usuario de texto simple?

azar Fichas

Los dos métodos en torno a este están creando fichas al azar que se almacenan en la base de datos y luego verificarlas al cargar la página. Esto, por supuesto, hace que sea muy fácil invalidarlos simplemente cambiando algo en la base de datos cuando quiera invalidarlos. Puedes simplemente almacenar un token aleatorio (Probablemente vaya a buscar una cadena codificada en base64 que tenga 16 caracteres de longitud, efectivamente 96 bits de aleatoriedad) en el DB junto con la información necesaria (por ejemplo, ID de usuario, fecha de creación (o fecha de caducidad) , etc.) Si desea que sea un uso, puede borrar el token del DB una vez que haya sido validado una vez (o marcar un campo para decir que ha sido usado o cualquier cantidad de otras alternativas).

cifrados Fichas

El método más seguro que no implica tocar la base de datos es crear un token de cifrado que se puede pasar al usuario. Este token podría contener el ID de usuario y la hora en que se creó el token (y cualquier otra información que desee) y se colocará en el correo electrónico y se olvidará. Debido a que se trata de datos cifrados en lugar de un token aleatorio en la devolución de datos en lugar de validar a través de la base de datos, puede descifrar el token dado para encontrar al usuario y la antigüedad del token.

Si quieres hacer un uso sin tocar la base de datos es un poco más complicado, pero probablemente vaya a guardar los tokens generados en el diccionario de la aplicación del servidor y si el token no está ahí, no está válido y lo elimina de la lista que está almacenando una vez utilizado. También borra viejos tokens de forma rutinaria para asegurarse de no almacenar demasiada basura. Este enfoque también tiene el inconveniente de que si se reinicia la aplicación, se borrará la lista de tokens y se invalidarán todos. Sin embargo, esto es solo un problema si necesita que sean de una sola vez. Personalmente, les permitía restablecer su contraseña, todo lo que querían, en el marco de tiempo que usted determinara apropiado con un solo token. :)

Otra advertencia sobre los ID de usuario en texto plano en el escenario original

No puedo expresar con palabras el cuidado que necesita para estar con sólo poner el id de usuario en texto plano en la url como la única información que se pasa. En el momento en que alguien descubre el ID de usuario de otra persona, su cuenta queda efectivamente comprometida. Simplemente tienen que poner esa persona userid en la url y pueden cambiar su contraseña.

Incluso si usted no tiene ninguna parte que expone identificadores de usuario de otras personas que ahora tienen que estar 100% seguro de que usted nunca en el futuro, ya sea que en la práctica es imposible garantizar.

Cuestiones relacionadas