从 WebMethod 中获取 Sitecore 用户?

Get Sitecore User from within WebMethod?

我想让一些 Sitecore 数据可供非 Sitecore 页面使用。数据将由 JQuery 请求,并且应采用 JSON 格式。我们还需要更新项目、执行工作流操作等。

我们使用的是 Sitecore 6.4,因此据我所知,我们没有可用的 ItemWebAPI 或 MVC 选项。 .NET 是版本 4

我们尝试使用 GET 请求执行此操作,查看查询字符串参数并分支到一个或另一个函数。一个问题是查询字符串的默认最大大小对于我们传递的数据来说太小了,将其设置为允许的最大大小(这显然违反安全最佳实践)也不够可靠。因此,出于这个原因和一些与缓存相关的问题,我们移至 POST。 JQuery 似乎无法以页面想要的方式发送 POST 数据,因此我们不得不引入一些代码来解析请求有效负载文本(即我们不能使用 Request.Form["something"])。我们确实得到了这个工作,但它很难看。在那个和分支之间是一个纠结。

我现在正在查看 WebMethods。除了简化代码之外,WebMethods 还为我们提供了一些免费的东西,例如 json 格式的错误消息、缺少参数的合理错误消息等。

我设置了一个测试页面来发出请求(只有 HTML 和 JQuery)和一个 ASPX 页面来执行 WebMethods。我将 WebMethods 页面的 URL 放在 web.config 的 IgnoreUrlPrefixes 中,如下所述:WebMethod not accessible in Sitecore。我可以使用 Sitecore.Configuration.Factory.GetDatabase(databasename) 访问 Sitecore 数据库。

因此,WebMethods 总体上似乎比我们以前使用的更适合编码和工作。现在我可以阅读代码,我只是在编写可以工作的函数,而不是花费大部分时间来弄清楚为什么事情不工作并实施解决方法。

但我们确实丢失了 Sitecore 上下文,如所引用问题的答案中所述。我一直没能找到获取 Sitecore 用户的方法。

当我发出请求时,我可以在 Chrome 开发人员工具中看到 sitecore_userticket cookie 随请求一起发出。我尝试将该 cookie 的值(以及 Sitecore.Web.Authentication.TicketManager.GetCurrentTicketId 的结果)提供给 Sitecore.Web.Authentication.Ticket.Parse,但我收到解析错误。有没有办法使用该 cookie 来获取用户?

或者有没有办法从 ASP.NET_SessionId cookie 获取用户?

如果这些都不可行,那么管理登录信息的好方法是什么?我知道我可以通过编程方式登录用户,但不希望在浏览器中跟踪 Sitecore 用户名和密码并在每次请求时发送它们。

除了 Sitecore,我对 .NET 没有太多经验。

目前您放置的是普通的 aspx 页面,而不是那样做。在 sitecore 中创建一个新项目,理想情况下应该在内容树的某个奇怪位置,例如

/sitecore/content/home/services/handler

在上面的路径中,services 只是一个文件夹,而 handler 只是另一个项目(可以基于示例模板)。对其应用一个布局,该布局又是一个 aspx 页面(在这里编写代码),您可以在其中放置 webmethods.. 这样它就变成了 Sitecore 请求,如果登录(否则是匿名用户),它将具有 sitecore 上下文和上下文用户,并且您也不需要从工厂获取上下文数据库。 为了确保安全,您可以放置​​基于 Sitecore 的身份验证或您喜欢的任何身份验证。 例如: 以下确保在页面上请求已通过身份验证,否则将重定向到所需页面。

protected override void OnInit(System.EventArgs arguments)
        {
            Assert.ArgumentNotNull(arguments, "arguments");
            checkSecurity(true);
            base.OnInit(arguments);
        }

其次是在页面加载时决定函数并调用它..

protected void Page_Load(object sender, EventArgs e)
        {
            if (!IsPostBack)
            {
                if (Request.QueryString != null && Request.QueryString.Count > 0)
                {
                       string jobName = Request.QueryString["jobName"].ToString();
                       string cacheName = Request.QueryString["cacheName"].ToString();
                       StringBuilder sbAjax = null;
                    if (jobName!=null && jobName.Length > 0)
                    {
                             if (jobName="")
                        {
                           sbAjax=callSomething();
                        this.Page.Response.Clear();
                        if (sbAjax != null)
                            this.Page.Response.Write(sbAjax.ToString());
                        else
                            this.Page.Response.Write("");
                            this.Page.Response.End();
                        }
                     }
                }
           }
}
private StringBuilder callSomething()
{
//Do Something
}

在重新阅读评论中提到的问题@Gabber (Display original Sitecore username instead of what's currently typed in) 后,我有了一个可行的解决方案。简而言之,我可以根据在创建 Sitecore 帐户时设置的底层 System.Web.Security.MembershipUser 对用户进行身份验证。访问者可以使用他或她的 Sitecore 用户名和密码。然后,我可以使用 System.Web.Security.FormsAuthentication.SetAuthCookie 设置 AuthCookie,每当我需要 Sitecore 用户时,我都可以从 HttpContext.Current.Request.Cookies[FormsAuthentication.FormsCookieName] 获取域和用户名,并将其提供给 Sitecore.Security.Accounts.User.FromName 到 return Sitecore 用户.

有一点不太好,如果用户已经登录到 Sitecore,他们将不得不再次进行身份验证以设置 MembershipUser 的 cookie(即我没有得到它来获取当前登录 Sitecore 用户的 Sitecore 身份验证)。我认为这对我的目的来说是可以的。大多数访问 WebMethod-fed 纯 html 页面的人无论如何都不会是 CMS 用户。但是最好避免那些已经登录的人再次登录。

[WebMethod]
public static bool login(string user, string password, string domain)
{
    bool valid = System.Web.Security.Membership.ValidateUser(domain + "\" + user, password);
    if (valid)
    {
        System.Web.Security.FormsAuthentication.SetAuthCookie(domain + "\" + user, true);
        return true;
    }
    return false;
}

[WebMethod]
public static string getuser()
{
    HttpCookie authCookie = HttpContext.Current.Request.Cookies[FormsAuthentication.FormsCookieName];
    FormsAuthenticationTicket ticket = FormsAuthentication.Decrypt(authCookie.Value);
    string u = ticket.Name;

    Dictionary<string, string> responseDict = new Dictionary<string, string>(); 

    User user = Sitecore.Security.Accounts.User.FromName(u,false);
    {
        responseDict["domain"] = user.Domain.Name;
        responseDict["user"] = user.Name;
        responseDict["displayname"] = user.DisplayName;
        responseDict["email"] = user.Profile.Email;
        responseDict["fullname"] = user.Profile.FullName;                
    }

    return JsonConvert.SerializeObject(responseDict, Formatting.Indented);
}

这是我用来测试这些网络方法的普通 html 页面:

<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
</head>
<body>

    <p>domain <input type="text" name="domain" id="domain"/></p>
    <p>user <input type="text" name="user" id="user"/></p>
    <p>password<input type="text" name="password" id="password"/></p>
    <div class="gettoken button">
        <p>Get Token</p>
    </div>
    <p class="tokenresult">token result</p>

    <hr/>

    <div class="getuserinfo button">
        <p>Get User Info</p>
    </div>
    <p class="userresult">result</p>

    <hr/>

    <script>
    $('div.gettoken').click(function ()
    {
        var user = $('#user').val();
        var domain = $('#domain').val();
        var password = $('#password').val();

        $.ajax({
            type: "POST",
            url: "http://sitecore/apis/scitemapi.aspx/setauthcookie",
            data: '{"domain":"' + domain + '", "user": "' + user + '", "password":"' + password + '"}',
            contentType: "application/json; charset=utf-8",
            success: function (msg)
            {
                $("p.tokenresult").text(msg.d);
            }
        });
    });

    $('div.getuserinfo').click(function ()
    {
        $.ajax({
            type: "POST",
            url: "http://sitecore/apis/scitemapi.aspx/getuser",
            data: '{}',
            contentType: "application/json; charset=utf-8",
            success: function (msg2)
            {
                $("p.userresult").text(msg2.d);
            }
        });
    });


    </script>
    <style>

    html{
        font-family:tahoma;
        }

    .button{
        background-color:blue;
        color:white;
        border:1px solid black;
        border-radius:4px;  
        width:12em;
        text-align:center;
        margin-top:1em;
        padding:.5em;
        }

    </style>
</html>