使用 ASP.NET MVC 上传(会话和身份验证)

Posted

技术标签:

【中文标题】使用 ASP.NET MVC 上传(会话和身份验证)【英文标题】:Uploadify (Session and authentication) with ASP.NET MVC 【发布时间】:2010-12-16 07:07:01 【问题描述】:

当我对 uplodify (http://www.uploadify.com/) 使用的操作或控制器使用授权过滤器时,无法执行操作...

而且 Session 没有被检索到。

我发现这是检索到的用户会话:

http://geekswithblogs.net/apopovsky/archive/2009/05/06/working-around-flash-cookie-bug-in-asp.net-mvc.aspx

但是如何将它与[Authorize] 过滤器和检索到的会话一起使用?

【问题讨论】:

本网站用于问答。可以回答您自己的问题或将知识库类型的文章放在这里,但以问题的形式表达它们,然后在答案中用您的解决方案来回答它们。 MVC中不能使用AuthorizeAttribute和Session状态?你确定吗? Sosh,是我写的吗?? 【参考方案1】:

为了纠正这个问题,我建议你一个解决方案...使用 uploadify 发送 auth cookie 值和 session id cookie 值,并在检索会话之前重新创建它。

这是要在视图中实现的代码:

<script>
    var auth = "<% = Request.Cookies[FormsAuthentication.FormsCookieName]==null ? string.Empty : Request.Cookies[FormsAuthentication.FormsCookieName].Value %>";
    var ASPSESSID = "<%= Session.SessionID %>";

    $("#uploadifyLogo").uploadify(
        ...
        formData:  ASPSESSID: ASPSESSID, AUTHID: auth 
    );

然后在 Global.asax 中:

protected void Application_BeginRequest(object sender, EventArgs e)
    
      /* we guess at this point session is not already retrieved by application so we recreate cookie with the session id... */
        try
        
            string session_param_name = "ASPSESSID";
            string session_cookie_name = "ASP.NET_SessionId";

            if (HttpContext.Current.Request.Form[session_param_name] != null)
            
                UpdateCookie(session_cookie_name, HttpContext.Current.Request.Form[session_param_name]);
            
            else if (HttpContext.Current.Request.QueryString[session_param_name] != null)
            
                UpdateCookie(session_cookie_name, HttpContext.Current.Request.QueryString[session_param_name]);
            
        
        catch
        
        

        try
        
            string auth_param_name = "AUTHID";
            string auth_cookie_name = FormsAuthentication.FormsCookieName;

            if (HttpContext.Current.Request.Form[auth_param_name] != null)
            
                UpdateCookie(auth_cookie_name, HttpContext.Current.Request.Form[auth_param_name]);
            
            else if (HttpContext.Current.Request.QueryString[auth_param_name] != null)
            
                UpdateCookie(auth_cookie_name, HttpContext.Current.Request.QueryString[auth_param_name]);
            

        
        catch
        
        
    

    private void UpdateCookie(string cookie_name, string cookie_value)
    
        HttpCookie cookie = HttpContext.Current.Request.Cookies.Get(cookie_name);
        if (null == cookie)
        
            cookie = new HttpCookie(cookie_name);
        
        cookie.Value = cookie_value;
        HttpContext.Current.Request.Cookies.Set(cookie);
    

瞧,用这种方法它是完全透明的。

希望对你有所帮助!! ;)

已编辑:使用 formData 而不是 scriptData

【讨论】:

确实,这非常有帮助:感谢您。我认为问题必须涉及 Flash 检索会话 cookie 的方式(如果有的话),但我只是不知道到底发生了什么,直到我看到这个我才意识到你实际上可以更新传入的 cookie这种方式。你是戈拉姆英雄,谢谢。 =) 将 sessionId 放入脚本中是个坏主意,因为它容易受到会话劫持(除非您通过 SSL 提供脚本)。 @Adam Nofsinger - 这是真的,但不需要更多地敞开心扉。使用 cookie,您可以将它们设置为 HTTPOnly(我知道不是完整的证明),但使用脚本可以将自己打开到恶意 js。这是一个类似的响应 - 不需要会话 ID 在您的 js 中。 ***.com/questions/4538174/… 对不起,我不是要挑剔,你的答案很好(帮了我),但我最近做了一些安全研究,引起了我的注意。 +1000 真的帮助了我。 -999 有 twocatch 子句。伤了我的眼睛... 对于较新版本的 Uploadify,使用 formData 而不是 scriptData【参考方案2】:

对于VB转换的代码 *以 开始代码块

var auth='<%# IIf(Request.Cookies(FormsAuthentication.FormsCookieName) Is Nothing, "", 
     Request.Cookies(FormsAuthentication.FormsCookieName).Value)%>';

var ASPSESSID = '<%# Session.SessionID%>';

【讨论】:

【参考方案3】:

此解决方案效果很好。如果有人需要,我将代码翻译成 vb:

    Protected Sub Application_BeginRequest(ByVal sender As Object, ByVal e As System.EventArgs)
    'we guess at this point session is not already retrieved by application so we recreate cookie with the session id...
    Try
        Dim session_param_name = "ASPSESSID"
        Dim session_cookie_name = "ASP.NET_SessionId"

        If Not HttpContext.Current.Request.Form(session_param_name) Is Nothing Then
            UpdateCookie(session_cookie_name, HttpContext.Current.Request.Form(session_param_name))
        ElseIf Not HttpContext.Current.Request.QueryString(session_param_name) Is Nothing Then
            UpdateCookie(session_cookie_name, HttpContext.Current.Request.QueryString(session_param_name))
        End If
    Catch ex As Exception
    End Try


    Try
        Dim auth_param_name = "AUTHID"
        Dim auth_cookie_name = FormsAuthentication.FormsCookieName

        If Not HttpContext.Current.Request.Form(auth_param_name) Is Nothing Then
            UpdateCookie(auth_cookie_name, HttpContext.Current.Request.Form(auth_param_name))
        ElseIf Not HttpContext.Current.Request.QueryString(auth_param_name) Is Nothing Then
            UpdateCookie(auth_cookie_name, HttpContext.Current.Request.QueryString(auth_param_name))
        End If
    catch ex As Exception
    End Try
End Sub

Private Sub UpdateCookie(ByVal cookie_name As String, ByVal cookie_value As String)
    Dim cookie = HttpContext.Current.Request.Cookies.Get(cookie_name)
    If cookie Is Nothing Then
        cookie = New HttpCookie(cookie_name)
    End If
    cookie.Value = cookie_value
    HttpContext.Current.Request.Cookies.Set(cookie)
End Sub

这是 javascript 变量赋值的部分:

var auth = "<%=IIf(Request.Cookies(FormsAuthentication.FormsCookieName) Is Nothing, "", Request.Cookies(FormsAuthentication.FormsCookieName).Value)%>";
var ASPSESSID = "<%=Session.SessionID%>";

也许在 VB 工作的人可以从中受益。

【讨论】:

以上是关于使用 ASP.NET MVC 上传(会话和身份验证)的主要内容,如果未能解决你的问题,请参考以下文章

使用 WIF 和 jquery ajax 请求时 ASP.NET MVC 3 中的会话 Cookie 过期处理

ASP.NET Core MVC:设置身份 cookie 过期

asp.net cookie、身份验证和会话超时

ASP.NET 窗体身份验证超时和会话超时

ASP.NET MVC:窗体身份验证及角色权限管理示例

如何同步表单身份验证 cookie 和 Asp.Net 会话的生命周期?