Generating cryptographically secure authentication tokens

后端 未结 7 1708
后悔当初
后悔当初 2020-12-22 15:15

Background:

This is really a general best-practices question, but some background about the specific situation might be helpful:

We are deve

7条回答
  •  醉梦人生
    2020-12-22 15:42

    Based on the feedback from the other answers to this question, additional research, and offline discussions, here is what we ended up doing...

    It was pointed out pretty quickly that the interaction model here is essentially exactly the same as the model used by Forms Authentication in ASP.NET when a "remember me" checkbox is checked. It's just not a web browser making the HTTP requests. Our "ticket" is equivilant to the cookie that Forms Authentication sets. Forms Authentication uses essentially an "encrypt some data with a secret key" approach by default.

    In our login web service, we use this code to create a ticket:

    string[] userData = new string[4];
    
    // fill the userData array with the information we need for subsequent requests
    userData[0] = ...; // data we need
    userData[1] = ...; // other data, etc
    
    // create a Forms Auth ticket with the username and the user data. 
    FormsAuthenticationTicket formsTicket = new FormsAuthenticationTicket(
        1,
        username,
        DateTime.Now,
        DateTime.Now.AddMinutes(DefaultTimeout),
        true,
        string.Join(UserDataDelimiter, userData)
        );
    
    // encrypt the ticket
    string encryptedTicket = FormsAuthentication.Encrypt(formsTicket);
    

    Then we have an operation behavior attribute for the WCF services that adds an IParameterInspector that checks for a valid ticket in the HTTP headers for the request. Developers put this operation behavior attribute on operations that require authentication. Here is how that code parses the ticket:

    // get the Forms Auth ticket object back from the encrypted Ticket
    FormsAuthenticationTicket formsTicket = FormsAuthentication.Decrypt(encryptedTicket);
    
    // split the user data back apart
    string[] userData = formsTicket.UserData.Split(new string[] { UserDataDelimiter }, StringSplitOptions.None);
    
    // verify that the username in the ticket matches the username that was sent with the request
    if (formsTicket.Name == expectedUsername)
    {
        // ticket is valid
        ...
    }
    

提交回复
热议问题