使用Global Admin帐户在线访问被拒绝的Office 365/SharePoint

问题描述:

自从两天后解决一个问题后,我就发疯了.问题是;

I am going crazy since two days solving an issue. The problem is;

我正在制作一个控制台APP,该APP正在使用全局管理员帐户(在进行新订阅时指定为admin)与SharePoint Online通讯.我想要实现的是,我想使用CSOM向Office 365的每个网站集和子网站添加自定义操作.该代码可以正常工作,除了在注册时由Office 365预先创建的根网站集上(即 https://xyz.sharepoint.com )

I am making a console APP which is talking to SharePoint Online using global admin account (One which was specified as admin while making a new subscription). What I am trying to achieve is, I want to add a custom action using CSOM to each site collection and subsite of office 365. That code works fine except on the root site collection which is pre-created by office 365 while signing up (i.e. https://xyz.sharepoint.com)

对于任何用于根网站收集的租户,它给我以下错误;

For any tenant for root site collection, it gives me below error;

{ "SchemaVersion":"15.0.0.0","LibraryVersion":"16.0.3912.1201","ErrorInfo":{ "ErrorMessage":访问被拒绝.您没有执行权限 此操作或访问此 资源.," ErrorValue:null," TraceCorrelationId:" 2a47fd9c-c07b-1000-cfb7-cdffbe3ab83a," ErrorCode:-2147024891," ErrorTypeName:" System.UnauthorizedAccessException },"TraceCorrelationId":"2a47fd9c-c07b-1000-cfb7-cdffbe3ab83a"}

{ "SchemaVersion":"15.0.0.0","LibraryVersion":"16.0.3912.1201","ErrorInfo":{ "ErrorMessage":"Access denied. You do not have permission to perform this action or access this resource.","ErrorValue":null,"TraceCorrelationId":"2a47fd9c-c07b-1000-cfb7-cdffbe3ab83a","ErrorCode":-2147024891,"ErrorTypeName":"System.UnauthorizedAccessException" },"TraceCorrelationId":"2a47fd9c-c07b-1000-cfb7-cdffbe3ab83a" }

现在,该用户是全局管理员.我还再次将该用户添加为网站集管理员.

Now the user is global admin. I also added again that user as site collection admin.

同一段代码在其他网站集(搜索网站集,任何新创建的网站集...)上都可以正常工作.

The same piece of code works fine on other site collections (search site collection, any newly made site collection...).

这是代码;

        using (ClientContext spcollContext = new ClientContext(web.Url))
        {
            SecureString passWord = new SecureString();
            foreach (char c in strAdminPassword.ToCharArray()) passWord.AppendChar(c);
            SharePointOnlineCredentials creds = new SharePointOnlineCredentials(strAdminUser, passWord);
            spcollContext.Credentials = creds;
            Web currentweb = spcollContext.Web;
            spcollContext.Load(currentweb);
            spcollContext.ExecuteQuery();

       //     authCookie = creds.GetAuthenticationCookie(new Uri(web.Url));

            var existingActions2 = currentweb.UserCustomActions;
            spcollContext.Load(existingActions2);
            spcollContext.ExecuteQuery();
            var actions2 = existingActions2.ToArray();
            foreach (var action in actions2)
            {
                if (action.Description == "CustomScriptCodeForEachsite" &&
                    action.Location == "ScriptLink")
                {
                    action.DeleteObject();
                    spcollContext.ExecuteQuery();
                }
            }

            var newAction2 = existingActions2.Add();
            newAction2.Description = "CustomScriptCodeForEachsite";
            newAction2.Location = "ScriptLink";

            newAction2.ScriptBlock = scriptBlock;
            newAction2.Update();
            spcollContext.Load(currentweb, s => s.UserCustomActions);
            spcollContext.ExecuteQuery(); // GETTING ERROR ON THIS LINE. 
        }

注意:上面的错误是Fiddler跟踪.

Note: Above error is Fiddler traces.

此行为很可能是由

Most probably this behavior is caused by Custom Script feature, basically the issue occurs when the Custom Script feature is turned off

如何验证?

您可以使用以下控制台应用程序验证站点权限:

You could verify the site permissions using the following console app:

using (var ctx = GetContext(webUri, userName, password))
{
    var rootWeb = ctx.Site.RootWeb;
    ctx.Load(rootWeb, w => w.EffectiveBasePermissions);
    ctx.ExecuteQuery();
    var permissions = rootWeb.EffectiveBasePermissions;
    foreach (var permission in Enum.GetValues(typeof(PermissionKind)).Cast<PermissionKind>())
    {
        var permissionName = Enum.GetName(typeof(PermissionKind), permission);
        var hasPermission = permissions.Has(permission);
        Console.WriteLine("Permission: {0}, HasPermission: {1}", permissionName, hasPermission);
    }   
}

其中

public static ClientContext GetContext(Uri webUri, string userName, string password)
{
    var securePassword = new SecureString();
    foreach (var ch in password) securePassword.AppendChar(ch);
    return new ClientContext(webUri) {Credentials = new SharePointOnlineCredentials(userName, securePassword)};
}

SP.PermissionKind.AddAndCustomizePages 设置为 False ,添加用户自定义操作时会出现拒绝访问"错误.

When SP.PermissionKind.AddAndCustomizePages is set to False, the Access denied error occurs while adding user custom action.

解决方案

根据

对于通过自助服务创建的网站,自定义脚本通过以下方式禁用: 默认

For self-service created sites, custom scripting is disabled by default

Solution: enable Allow users to run custom scripts on self-service created sites

要从SharePoint管理中心启用或禁用脚本编制

To enable or disable scripting from the SharePoint admin center

  1. 使用您的工作或学校帐户登录Office 365.
  2. 转到SharePoint管理中心.
  3. 选择设置.
  4. 在自定义脚本"下选择:

  1. Sign in to Office 365 with your work or school account.
  2. Go to the SharePoint admin center.
  3. Select Settings.
  4. Under Custom Script choose:

  • 防止用户在个人网站上运行自定义脚本或允许" 用户在个人网站上运行自定义脚本.

  • Prevent users from running custom script on personal sites or Allow users to run custom script on personal sites.

防止用户在用户创建的网站上运行自定义脚本,或者 允许用户在自助创建的网站上运行自定义脚本.

Prevent users from running custom script on user created sites or Allow users to run custom script on self-service created sites.


由于通过SharePoint Online管理中心对脚本设置进行的任何更改最多可能需要 24小时才能生效,因此您可以立即在特定网站集上启用脚本>通过CSOM API( SharePoint在线客户端组件SDK )如下所示:


Since any change to the scripting setting made through the SharePoint Online admin center may take up to 24 hours to take effect, you could enable scripting on a particular site collection immediately via CSOM API (SharePoint Online Client Components SDK) as demonstrated below:

public static void DisableDenyAddAndCustomizePages(ClientContext ctx, string siteUrl)
{
    var tenant = new Tenant(ctx);
    var siteProperties = tenant.GetSitePropertiesByUrl(siteUrl, true);
    ctx.Load(siteProperties);
    ctx.ExecuteQuery();

    siteProperties.DenyAddAndCustomizePages = DenyAddAndCustomizePagesStatus.Disabled;
    var result = siteProperties.Update();
    ctx.Load(result);
    ctx.ExecuteQuery();
    while (!result.IsComplete)
    {
        Thread.Sleep(result.PollingInterval);
        ctx.Load(result);
        ctx.ExecuteQuery();
    }
}

用法

using (var ctx = GetContext(webUri, userName, password))
{
    using (var tenantAdminCtx = GetContext(tenantAdminUri, userName, password))
    {                  
         DisableDenyAddAndCustomizePages(tenantAdminCtx,webUri.ToString());
    }
    RegisterJQueryLibrary(ctx);
 }

其中

public static void RegisterJQueryLibrary(ClientContext context)
{
    var actions = context.Site.UserCustomActions;
    var action = actions.Add();
    action.Location = "ScriptLink";
    action.ScriptSrc = "~SiteCollection/Style Library/Scripts/jQuery/jquery.min.js";
    action.Sequence = 1482;
    action.Update();
    context.ExecuteQuery();
}