5

asp.net ログイン コントロールを使用する Web アプリケーションがあります。さらに、ユーザーがパスワードを回復するためのパスワード回復コントロールも使用します。ユーザーがリカバリ コントロールに詳細を入力し終えると、検証 URL を含む電子メールがユーザーの電子メール アドレスに送信されます。URL をクリックすると、ユーザーは Web アプリケーションの UserProfile に誘導され、その中でユーザーはパスワードを変更できます。

ここで問題は、アクセス ルールを UserProfile.aspx に設定して匿名ユーザーを拒否するため、URL から UserProfile.aspx ページにリダイレクトすると、代わりに LoginPage にリダイレクトされることです (システムは私を匿名ユーザーとして認識します)。 )。

なぜそうなのですか?URL をクリックすると (すべてのユーザー情報を含む)、ユーザー プロファイル ページに移動できる場所はありますか?

URL は次のようになります。

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

URL の最後の部分は実際には userId でした。

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

コードビハインドは次のとおりです。

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

次に、URL に有効期限を設定する方法はありますか? URL が 2 回目にクリックされた場合、ユーザーはどこにもリダイレクトされません。多くの投稿を見ましたが、そのほとんどはデータベースに列を追加することを推奨しています。データベースに触れずに有効期限を設定できる他の方法はありますか???

4

3 に答える 3

5

changepassword リンク用の別のページを検討してください。このページに一意の識別子を取得させます。この識別子は 1 回だけ機能し、有効期限があり、そのユーザーに固有のものである必要があります。このページを公開する:

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

ユーザーに対して一意の識別子をどこかに保存する必要があります。現在のスキーマに影響を与えたくない場合は、新しいテーブルを作成できます。

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

ページが要求されたときに、識別子の有効期限が切れていると、ページが機能しなくなります。パスワードが変更されたら、識別子を無効にします。識別子を削除するか、有効期限を過去 (たとえば現在) に設定します。

于 2012-07-16T16:26:14.497 に答える
2

これは、尋ねられた質問に対する直接の回答ではありませんが、パスワード リセット ツールの構造化に関するより一般的なコメントです...

この機能をコーディングするとき、いくつかのことを別の方法で行います。

プロフィール ページにアクセスしますか、それとも単にパスワードを変更しますか?

まず、ユーザーがパスワードを変更する必要がある場合は、ユーザー プロファイル ページにアクセスする必要はなく、パスワードの変更ページだけにアクセスする必要があります。私は彼らを「パスワードの変更」ページに直接連れて行き、これをパスワードリセット機能に固有のものにして、問題なく匿名で利用できるようにします.

それらを認証してから、プロファイル ページに送信してみませんか?

もう1つの選択肢は、物事への匿名アクセスを台無しにするのではなく、自動ログインを行うことです. その URL は、指定されたユーザーを自動的にログインさせるランディング ページにつながります (結局のところ、すべてのユーザーの詳細が表示されます)。その後、彼らはプロフィールページにリダイレクトされ、匿名ではなくなるため、すべて問題ありません.

プレーンテキストのユーザー ID に関する問題

より良いトークンを使用する必要があります。誰かが別のユーザーのユーザー ID を見つけた場合 (ユーザーのパブリック プロファイルをクリックして表示すると、URL に表示される可能性があります)、そのユーザーのパスワードを変更できます。あなたが知っていると確信しているので、それはクールではありません。

プレーンテキストのユーザー ID の代わりに何を使用しますか?

ランダムトークン

これを回避する 2 つの方法は、データベースに保存するランダム トークンを作成し、ページの読み込み時にそれらを検証することです。もちろん、これにより、無効にしたいときにデータベース内の何かを変更するだけで、非常に簡単に無効にすることができます。必要な情報 (ユーザー ID、作成日 (または有効期限) など) と一緒にランダム トークンを DB に格納することができます (私はおそらく、長さ約 16 文字の base64 でエンコードされた文字列 - 事実上 96 ビットのランダム性) を使用します。など)。1回だけ使用したい場合は、トークンが1回検証されたらDBからトークンをクリアするだけです(または、フィールドにマークを付けて、使用済みまたはその他の代替手段をいくつでも指定できます)。

暗号化されたトークン

データベースに触れる必要のないより安全な方法は、ユーザーに渡すことができる暗号化されたトークンを作成することです。このトークンには、ユーザー ID とトークンが作成された時刻 (および必要に応じてその他の情報) を含めることができ、電子メールに入れられて忘れられます。データベースを介して検証するのではなく、ポストバックのランダムトークンではなく暗号化されたデータであるため、指定されたトークンを復号化して、ユーザーとトークンの古さを確認できます。

データベースにアクセスせずにそれらを1回使用したい場合は、もう少しトリッキーですが、生成されたトークンをサーバーアプリケーションディクショナリに保存することをお勧めします。トークンがそこにない場合は有効ではないため、削除します一度使用すると、保存しているリストからそれを取得します。また、古いトークンを定期的にクリアして、ジャンクを保存しすぎないようにします。このアプローチには、アプリを再起動すると、トークンのリストがクリアされてすべてが無効になるという欠点もあります。ただし、これは、それらを一発にする必要がある場合にのみ問題になります。個人的には、単一のトークンで適切と判断した期間内に、必要なだけパスワードをリセットできるようにします。:)

元のシナリオでのプレーンテキストのユーザー ID に関する別の警告

渡される唯一の情報として、ユーザー ID をプレーンテキストで URL に入れるだけで、どれだけ注意する必要があるかは強調しきれません。誰かが別の人のユーザー ID を見つけた瞬間、そのアカウントは実質的に侵害されます。その人のユーザー ID を URL に入力するだけで、パスワードを変更できます。

他の人の UserID を公開する場所が今はなくても、将来も公開しないことを 100% 確信する必要がありますが、これは実際には保証できません。

于 2012-07-16T16:35:27.257 に答える
1

<configuration>タグ内の web.config に以下を追加することで、ユーザー プロファイル ページへの匿名ユーザーの許可を試みることができます。

  <location path="userProfile.aspx">
    <system.web>
      <authorization>
        <allow users="?"/>
      </authorization>
    </system.web>
  </location>
于 2012-07-16T16:20:43.770 に答える