MVC3: HTTP 302 Redirect Error (due to asp.net authentication)

I'm using uploadify to bulkupload files and I get a 302 redirect error. I'm assuming that this is because of some asp.net authentication cookie token not being passed back in the script call.

I have uploadify working in a regular bare bones mvc3 application but when I tried to integrate it within a secure asp.net mvc3 application it tries to redirect to account/signin.

I have an authentication token (@auth) that does come back as a long string within the view but I still get the 302 redirect error.

Any ideas how to send the cookie authentication data over?

View:

 @{
     string auth = @Request.Cookies[FormsAuthentication.FormsCookieName] == null ? string.Empty : Request.Cookies[FormsAuthentication.FormsCookieName].Value;
     }


<script type="text/javascript">
    jQuery.noConflict();
    jQuery(document).ready(function () {
        jQuery("#bulkupload").uploadify({
            'uploader': '@Url.Content("~/Scripts/uploadify.swf")',
            'cancelImg': '/Content/themes/base/images/cancel.png',
            'buttonText': 'Browse Files',
            'script': '/Creative/Upload/',
            scriptData: { token: "@auth" }, 
            'folder': '/uploads',
            'fileDesc': 'Image Files',
            'fileExt': '*.jpg;*.jpeg;*.gif;*.png',
            'sizeLimit': '38000',
            'multi': true,
            'auto': true,
              'onError'     : function (event,ID,fileObj,errorObj) {
      alert(errorObj.type + ' Error: ' + errorObj.info);
    }
        });
    }); 
    </script> 

Controller:

public class CreativeController : Controller
{
    public string Upload(HttpPostedFileBase fileData, string token)
    {
      ...
    }
}

UPDATE: Ok, this works fine with IE9 but not in Chrome (Chrome throws the 302). FF doesn't even render the control.

Does anybody know how to get this working in the latest revs for Chrome and FF?


I had similar problems when I tried to use uploadify with asp.net mvc3. After much googling this is what I found that seems to work. It basically involves declaring a custom attribute, then explicitly passing the authentication cookie into Uploadify's HTTP Post and processing the cookie manually via the custom attribute.

First declare this custom attribute:

/// <summary>
/// A custom version of the <see cref="AuthorizeAttribute"/> that supports working
/// around a cookie/session bug in Flash.  
/// </summary>
/// <remarks>
/// Details of the bug and workaround can be found on this blog:
/// http://geekswithblogs.net/apopovsky/archive/2009/05/06/working-around-flash-cookie-bug-in-asp.net-mvc.aspx
/// </remarks>
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)]
public class TokenizedAuthorizeAttribute : AuthorizeAttribute
{
    /// <summary>
    /// The key to the authentication token that should be submitted somewhere in the request.
    /// </summary>
    private const string TOKEN_KEY = "authCookie";

    /// <summary>
    /// This changes the behavior of AuthorizeCore so that it will only authorize
    /// users if a valid token is submitted with the request.
    /// </summary>
    /// <param name="httpContext"></param>
    /// <returns></returns>
    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
        string token = httpContext.Request.Params[TOKEN_KEY];

        if (token != null)
        {
            FormsAuthenticationTicket ticket = FormsAuthentication.Decrypt(token);

            if (ticket != null)
            {
                var identity = new FormsIdentity(ticket);
                string[] roles = System.Web.Security.Roles.GetRolesForUser(identity.Name);
                var principal = new GenericPrincipal(identity, roles);
                httpContext.User = principal;
            }
        }

        return base.AuthorizeCore(httpContext);
    }
}

Then declare this Action to pass the authentication cookie into your ViewData so you can pass it to the Uploadify widget. This will also be the action you invoke to instantiate the Uploadify widget later.

    [Authorize]
    public ActionResult UploadifyUploadPartial()
    {
        ViewBag.AuthCookie = Request.Cookies[FormsAuthentication.FormsCookieName] == null
                                 ? string.Empty
                                 : Request.Cookies[FormsAuthentication.FormsCookieName].Value;
        return PartialView("UploadifyUpload");
    }

This is the code for the UploadifyUpload View. It is basically a wrapper for the JavaScript which sets up Uploadify. I copied mine without changes so you will have to adapt it for your application. The important thing to note is that you are passing the authCookie into the scriptData property via the ViewData from the UploadifyUploadPartial Action.

@if (false)
{
    <script src="../../Scripts/jquery-1.5.1-vsdoc.js" type="text/javascript"></script>
}
@{
    ViewBag.Title = "Uploadify";
}
<script src="@Url.Content("~/Scripts/plugins/uploadify/swfobject.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/plugins/uploadify/jquery.uploadify.v2.1.4.min.js")" type="text/javascript"></script>
<link href="@Url.Content("~/Scripts/plugins/uploadify/uploadify.css")" rel="stylesheet" type="text/css" />
<script>
    $(document).ready(function () {
        CreateUploadifyInstance("dir-0");
    });
    function CreateUploadifyInstance(destDirId) {
        var uploader = "@Url.Content("~/Scripts/plugins/uploadify/uploadify.swf")";
        var cancelImg = "@Url.Content("~/Scripts/plugins/uploadify/cancel.png")";
        var uploadScript = "@Url.Content("~/Upload/UploadifyUpload")";
        var authCookie = "@ViewBag.AuthCookie";
        $('#uploadifyHiddenDummy').after('<div id="uploadifyFileUpload"></div>');
        $("#uploadifyFileUpload").uploadify({
            'uploader': uploader,
            'cancelImg': cancelImg,
            'displayData': 'percentage',
            'buttonText': 'Select Session...',
            'script': uploadScript,
            'folder': '/uploads',
            'fileDesc': 'SunEye Session Files',
            'fileExt': '*.son2',
            'scriptData'  : {'destDirId':destDirId, 'authCookie': authCookie},
            'multi': false,
            'auto': true,
            'onCancel': function(event, ID, fileObj, data) {
                //alert('The upload of ' + ID + ' has been canceled!');
            },
            'onError': function(event, ID, fileObj, errorObj) {
                alert(errorObj.type + ' Error: ' + errorObj.info);
            },
            'onAllComplete': function(event, data) {
                $("#treeHost").jstree("refresh");
                //alert(data.filesUploaded + ' ' + data.errors);
            },
            'onComplete': function(event, ID, fileObj, response, data) {
                alert(ID + " " + response);
            }
        });
    }
    function DestroyUploadifyInstance() {
        $("#uploadifyFileUpload").unbind("uploadifySelect");
        swfobject.removeSWF('uploadifyFileUploadUploader');
        $('#uploadifyFileUploadQueue').remove();
        $('#uploadifyFileUploadUploader').remove();
        $('#uploadifyFileUpload').remove();
    }
</script>
<div id="uploadifyHiddenDummy" style="visibility:hidden"></div>
<div id="uploadifyFileUpload">
</div>

For your Action that Uploadify Posts to, use the new TokenizedAuthorize attribute instead of the Authorize attribute:

    [HttpPost]
    [TokenizedAuthorize]
    public string UploadifyUpload(HttpPostedFileBase fileData)
    {
        FormsAuthenticationTicket ticket = FormsAuthentication.Decrypt(Request.Form["authCookie"]);
        if (ticket != null)
        {
            var identity = new FormsIdentity(ticket);
            if (!identity.IsAuthenticated)
            {
                return "Not Authenticated";
            }
        }
        // Now parse fileData...
    }

Finally, to use the code we have written, invoke the UploadifyUploadPartial Action via the Html.Action Helper on any View you wish to host the Uploadify Widget:

@Html.Action("UploadifyUploadPartial", "YourUploadControllerName")

You should be good to go at this point. The code should work in FF, Chrome and IE 9. Let me know if you have problems.

链接地址: http://www.djcxy.com/p/71806.html

上一篇: 基于声明的Web客户端,ASP.Net MVC 4和ASP.Net WebAPI之间的安全性

下一篇: MVC3:HTTP 302重定向错误(由于asp.net认证)