none
执行FormsAuthentication.Decrypt方法错误:无法验证数据【Execution of the FormsAuthentication.Decrypt method error: Can not validate data 】 RRS feed

  • 问题

  • 客户端通过AJAX请求WCF REST 服务,传递token参数验证合法用户时,服务端返回错误:

    System.Web.HttpException (0x80004005): 无法验证数据。
       在 System.Web.Configuration.MachineKeySection.EncryptOrDecryptData(Boolean fEncrypt, Byte[] buf, Byte[] modifier, Int32 start, Int32 length, Boolean useValidationSymAlgo, Boolean useLegacyMode, IVType ivType, Boolean signData)
       在 System.Web.Security.FormsAuthentication.Decrypt(String encryptedTicket)
       在 KPT.Auth.Authorize.TokenAuthorize.get_CurrentUser()

    服务端代码:

    public User CurrentUser
            {
                get
                {
                    if (String.IsNullOrWhiteSpace(token))
                    {
                        return null;
                    }
    
                    try
                    {
                       FormsAuthenticationTicket ticket = FormsAuthentication.Decrypt(token);
                        if (ticket == null)
                        {
                            return null;
                        }
    
                        var user = new JavaScriptSerializer().Deserialize<User>(ticket.UserData);
                        user.userData = ticket.UserData;
                        return user;
                    }
                    catch (Exception ex)
                    {
                       throw new ArgumentException(ex.Message);
                    }
                }
            }

    2017年7月12日 9:35

答案

  • 非常感谢您的回复

    那个问题今上午已经解决好了,错误原因是由于公司部门经理在配置站点的时候,把调用接口地址配置错了,导致生成token的时候,不在测试服务器。

    我很乐意把我这个功能场景给您说一下:

    1:所有的WCF服务寄宿在IIS一个站点上(例如:测试服务器),WCF REST接口调用的安全机制是通过FormsAuthenticationTicket来处理的,FormsAuthenticationTicket相关的操作我用单独一个类库封装好的,这样以便于复用,正如您上面提到的IAuthorize这个接口,也是自定义的。

    2:在我们这个项目中,有两个场景需要生产token,第一是在登录成功后给用户返回一个token,第二是在项目中通过引用WCF服务地址(xxxx.svc?wsdl这种方式)后,通过该服务里的方法来生成token,而出现问题的场景恰好在第二种情况中,由于项目经理在更新站点时,误将演示版(演示版单独服务器)站点中的配置文件信息用到测试版(测试版单独服务器)站点的配置文件中,这样导致在测试版服务器中生成token的时候,是调用了演示版的接口,而并非调用测试服务器的接口,所以,测试服务器在解析token的时候是无法解析,从而抛出了那个异常。

    • 已标记为答案 A-Leon 2017年7月18日 3:09
    2017年7月18日 3:05

全部回复

  • Hi,

    感谢你在MSDN论坛发帖。

    因为你的问题涉及WCF的开发问题,我将把这个帖子移到WCF论坛。

    Best Regards,

    Hart


    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    2017年7月13日 1:47
  • 嗨,

    根据错误信息好像是你的Token不合法,你的tokenCurrentUser里是怎么拿到的?

    我建议你参考下下面的链接。

    #WCF Restful Service Form Authentication

    https://www.codeproject.com/Tips/838957/WCF-Restful-Service-Form-Authentication

    方便重新你的问题,最好能上传一个可以重新你问题的项目,这样方便调试来解决问题。

    Best Regards,

    Edward


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    2017年7月13日 5:49
    版主
  • 恩 谢谢

    因为我是第一次在MSDN发帖,有些地方可能不清楚。

    2017年7月17日 1:49
  • AJAX 是通过GET请求方式来调用WCF REST服务的,请求地址为:http://www.url.com/class/relation/list?token=xxxxxxx&comId=xxxxx

    下面是WCF的服务契约:

    [OperationContract, WebInvoke(Method = "GET", UriTemplate = "/class/relation/list?token={token}&comId={comId}", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]
            Message GetCustClassRelationList(string token, string comId);

    契约的实现:

    public System.ServiceModel.Channels.Message GetCustClassRelationList(string token, string comId)
    {
                    var authUser = Fetch.GetAuthUserByToken(token);
                    if (authUser == null)
                    {
                        DTO<string> dtoError = new DTO<string>()
                        {
                            success = false,
                            data = string.Empty,
                            content = "请求接口认证失败"
                        };
    
                        return context.CreateJsonResponse(dtoError);
                    }
    
                  //Do something.........
    }

    在Fetch类中封装了一个获取认证用户的静态方法:

    public static Auth.User GetAuthUserByToken(string token)
     {
            return Auth.AuthContext.GetTokenAuth(token).CurrentUser;
     }

    AuthContext上下文的GetTokenAuth静态方法:

    public static IAuthorize GetTokenAuth(string token)
    {
          return new TokenAuthorize(token);
    }

    然后通过IAuthorize的实例TokenAuthorize去获取当前认证用户

    public User CurrentUser
    {
                get
                {
                    if (String.IsNullOrWhiteSpace(token))
                    {
                        return null;
                    }
    
                    try
                    {
                       FormsAuthenticationTicket ticket = FormsAuthentication.Decrypt(token);
                        if (ticket == null)
                        {
                            return null;
                        }
    
                        var user = new JavaScriptSerializer().Deserialize<User>(ticket.UserData);
                        user.userData = ticket.UserData;
                        return user;
                    }
                    catch (Exception ex)
                    {
                       throw new Exception(ex.Message);
                    }
                }
    }

    此时,在执行FormsAuthentication.Decrypt(token)时,就抛出异常:System.Web.HttpException (0x80004005): 无法验证数据

    现在,我不知道为什么会出现这个问题,因为在正式公网服务器中该代码功能可以正常运行,而在测试公网服务器中就出现上面这个问题了。








    • 已编辑 A-Leon 2017年7月17日 2:34
    2017年7月17日 2:07
  • 嗨,

    "IAuthorize"是你自己定义的接口还是.net内置的?我没有查找到相关的方法返回“CurrentUser”。

    对于“GetCustClassRelationList“传入的token是怎么生成的?

    对于你的问题,我觉得主要是token的生成和验证,针对正式服务器正常,测试服务器又问题,我建议你查看针对同一个用户,两个服务器生成的token是不是一样的,是不是混用了token.

    Best Regards,

    Edward


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    2017年7月17日 6:23
    版主
  • 非常感谢您的回复

    那个问题今上午已经解决好了,错误原因是由于公司部门经理在配置站点的时候,把调用接口地址配置错了,导致生成token的时候,不在测试服务器。

    我很乐意把我这个功能场景给您说一下:

    1:所有的WCF服务寄宿在IIS一个站点上(例如:测试服务器),WCF REST接口调用的安全机制是通过FormsAuthenticationTicket来处理的,FormsAuthenticationTicket相关的操作我用单独一个类库封装好的,这样以便于复用,正如您上面提到的IAuthorize这个接口,也是自定义的。

    2:在我们这个项目中,有两个场景需要生产token,第一是在登录成功后给用户返回一个token,第二是在项目中通过引用WCF服务地址(xxxx.svc?wsdl这种方式)后,通过该服务里的方法来生成token,而出现问题的场景恰好在第二种情况中,由于项目经理在更新站点时,误将演示版(演示版单独服务器)站点中的配置文件信息用到测试版(测试版单独服务器)站点的配置文件中,这样导致在测试版服务器中生成token的时候,是调用了演示版的接口,而并非调用测试服务器的接口,所以,测试服务器在解析token的时候是无法解析,从而抛出了那个异常。

    • 已标记为答案 A-Leon 2017年7月18日 3:09
    2017年7月18日 3:05