Supposedly in Webs.asmx web service we pass on the user credentials and then call GetWebCollection method to get the webs underneath the current site, we expect the web method to return only those webs for which the user has permission to. But this web method actually returns all the webs present underneath the current site.
Let us assume that there are 2 users, User1 and User2. User1 is the site owner and User2 is added to the site collection members group. There is a root site in the site collection and a sub-site (say site1) underneath the site collection. Both the users has access to the root site and the sub-site. Then in the sub-site, site1, we go to Advanced permission settings and remove the permission for the members group. When User1 logs in, he will be able to see both the site collection and the sub-site (site1) as he has permission in both the sites. When User2 logs in, he will be able to see only the root site and not the sub-site ( as his permission is removed in the sub-site). This works perfectly fine in the UI.
When the same is executed via web service passing User2 credentials, the web method returns all the sub-sites. In this case it returns sub-site site1 as well ( though he doesn't have permission on that site). So irrespective of the permission, the web method returns all the sub-sites. The web method initially checks if the credential passed has permission on the site collection level ( in this case the User2 has permission ) and then returns all the sub-sites.
localhost.Webs web = new global::Webs.localhost.Webs(); web.Credentials = new System.Net.NetworkCredential("User2", "test123!", "chnatara2k8"); string sXML = web.GetWebCollection().OuterXml;
Reason for this behavior? Actually the Web Service uses Object Model to return all the Sub Webs, essentially it is the same as SPWeb.Webs call. One important thing is SPWeb.Webs returns all subwebs and it doesn't matter whether the current user has permission or not.
Workaround using SharePoint Object Model - In the SharePoint object model, there is a method called GetSubwebsForCurrentUser, to get the sub-sites specific to a user. So, we can create a custom web service to get subwebs based on a user.
Another possible workaround is to use UserGroup web service. This web service returns all the users for a site. Once we get the list of users for a site, then we can filter down to check if a user has access to the site or not. It's a intricate process to get subwebs for a particular user. For this we also need to create a web service proxy instance.