how to save user credentials on server for running

2019-04-12 17:41发布

问题:

Background:

We have an ASP.NET / Silveright web application. The silverlight client displays user specific data in a graphical form - it requests the data from the server:

Problem: Getting this data is expensive, due to the underlying database queries that the server has to perform - so the client has to wait...

Optimisation Idea: We run the database queries at regular intervals on the server, writing the results to a 'userdata' table in a database 'close' to where the ASP.NET server runs.

The process of running the queries and writing the data to the tables is performed by a 'data collection' service, which is separated from the ASP.NET server.

When the client requests data the server retrieves it from a 'userdata' table. This should be nice and quick - we probably have the 'userdata' tables on the same machine as the ASP.NET server. We also have the added benefit that the client sees data even if the underlying database is offline.

Of course the data is not live - but all data is potentially old as soon as it reaches the client.

So now my Problem: The 'data collection' service needs the user credentials in order to perform these database queries (because each user gets different results for the same query).

Question:

How can I store user credentials in a database, in an acceptable 'secure' way? Such that the 'data collection' can impersonate a user to perform the database queries. Our initial scenario is based upon using windows integrated login to the database.

回答1:

As I understand this you will need to run a query per user but you do not want to make this a blocking call. You want the responsiveness of a denormalized read model, the UserData.

I have an idea where you instead of storing the credentials somewhere, you simply start a thread and provide that thread with the current credentials taken from the request.

class MyClass
{
    public static void DoSomething(object principal)
    {
        if (principal == null || !(principal is IPrincipal))
            throw new ArgumentException();
        Thread.CurrentPrincipal = (IPrincipal) principal;
        // Do heavy querying and update UserData
    }
}

I call this from an ASP.NET MVC Controller like this:

public ActionResult Index() 
{
    var t = new Thread(MyClass.DoSomething);
    t.Start(User);

    return View();
}

This would update the UserData for each request. If you want, you could introduce some logic for the update frequency and only make the call on certain conditions.

Another approach I was thinking about was a step towards the CQRS mindset, where I in this case would publish a message containing the serialized IPrincipal and that message would be consumed by another instance/server that would update the read model as a separate process. But I am uncertain that the IPrincipal would actually work if deserialized on another server.

Anyway, I don't see the benefit of persisting the credentials. Just use them in the scope of a new thread or in the context of a message consumed.