2

MVCアプリケーションでiCalendarファイル(.ics)を提供しようとしています。

これまでのところ、正常に動作しています。カレンダーのURLをサブスクライブしているiPhoneを持っていますが、今度は各ユーザーにパーソナライズされたカレンダーを提供する必要があります。

iPhoneでカレンダーを購読するときに、ユーザー名とパスワードを入力できますが、MVCアプリでこれらにアクセスする方法がわかりません。

認証の仕組みと実装方法の詳細はどこにありますか?

4

2 に答える 2

2

必要なのは基本認証であることがわかります。半分は機能していましたが、IIS構成が邪魔になりました。したがって、Authorizationヘッダーがないときに401応答を返すだけで、クライアント(iPhoneなど)はカレンダーをサブスクライブするためにユーザー名/パスワードを要求します。

Authorizationリクエストヘッダーがあるリクエストの承認時に、基本認証を処理して、base64でエンコードされた文字列からユーザー名とパスワードを取得できます。

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オプションを選択する必要がありました。

最後に、URLの先頭にhttp://ではなくwebcal://を追加する必要があることがわかりました。

また、上記のコードはロール入力変数を無視し、常に何も渡さないため、カレンダールーチン内でロールベースのチェックを実行するか、ロール変数を処理するために上記のコードを変更する必要がある場合があるので注意してください。

于 2013-09-09T12:29:17.760 に答える