开发者

Sql data reader in classes

Hi On several pages of our website, I want to check if the currently logged in user has accepted our terms and conditions in the past. This boolean value is stored in the application database. Rather than creating a sql data reader afresh on each relevant page, I thought I could put it in a class and then assign the true/false to a variable. This is what I have so far and it does exactly what I want it to:

Public Shared ReadOnly Property termsCompleted As String
    Get
        Dim selectTerms As String = "SELECT Terms FROM tblPersonal WHERE Ref=@Ref"

        Dim dbconn As String = ConfigurationManager.ConnectionStrings("ApplicationServices").ConnectionString
        Using myConnection As New SqlConnection(dbconn)
            myConnection.Open()

            Dim cmdTerms As New SqlCommand(selectTerms, myConnection)
            cmdTerms.Parameters.AddWithValue("@R开发者_运维技巧ef", myUser.ToString())

            Dim readerTerms As SqlDataReader = cmdTerms.ExecuteReader()
            readerTerms.Read()

            termsCompleted = readerTerms.Item(0)

            readerTerms.Close()
            myConnection.Close()

        End Using

    End Get
End Property

I am them using the following on each page that is relevant to deny access and redirect (in the page_load):

If Variables.termsCompleted = False Then
        Response.Redirect("Terms.aspx")
    End If

While this works ok, i'm interested in how secure it is, and is there a better way to do this?

Thanks


Have you considered retrieving the information once during Session_Start, and carrying it around in Session so that you can interrogate it any time you want?

If you can't retrieve the data during authentication/authorization, you would retrieve the data in the same way as you show above.

To put the value into Session: Session["termsCompleted"] = "true";

To read the value from Session: if (Session["termsCompleted"] == "true")....

As an alternative, you could add the information to HttpContext.Current.User.


Sub Session_Start(ByVal sender As Object, ByVal e As EventArgs)
    ' Code that runs when a new session is started
    Dim selectTerms As String = "SELECT Terms FROM tblPersonal WHERE Ref=@Ref"

    If Request.IsAuthenticated = True Then
        Dim dbconn As String = ConfigurationManager.ConnectionStrings("ApplicationServices").ConnectionString
        Using myConnection As New SqlConnection(dbconn)
            myConnection.Open()

            Dim cmdTerms As New SqlCommand(selectTerms, myConnection)
            cmdTerms.Parameters.AddWithValue("@Ref", Variables.myUser)

            Dim readerTerms As SqlDataReader = cmdTerms.ExecuteReader()
            readerTerms.Read()

            Session("termsCompleted") = readerTerms.Item(0)

            readerTerms.Close()
            myConnection.Close()

        End Using
    End If
End Sub

And in the code-behind:

If Session("termsCompleted") = False Then
        Response.Redirect("Terms.aspx")
    End If

Unfortunately this is redirecting to the terms.aspx page every time regardless of what is in the database. From debugging it's picking up the reader item as 'False' even when it's true..

Thanks


Create a base page and have each page inherit from that. In this base page you can do the data access once to perform this check. Then store it in session state.


I don't think you have a security issue...I think it's more of a best practice issue. It's not good practice to put your data access requests in a property. In projects I work on, I typically will have a class that has functions that handle my data access with a buisiness layer that makes the calls to my data access. An n-tier project design may not fit your project...I'm just speaking from my experience.

If you need to reuse the bit flag, just store it in Session.


This logic doesn't really belong on a page. If accepting the terms of use is a requirement for accessing parts of your site then you should handle it that way. This problem is a very similar situation to having an administrator section of a site that only a few users can access.

Ideally this is something you would handle before the request gets to the page. There are (at least) two ways to approach this.

  1. You could write a custom HTTP module that subscribes to the AuthorizeRequest event. It will check whether this page requires that you accept terms of agreement or not and if so checks to see if the user has or not. If not it will redirect the user to the terms of use page.

  2. The other option is to put this code into your Global.ascx file. You would want to subscribe to the AuthorizeRequest event and perform your logic there.

I don't think it matters which option you chose (though the second one may be a little more straight forward to implement). The benefit is that this concern is handled outside of the page itself. This way as you add new pages to your site, you can't forget to add your validation code to it. If you ever decide that in addition to accepting terms of agreement users need to do something else, you now have one place to change instead of going through all of the pages, etc.

You should also take advice of some of the other answers and store this value into the Session to avoid having to to do a database request every time a page loads.

More information:

  • Http Modules and handlers
  • How To Create an ASP.NET HTTP Module Using Visual C# .NET (VB should be the same concept with VB syntax).
  • Application, Page and Control lifecycle (to help you better understand how ASP.NET application lifecycle works and what else is possible).
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜