2

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

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

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

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

4

2 回答 2

2

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

在有 Authorization 请求标头的请求的授权上,可以处理基本身份验证,从 base 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");
}
于 2012-06-11T09:55:51.987 回答
0

我发现这真的很有帮助,但是我在开发过程中遇到了一些问题,我想我会分享其中的一些来帮助其他人节省一些时间。

我正在寻找从我的 web 应用程序获取数据到 android 设备的日历中,并且我正在使用 discountasp 作为托管服务。

我遇到的第一个问题是验证在上传到服务器时不起作用,奇怪的是它接受了我的控制面板登录为 discountasp,但不接受我的表单登录。

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

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

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

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

于 2013-09-09T12:29:17.760 回答