将元素添加到特定用户的公告列表中

时间:2023-01-16 15:41:22

I have a customer request to create a number of announcements based on some data from another database. Most of it seems easy enough but the new elements should be created by the user (login) specified in the input data. I was planning to add the announcements using the list web services but I sure would like to avoid using impersonation in order to get the create user right. Is there a way to assign the correct user as the creator without using impersonation?

我有客户请求根据另一个数据库中的某些数据创建一些公告。大多数似乎很容易,但新元素应该由输入数据中指定的用户(登录)创建。我打算使用列表Web服务添加公告,但我确实希望避免使用模拟以使创建用户正确。有没有办法在不使用模拟的情况下将正确的用户指定为创建者?

4 个解决方案

#1


This may not be the answer you are looking for, but impersonation is pretty easy if you have code running in the GAC on a SharePoint server. You don't need to know any password which many do not realize, so I'll continue assuming that this was the reason you did not want to do impersonation. Here's how to do it.

这可能不是您正在寻找的答案,但如果您在SharePoint服务器上的GAC中运行代码,则模拟非常简单。你不需要知道许多人没有意识到的密码,所以我会继续假设这是你不想冒充的原因。这是怎么做的。

You can connect to SharePoint using the typical constructor you use for SPSite and find the appropriate SPUser object. Once you do that, you can get the UserToken property for that SPUser. Then you'll need to use the SPSite constructor again, but use the overload that provides the SPUserToken. Then anything you do in SharePoint will be done via impersonation. No need to run with elevated privileges.

您可以使用用于SPSite的典型构造函数连接到SharePoint,并查找相应的SPUser对象。完成后,您可以获取该SPUser的UserToken属性。然后,您将需要再次使用SPSite构造函数,但使用提供SPUserToken的重载。然后,您在SharePoint中执行的任何操作都将通过模拟完成。无需使用提升权限运行。

OK, now that I've said it in words, I'll try to guess at the code. It should be something like:

好了,既然我已经用语言说过了,我会试着猜测代码。它应该是这样的:

// Just determine the user token for a particular user
SPUserToken userToken = null;
using (SPSite tempSite = new SPSite("http://sharepointurl"))
{
    using (SPWeb tempWeb = tempSite.OpenWeb())
    {
        // I think this next line works, but I'm going from memory
        // I believe the user needs to have already logged into the site at least once
        SPUser user = tempWeb.AllUsers["username"];
        userToken = user.UserToken;
    }
}

// Now do whatever we want impersonating that user
using (SPSite site = new SPSite("http://sharepointurl", userToken))
{
    using (SPWeb web = site.OpenWeb())
    {
        // Do whatever you want here
    }
} 

#2


I don't think that there is a method to archive this.

我认为没有一种存档方法。

But perhaps this workaround might help. I have to admit I never tested this, it's only an idea how you might solve your problem.

但也许这种解决方法可能有所帮助。我不得不承认我从来没有测试过这个,只知道如何解决你的问题。

You could try this. Create the new announcement with an admin user or with RunWithElevatedPrivileges(). After that use the RunWithElevatedPrivileges() method again and set the "created by" field to the user who should be the actual creator of the announcement. By this way only the "edited by" field should show the "wrong" user.

你可以试试这个。使用admin用户或RunWithElevatedPrivileges()创建新公告。之后再次使用RunWithElevatedPrivileges()方法并将“created by”字段设置为应该是公告的实际创建者的用户。通过这种方式,只有“编辑者”字段应该显示“错误”用户。

I know this is not a very elegant solution but it might work. ;)

我知道这不是一个非常优雅的解决方案,但它可能会奏效。 ;)

#3


I just realized that that my requirement was actually to circumvent the audit trail in SharePoint so I sure hope that it can't be done :-)

我刚刚意识到我的要求实际上是绕过SharePoint中的审计跟踪,所以我当然希望它无法完成:-)

I came up with another solution: I added a new user or group field to the announcement list, and copy the AD-user logon into this field. Any report or view that previously used the "created by" field should now use the new field.

我提出了另一个解决方案:我在公告列表中添加了一个新用户或组字段,并将AD用户登录复制到此字段中。以前使用“创建者”字段的任何报告或视图现在都应使用新字段。

How about the situation where a real user enters a new element in the announcement list then? That will not update the new field with the logged in user!

那么真实用户在公告列表中输入新元素的情况如何呢?这不会使用登录用户更新新字段!

Well, the only solution I could come up with is to add a ListItem Add trigger on the list. When a new element is added I check whether the new field contains a value, is not then I update the new field with the ID of the logged in user. That way the new field should always contain a valid userID.

好吧,我能想到的唯一解决方案是在列表中添加一个ListItem Add触发器。添加新元素时,我检查新字段是否包含值,然后我不会使用登录用户的ID更新新字段。这样,新字段应始终包含有效的userID。

I know this is not an elegant solution, but for the time being it is the best I can think of.

我知道这不是一个优雅的解决方案,但目前它是我能想到的最好的解决方案。

#4


As alluded to in the answer's code comments, if the user has not visited the site at least one time, then there is no user metadata available from which to derive a proper usertoken.

如答案的代码注释中所提到的,如果用户至少没有访问过该站点一次,那么就没有可用的用户元数据可以从中获得正确的usertoken。

With SharePoint 2010, you can simulate a user visit, with the EnsureUser method available from the SPWeb class (this snippet creates the user and also tweaks their profile a bit):

使用SharePoint 2010,您可以使用SPWeb类提供的EnsureUser方法模拟用户访问(此代码段创建用户并稍微调整其配置文件):

SPUser alice = web.EnsureUser(@"MYDOMAIN\alice");
SPList userInfo = web.SiteUserInfoList; //metadata storage of user info

SPListItem item = userInfo.GetItemById(alice.ID);
item["About Me"] = "I am Alice from Mel's Diner";
item.Update();

#1


This may not be the answer you are looking for, but impersonation is pretty easy if you have code running in the GAC on a SharePoint server. You don't need to know any password which many do not realize, so I'll continue assuming that this was the reason you did not want to do impersonation. Here's how to do it.

这可能不是您正在寻找的答案,但如果您在SharePoint服务器上的GAC中运行代码,则模拟非常简单。你不需要知道许多人没有意识到的密码,所以我会继续假设这是你不想冒充的原因。这是怎么做的。

You can connect to SharePoint using the typical constructor you use for SPSite and find the appropriate SPUser object. Once you do that, you can get the UserToken property for that SPUser. Then you'll need to use the SPSite constructor again, but use the overload that provides the SPUserToken. Then anything you do in SharePoint will be done via impersonation. No need to run with elevated privileges.

您可以使用用于SPSite的典型构造函数连接到SharePoint,并查找相应的SPUser对象。完成后,您可以获取该SPUser的UserToken属性。然后,您将需要再次使用SPSite构造函数,但使用提供SPUserToken的重载。然后,您在SharePoint中执行的任何操作都将通过模拟完成。无需使用提升权限运行。

OK, now that I've said it in words, I'll try to guess at the code. It should be something like:

好了,既然我已经用语言说过了,我会试着猜测代码。它应该是这样的:

// Just determine the user token for a particular user
SPUserToken userToken = null;
using (SPSite tempSite = new SPSite("http://sharepointurl"))
{
    using (SPWeb tempWeb = tempSite.OpenWeb())
    {
        // I think this next line works, but I'm going from memory
        // I believe the user needs to have already logged into the site at least once
        SPUser user = tempWeb.AllUsers["username"];
        userToken = user.UserToken;
    }
}

// Now do whatever we want impersonating that user
using (SPSite site = new SPSite("http://sharepointurl", userToken))
{
    using (SPWeb web = site.OpenWeb())
    {
        // Do whatever you want here
    }
} 

#2


I don't think that there is a method to archive this.

我认为没有一种存档方法。

But perhaps this workaround might help. I have to admit I never tested this, it's only an idea how you might solve your problem.

但也许这种解决方法可能有所帮助。我不得不承认我从来没有测试过这个,只知道如何解决你的问题。

You could try this. Create the new announcement with an admin user or with RunWithElevatedPrivileges(). After that use the RunWithElevatedPrivileges() method again and set the "created by" field to the user who should be the actual creator of the announcement. By this way only the "edited by" field should show the "wrong" user.

你可以试试这个。使用admin用户或RunWithElevatedPrivileges()创建新公告。之后再次使用RunWithElevatedPrivileges()方法并将“created by”字段设置为应该是公告的实际创建者的用户。通过这种方式,只有“编辑者”字段应该显示“错误”用户。

I know this is not a very elegant solution but it might work. ;)

我知道这不是一个非常优雅的解决方案,但它可能会奏效。 ;)

#3


I just realized that that my requirement was actually to circumvent the audit trail in SharePoint so I sure hope that it can't be done :-)

我刚刚意识到我的要求实际上是绕过SharePoint中的审计跟踪,所以我当然希望它无法完成:-)

I came up with another solution: I added a new user or group field to the announcement list, and copy the AD-user logon into this field. Any report or view that previously used the "created by" field should now use the new field.

我提出了另一个解决方案:我在公告列表中添加了一个新用户或组字段,并将AD用户登录复制到此字段中。以前使用“创建者”字段的任何报告或视图现在都应使用新字段。

How about the situation where a real user enters a new element in the announcement list then? That will not update the new field with the logged in user!

那么真实用户在公告列表中输入新元素的情况如何呢?这不会使用登录用户更新新字段!

Well, the only solution I could come up with is to add a ListItem Add trigger on the list. When a new element is added I check whether the new field contains a value, is not then I update the new field with the ID of the logged in user. That way the new field should always contain a valid userID.

好吧,我能想到的唯一解决方案是在列表中添加一个ListItem Add触发器。添加新元素时,我检查新字段是否包含值,然后我不会使用登录用户的ID更新新字段。这样,新字段应始终包含有效的userID。

I know this is not an elegant solution, but for the time being it is the best I can think of.

我知道这不是一个优雅的解决方案,但目前它是我能想到的最好的解决方案。

#4


As alluded to in the answer's code comments, if the user has not visited the site at least one time, then there is no user metadata available from which to derive a proper usertoken.

如答案的代码注释中所提到的,如果用户至少没有访问过该站点一次,那么就没有可用的用户元数据可以从中获得正确的usertoken。

With SharePoint 2010, you can simulate a user visit, with the EnsureUser method available from the SPWeb class (this snippet creates the user and also tweaks their profile a bit):

使用SharePoint 2010,您可以使用SPWeb类提供的EnsureUser方法模拟用户访问(此代码段创建用户并稍微调整其配置文件):

SPUser alice = web.EnsureUser(@"MYDOMAIN\alice");
SPList userInfo = web.SiteUserInfoList; //metadata storage of user info

SPListItem item = userInfo.GetItemById(alice.ID);
item["About Me"] = "I am Alice from Mel's Diner";
item.Update();