AntiForgeryToken invalid after sign in

前端 未结 2 1725
南笙
南笙 2021-02-07 20:11

I have a form which the user can post without loging in. If however his email is recognized a password is required. The password form is validated over Ajax and if successfull t

相关标签:
2条回答
  • 2021-02-07 20:35

    The current user is stored in the anti-forgery token in the form data and compared with the current user on postback.

    You should be able to pull out the form token on postback in the same way Phil Haack does it in this post.

    Then use the AntiForgeryDataSerializer class to deserialize the token, update the current user, serialize it again and put it back in the form before it's checked. Or replace the validate method entirely using your own attribute.

    Alternatively, instead of updating it on the main forms postback, you could try send the updated token back with the password ajax request and update the form. Either way the basic approach is the same, deserialize, update user, serialize, replace token.

    string antiForgeryTokenName = AntiForgeryData.GetAntiForgeryTokenName(null);
    string text = context.Request.Form[antiForgeryTokenName];
    AntiForgeryDataSerializer serializer = new AntiForgeryDataSerializer();
    
    AntiForgeryData antiForgeryData = serializer.Deserialize(text); 
    antiForgeryData.Username = AntiForgeryData.GetUsername(context.User);
    string newToken = serializer.Serialize(antiForgeryData);    
    

    AntiForgeryDataSerializer and AntiForgeryData are internal classes, so you will have to use some basic reflection to call methods on them.

    0 讨论(0)
  • 2021-02-07 20:38

    Updated final answer to account for changes to AntiForgeryTokenSerializer constructor:

        const string serializerAssembly = "System.Web.Helpers.AntiXsrf.AntiForgeryTokenSerializer";
        const string cryptoAssembly = "System.Web.Helpers.AntiXsrf.MachineKey40CryptoSystem";
        const string token = "System.Web.Helpers.AntiXsrf.AntiForgeryToken";
        const string fieldName = "__RequestVerificationToken";
    
        Assembly mvcAssembly = typeof (AntiForgery).Assembly;
        Type afdType = mvcAssembly.GetType(token);
    
        Type serializerType = mvcAssembly.GetType(serializerAssembly);
        Type cryptoType = mvcAssembly.GetType(cryptoAssembly);
        var constructors = serializerType.GetConstructors(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
        ConstructorInfo cryptoConstructor = cryptoType.GetConstructor(new Type[0]);
        var crypto = cryptoConstructor.Invoke(new object[0]);
        object serializer = constructors[0].Invoke(new object[] { crypto });
    
        string text = currentContext.Request.Form[fieldName];
        string newToken = String.Empty;
    
        if (!String.IsNullOrEmpty(text))
        {
            object antiForgeryToken = serializerType.InvokeMember("Deserialize", BindingFlags.InvokeMethod, null,
                                                                  serializer, new object[] {text});
    
            afdType.GetProperty("Username").SetValue(antiForgeryToken,
                                                     signIn ? user.Email : string.Empty,
                                                     null);
    
            newToken = Convert.ToString(serializerType.InvokeMember(
                "Serialize",
                BindingFlags.InvokeMethod,
                null,
                serializer,
                new[] {antiForgeryToken}));
        }
    
        return newToken;
    
    0 讨论(0)
提交回复
热议问题