通过身份验证在ASPNET MVC中提供iCalendar文件

时间:2012-06-11 01:35:42

标签: asp.net-mvc icalendar

我正在尝试在我的MVC应用程序中提供iCalendar文件(.ics)。

到目前为止它工作正常。我有一个iPhone订阅了日历的URL,但现在我需要为每个用户提供个性化的日历。

在iPhone上订阅日历时,我可以输入用户名和密码,但我不知道如何在我的MVC应用中访问这些。

我在哪里可以找到有关身份验证的工作方式以及如何实施的详细信息?

2 个答案:

答案 0 :(得分:2)

事实证明,基本身份验证是必需的。我有一半工作,但我的IIS配置阻碍了。因此,只有在没有授权标头时返回401响应会导致客户端(例如iPhone)需要用户名/密码才能订阅日历。

在有授权请求标头的请求授权中,可以处理基本身份验证,从基本64位编码的字符串中检索用户名和密码。

这是一些有用的MVC代码:

public class BasicAuthorizeAttribute : AuthorizeAttribute
{
    public override void OnAuthorization(AuthorizationContext filterContext)
    {
        if (filterContext == null)
        {
            throw new ArgumentNullException("filterContext");
        }

        var auth = filterContext.HttpContext.Request.Headers["Authorization"];

        if (!String.IsNullOrEmpty(auth))
        {
            var encodedDataAsBytes = Convert.FromBase64String(auth.Replace("Basic ", ""));
            var value = Encoding.ASCII.GetString(encodedDataAsBytes);
            var username = value.Substring(0, value.IndexOf(':'));
            var password = value.Substring(value.IndexOf(':') + 1);

            if (MembershipService.ValidateUser(username, password))
            {
                filterContext.HttpContext.User = new GenericPrincipal(new GenericIdentity(username), null);
            }
            else
            {
                filterContext.Result = new HttpStatusCodeResult(401);
            }
        }
        else
        {
            if (AuthorizeCore(filterContext.HttpContext))
            {
                var cachePolicy = filterContext.HttpContext.Response.Cache;
                cachePolicy.SetProxyMaxAge(new TimeSpan(0));
                cachePolicy.AddValidationCallback(CacheValidateHandler, null);
            }
            else
            {
                filterContext.HttpContext.Response.Clear();
                filterContext.HttpContext.Response.StatusDescription = "Unauthorized";
                filterContext.HttpContext.Response.AddHeader("WWW-Authenticate", "Basic realm=\"Secure Calendar\"");
                filterContext.HttpContext.Response.Write("401, please authenticate");
                filterContext.HttpContext.Response.StatusCode = 401;
                filterContext.Result = new EmptyResult();
                filterContext.HttpContext.Response.End();
            }
        }
    }

    private void CacheValidateHandler(HttpContext context, object data, ref HttpValidationStatus validationStatus)
    {
        validationStatus = OnCacheAuthorization(new HttpContextWrapper(context));
    }
}

然后,我的控制器操作如下所示:

[BasicAuthorize]
public ActionResult Calendar()
{
    var userName = HttpContext.User.Identity.Name;
    var appointments = GetAppointments(userName);
    return new CalendarResult(appointments, "Appointments.ics");
}

答案 1 :(得分:0)

我发现这确实很有帮助,但我在开发过程中遇到了一些问题,我想我会分享一些问题,以帮助拯救其他人一段时间。

我希望从我的网络应用程序获取数据到Android设备的日历中,我使用discountasp作为托管服务。

我遇到的第一个问题是,当上传到服务器时验证不起作用,很可靠,它接受我的控制面板登录discountasp而不是我的表单登录。

答案是关闭IIS管理器中的基本身份验证。这解决了这个问题。

其次,用于将日历同步到Android设备的应用程序称为iCalSync2 - 它是一个不错的应用程序并且运行良好。但是我发现只有当文件以.ics形式发送时才能正常工作(因为某些原因我把它作为.ical ...它一定是迟到了)而且我还必须选择网络选项

最后我发现我必须在我的网址的开头添加webcal://而不是http://

另外要小心,因为上面发布的代码忽略了角色输入变量,并且总是不传递任何内容,因此您可能需要在日历例程中执行一些基于角色的检查,或修改上面的代码来处理角色变量。