【问题标题】:Sharepoint 2013 MVC 5 provider-hosted app. Fails to authenticate on HttpPost using [SharePointContextFilter]Sharepoint 2013 MVC 5 提供商托管的应用程序。无法使用 [SharePointContextFilter] 在 HttpPost 上进行身份验证
【发布时间】:2014-07-12 18:50:33
【问题描述】:

在过去的一周里,我一直在苦苦挣扎,无法解决共享点提供商托管应用的正确身份验证问题。

我目前正在为一家公司的在线 Sharepoint 开发一个 sharepoint 应用程序。我正在使用 Visual Studio 2013。我将该应用程序作为云服务部署在公司的 Windows Azure 门户上。当我需要制作 HttpPost 时,一切都很顺利,然后应用程序无法进行身份验证。控制器的设计如下:

    [SharePointContextFilter]
    public ActionResult Index()
    {
        UserSingleton user_temp = UserSingleton.GetInstance();

        User spUser = null;

        SharePointContext spContext = SharePointContextProvider.Current.GetSharePointContext(HttpContext);

        using (var clientContext = spContext.CreateUserClientContextForSPHost())
        {
            if (clientContext != null)
            {
                spUser = clientContext.Web.CurrentUser;

                clientContext.Load(spUser, user => user.Title, user => user.Email);

                clientContext.ExecuteQuery();

                ....code....

            }
        }

           ....code....

        return View();
    }

加载索引页面很顺利,该操作创建了用户上下文,一切都很好。当我尝试按如下方式提交 HttpPost 时,问题就出现了:

    [HttpPost]
    [ValidateAntiForgeryToken]
    [SharePointContextFilter]
    public ActionResult GetService(System.Web.Mvc.FormCollection fc)
    {
        PlannedHours ph = this.PopulateModel(fc);

        if (ph == null)
            return View("NoInfoFound");

        ViewData["PlannedHours"] = ph;

        return View("Index");
    }

当我通过发布按钮调用它时,我收到“无法确定您的身份。请通过启动安装在您网站上的应用重试。” Shared/Error.cshtml 视图。问题是,当我删除 [SharePointContextFilter] 时它可以工作,但这意味着请求没有通过 [SharePointContextFilter] 因此它没有正确验证?或者是吗?因为它无法验证用户的合法性。

当我不删除 [SharePointContextFilter] 并调用帖子时,我注意到一件事,然后 url 最终没有 {StandardTokens} 查询。是不是应该是这样 - 我的意思是它就像 hostname.com/Home/GetService 一样,但是当我使用 actionlink 时,spcontext.js 总是将 {StandardTokens} 查询附加到基本 url - smth 就像 hostname.com/Home /ActionNAme/?SPHostUrl=https%3A%2F%2FSHAREPOINTPAGEURL....

我注意到的是,我在没有附加查询的情况下调用 hostname.com/Home/ActionNAme/ 它未能通过 [SharePointContextFilter]。

我对 sharepoint 2013 和 MVC 5 ( Razor ) 还很陌生,所以如果您知道为什么我的 HttpPost 未能通过 [SharePointContextFilter],请尝试解释我或提供任何建议。我尝试过使用 HttpGet 但是,当我调用具有 [SharePointContextFilter] 并附加 SPHostUrl= 令牌的 HttpGet 时,它可以工作。但是我不能使用 [ValidateAntiForgeryToken]。由于 [SharePointContextFilter] 总是检查用户的合法性,因此在这样的应用程序中是否甚至需要 [ValidateAntiForgeryToken]?我现在很困惑。网上有大量资料可供阅读,没有什么可以解释何时附加这些标准令牌,何时使用 [SharePointContextFilter] 等。事实上,我正在开发一个共享点应用程序,这是我的第一次。在过去的 3 周里,我一直在研究和编码。所以我的知识还很有限,在回答时请记住这一点。在此先感谢,我希望我能对正在发生的事情有所了解!

------------------更新----------------- ----------------------

好的,快速更新。我发现了一些相当奇怪的东西。 SharePointContextFilterAttribute.cs

    public class SharePointContextFilterAttribute : ActionFilterAttribute
    {
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        if (filterContext == null)
        {
            throw new ArgumentNullException("filterContext");
        }

        Uri redirectUrl;
        switch (SharePointContextProvider.CheckRedirectionStatus(filterContext.HttpContext, out redirectUrl))
        {
            case RedirectionStatus.Ok:
                return;
            case RedirectionStatus.ShouldRedirect:
                filterContext.Result = new RedirectResult(redirectUrl.AbsoluteUri);
                break;
            case RedirectionStatus.CanNotRedirect:
                filterContext.Result = new ViewResult { ViewName = "Error" };
                break;
        }
    }
}

总是返回最后一种情况( RedirectionStatus.CanNotRedirect ),因为 SharePointContextProvider.CheckRedirectionStatus(filterContext.HttpContext, out redirectUrl) 方法包含一些我无法理解的内容。

首先:

     Uri spHostUrl = SharePointContext.GetSPHostUrl(httpContext.Request);

        if (spHostUrl == null)
        {
            return RedirectionStatus.CanNotRedirect;
        }

好的,我明白 - 如果 httpContext.Request 不包含 spHostUrl,它将无法重定向。出于某种原因,它必须存在。

但是如下:

    if (StringComparer.OrdinalIgnoreCase.Equals(httpContext.Request.HttpMethod,                    "POST"))
        {
            return RedirectionStatus.CanNotRedirect;
        }

等等什么?!?不允许发帖?!!?这里发生了什么?我真的不知道我做错了什么还是什么?我什至可以玩 SharePointContext.cs 吗?我真的需要有人来澄清到底发生了什么......我将不胜感激!

【问题讨论】:

  • 你有没有想过这个问题? Microsoft 尚未就这种方法的工作原理提供任何更新。
  • 您好,很遗憾,我还没有弄清楚,因为我必须交付我的项目,并且在与一些同事讨论后,我只使用了 HTTP GET 而不是 POST。它违反了协议,但由于 MS 在解决新技术方面的问题方面如此之快,我们别无选择。我会回到它,只有在 MS 方面进行了一些适当的更新之后......你也可以通过 Post/Redirect/Get 模式来解决它,但它实际上或多或少就像使用 GET 来代替。
  • 我不确定我是否跟随。 SharePoint 正在我的应用程序上进行 POST。你是说我的应用程序必须实现一个 POST 控制器方法吗?我无法控制 sharePoint 如何重定向到我。
  • 我在这里找到了另一个工作 link Nicolae Anghel

标签: asp.net-mvc-5 sharepoint-2013


【解决方案1】:

上述解决方案对我不起作用。我的帖子也有同样的问题,但对我来说是

return RedirectToAction("Index");

导致错误。

我改成:

return RedirectToAction("Index", new {SPHostUrl = SharePointContext.GetSPHostUrl(HttpContext.Request).AbsoluteUri});

它成功了。

我不确定这是否是您的问题的解决方案,因为您正在执行返回视图,但它可能对某人有所帮助:)

【讨论】:

  • 嘿,是的,这也是我遇到的问题,但这与我寻求帮助的问题不同:) 但是,你是对的,你总是需要通过 SpHostUrl重定向时的令牌。
  • 我希望我能给你超过1分!这在狩猎了几个小时后救了我。谢谢!
【解决方案2】:

我遇到了同样的问题,花了几天时间解决了这个问题。我不知道为什么 SharePointContextFilter 不能正常工作并且没有重定向。所以我的应用程序是通过 POST 方法启动的,刷新页面时我有重新提交表单确认对话框。我还收到“无法确定您的身份。请启动安装在您网站上的应用程序重试。”。

为了解决我使用Post/Redirect/Get 模式的问题。我将我的 Index 操作更改为 RedirectToAction 到另一个 IndexGet 操作。但是你应该有两个 IndexGet 方法——用于发布和获取。

最后我为此做了三个动作。索引操作重定向到 POST IndexGet 操作:

    public ActionResult Index()
    {            
        return RedirectToAction("IndexGet");
    }

Post 和 Get 的两个 IndexGet 方法具有相同的代码:

    [HttpPost]
    public ActionResult IndexGet(string tmp)
    {
        //your code from Index action
        return View();
    }

    [HttpGet]
    public ActionResult IndexGet()
    {
        //your code from Index action
        return View();
    }

所以它以这样的方式工作:在开始时通过 POST 调用 Index 操作。它重定向到 POST IndexGet 操作,在此位置 SharePointContextFilter 正常工作并通过 GET 调用 IndexGet。这种模式解决了我的问题。

【讨论】:

  • 您好,我不确定您是否正确理解了我的问题。另外,我没有看到您使用 [SharepointContextFilter] 数据注释。这使您在控制器中的所有操作都是公开的,因此未经共享点身份验证的用户可以访问它们。这对我来说至关重要。
  • @Lys,很抱歉忘记了 [SharePointContextFilterAttribute]。我在基本控制器中使用它。所以我所有的动作都使用它。在您的更新中,您写道 SharePointContextFilterAttribute 始终返回 RedirectionStatus.CanNotRedirect。我有同样的。我不知道为什么 Sharepoint online 无法通过 GET 方法调用 RedirectionStatus.ShouldRedirect 来刷新我的应用程序。所以我使用 PRG 模式来强制重定向。它对我有用。
【解决方案3】:

我同意 Libin/user24176!

当从一个控制器的操作导航到另一个时,SharePoint 引用 SPHostUrl 来获取上下文。但是,当我发现问题是由于缺少 SPHostUrl 时,我尝试在 RedirectToAction 方法中附加 SPHostUrl,一切都开始工作了。

解决方案: 将 SPHostUrl 附加到 RedirectToAction 方法调用 使用 Controller 的 RedirectToAction 方法将用户重定向到另一个 Action 是一种常见的场景,它是重载的。

默认情况下,您可以使用以下代码行轻松地将用户重定向到“另一个”操作

return RedirectToAction("Another");

假设您从 HomeController 执行此调用,您的浏览器将被重定向到 www.PHapp.com/Home/Another 并且 SPHostUrl 再次丢失

要解决此问题,您可以轻松地将 SPHostUrl 传递给 RedirectToAction 方法,或者您可以覆盖 BaseController 类中的方法(每个 MVC 应用程序都应具有)并将实际重定向更改为类似这样的内容

return RedirectToAction("Another",new 
{ SPHostUrl = SharePointContext.GetSPHostUrl(HttpContext.Request).AbsoluteUri }); 

这将强制您的浏览器使用以下网址请求操作 www.PHapp.com/Home/Fallback?SPHostUrl=..."

当然,在使用 MVC 构建 SharePoint 应用程序时还有其他陷阱,但能否从每个控制器方法创建 SharePoint 上下文是一种关键,具体取决于客户的要求。

---# 更新 2--- 最初我在 IE 中工作,该站点在 IE 较低版本中加载没有 SPHostURL 的控制器操作,后来我更新了 _Layouts HTML- 标题部分,强制 IE 在最新版本中打开:

<meta http-equiv="X-UA-Compatible" content="IE=Edge" />

此后,MVC PH App 将 SPhotosURL 绑定到所有 Action 链接中。

【讨论】:

    【解决方案4】:

    我有同样的错误。如果它不包含有错误的表单数据,则在这种情况下发布请求是正常的。例如这样的 Post 请求可以包含这样的错误:

    SPErrorInfo:端点地址''与应用程序的端点''不匹配。

    如果您在 POST 中看到此类错误,您的 SharePointContextFilterAttribute 类肯定会按照您在问题中的描述使用 POST 引发错误。但是如果 POST 请求是一个“好”的请求,它将在抛出错误并返回重定向 OK 之前进行处理。

    因此,这里的任务是不改变 SharePointContextFilterAttribute 的行为,而是解决问题。例如,上面的错误表明我为我的 ClientID 指定了错误的域名。您可以在 Microsoft Seller Dashboard 中生成 ClientID,它需要指定域。如果它与托管提供商托管应用程序的域不同,它将引发错误。

    https 也是一样...如果重定向 URL 不是 HTTPS,它也会抛出错误。由于某些原因,当您从 Visual Studio 启动应用程序时,它不会引发此类错误,但如果您将应用程序部署到 App Catalog,则会引发此类错误。

    因此,我建议您打开 Fiddler 并研究您的 POST 要求。您很可能会看到错误,它清楚地解释了问题。

    【讨论】:

      【解决方案5】:

      您可能在重定向操作中丢失了 Sharepoint 上下文。

      从 29 分钟开始观看来自 SP 会议的演示。您描述的错误是故意产生的,并提供了解决方案(在新的 RedirectAction 中提供 Sharepoint Context)

      https://youtu.be/EnT5FtTeWA4?t=28m57s

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-10-15
        • 2015-06-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-03-04
        • 2014-10-28
        • 2020-09-17
        相关资源
        最近更新 更多