一步一步实现ReportingServices2008匿名访问
在ReportingServices2005中我们需要匿名访问报表的时候,只需要在IIS里面做下简单设置就可以实现,而在ReportingServices2008(R2)中不在依靠IIS,只是占用的还是80端口而已。其实匿名访问有很多中解决办法,譬如:使用ReportViewer控件、与SharePoint集成等等......
下面我介绍SQL团队技术博客所提供的比较彻底而且通用的方法 。(注:修改配置文件前如果害怕出问题请提前备份)
第一步:编译SQL团队所提供的代码并将所生成的Microsoft.Samples.ReportingServices.AnonymousSecurity.dll文件拷贝到SQL Server的安装目录
1.
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.ReportingServices.Interfaces;
using System.Security.Principal;
using System.Collections.Specialized;
using System.Collections;
namespace Microsoft.Samples.ReportingServices.AnonymousSecurity
{
public class AuthenticationExtension : IAuthenticationExtension
{
/// <summary>
/// You must implement SetConfiguration as required by IExtension
/// </summary>
/// <param name="configuration">Configuration data as an XML
/// string that is stored along with the Extension element in
/// the configuration file.</param>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase")]
public void SetConfiguration(String configuration)
{
// No configuration data is needed for this extension
}
/// <summary>
/// You must implement LocalizedName as required by IExtension
/// </summary>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase")]
public string LocalizedName
{
get
{
return null;
}
}
/// <summary>
/// Indicates whether a supplied username and password are valid.
/// </summary>
/// <param name="userName">The supplied username</param>
/// <param name="password">The supplied password</param>
/// <param name="authority">Optional. The specific authority to use to
/// authenticate a user. For example, in Windows it would be a Windows
/// Domain</param>
/// <returns>true when the username and password are valid</returns>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase")]
public bool LogonUser(string userName, string password, string authority)
{
return true;
}
/// <summary>
/// Required by IAuthenticationExtension. The report server calls the
/// GetUserInfo methodfor each request to retrieve the current user
/// identity.
/// </summary>
/// <param name="userIdentity">represents the identity of the current
/// user. The value of IIdentity may appear in a user interface and
/// should be human readable</param>
/// <param name="userId">represents a pointer to a unique user identity
/// </param>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase")]
public void GetUserInfo(out IIdentity userIdentity, out IntPtr userId)
{
userIdentity = new GenericIdentity("dummy user");
userId = IntPtr.Zero;
}
/// <summary>
/// The IsValidPrincipalName method is called by the report server when
/// the report server sets security on an item. This method validates
/// that the user name is valid for Windows.The principal name needs to
/// be a user, group, or builtin account name.
/// </summary>
/// <param name="principalName">A user, group, or built-in account name
/// </param>
/// <returns>true when the principle name is valid</returns>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase")]
public bool IsValidPrincipalName(string principalName)
{
return true;
}
}
}
namespace Microsoft.Samples.ReportingServices.AnonymousSecurity
{
public class Authorization : IAuthorizationExtension
{
static Authorization()
{
InitializeMaps();
}
/// <summary>
/// Returns a security descriptor that is stored with an individual
/// item in the report server database.
/// </summary>
/// <param name="acl">The access code list (ACL) created by the report
/// server for the item. It contains a collection of access code entry
/// (ACE) structures.</param>
/// <param name="itemType">The type of item for which the security
/// descriptor is created.</param>
/// <param name="stringSecDesc">Optional. A user-friendly description
/// of the security descriptor, used for debugging. This is not stored
/// by the report server.</param>
/// <returns>Should be implemented to return a serialized access code
/// list for the item.</returns>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase")]
public byte[] CreateSecurityDescriptor(
AceCollection acl,
SecurityItemType itemType,
out string stringSecDesc)
{
stringSecDesc = null;
return null;
}
public bool CheckAccess(
string userName,
IntPtr userToken,
byte[] secDesc,
ModelItemOperation modelItemOperation)
{
return true;
}
public bool CheckAccess(
string userName,
IntPtr userToken,
byte[] secDesc,
ModelOperation modelOperation)
{
return true;
}
/// <summary>
/// Indicates whether a given user is authorized to access the item
/// for a given catalog operation.
/// </summary>
/// <param name="userName">The name of the user as returned by the
/// GetUserInfo method.</param>
/// <param name="userToken">Pointer to the user ID returned by
/// GetUserInfo.</param>
/// <param name="secDesc">The security descriptor returned by
/// CreateSecurityDescriptor.</param>
/// <param name="requiredOperation">The operation being requested by
/// the report server for a given user.</param>
/// <returns>True if the user is authorized.</returns>
public bool CheckAccess(
string userName,
IntPtr userToken,
byte[] secDesc,
CatalogOperation requiredOperation)
{
return true;
}
// Overload for array of catalog operations
public bool CheckAccess(
string userName,
IntPtr userToken,
byte[] secDesc,
CatalogOperation[] requiredOperations)
{
return true;
}
// Overload for Report operations
public bool CheckAccess(
string userName,
IntPtr userToken,
byte[] secDesc,
ReportOperation requiredOperation)
{
return true;
}
// Overload for Folder operations
public bool CheckAccess(
string userName,
IntPtr userToken,
byte[] secDesc,
FolderOperation requiredOperation)
{
return true;
}
// Overload for an array of Folder operations
public bool CheckAccess(
string userName,
IntPtr userToken,
byte[] secDesc,
FolderOperation[] requiredOperations)
{
return true;
}
// Overload for Resource operations
public bool CheckAccess(
string userName,
IntPtr userToken,
byte[] secDesc,
ResourceOperation requiredOperation)
{
return true;
}
// Overload for an array of Resource operations
public bool CheckAccess(
string userName,
IntPtr userToken,
byte[] secDesc,
ResourceOperation[] requiredOperations)
{
return true;
}
// Overload for Datasource operations
public bool CheckAccess(
string userName,
IntPtr userToken,
byte[] secDesc,
DatasourceOperation requiredOperation)
{
return true;
}
2.
/// Returns the set of permissions a specific user has for a specific
/// item managed in the report server database. This provides underlying
/// support for the Web service method GetPermissions().
/// </summary>
/// <param name="userName">The name of the user as returned by the
/// GetUserInfo method.</param>
/// <param name="userToken">Pointer to the user ID returned by
/// GetUserInfo.</param>
/// <param name="itemType">The type of item for which the permissions
/// are returned.</param>
/// <param name="secDesc">The security descriptor associated with the
/// item.</param>
/// <returns></returns>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase"), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")]
public StringCollection GetPermissions(string userName, IntPtr userToken,
SecurityItemType itemType, byte[] secDesc)
{
return m_fullPermissions;
}
private static Hashtable m_ModelItemOperNames;
private static Hashtable m_ModelOperNames;
private static Hashtable m_CatOperNames;
private static Hashtable m_FldOperNames;
private static Hashtable m_RptOperNames;
private static Hashtable m_ResOperNames;
private static Hashtable m_DSOperNames;
private static StringCollection m_fullPermissions = new StringCollection();
private const int NrRptOperations = 27;
private const int NrFldOperations = 10;
private const int NrResOperations = 7;
private const int NrDSOperations = 7;
private const int NrCatOperations = 16;
private const int NrModelOperations = 11;
private const int NrModelItemOperations = 1;
// Utility method used to create mappings to the various
// operations in Reporting Services. These mappings support
// the implementation of the GetPermissions method.
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2201:DoNotRaiseReservedExceptionTypes"), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2201:DoNotRaiseReservedExceptionTypes"), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2201:DoNotRaiseReservedExceptionTypes"), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2201:DoNotRaiseReservedExceptionTypes"), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2201:DoNotRaiseReservedExceptionTypes"), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2201:DoNotRaiseReservedExceptionTypes"), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2201:DoNotRaiseReservedExceptionTypes")]
private static void InitializeMaps()
{
// create model operation names data
m_ModelItemOperNames = new Hashtable();
m_ModelItemOperNames.Add(ModelItemOperation.ReadProperties,
OperationNames.OperReadProperties);
if (m_ModelItemOperNames.Count != NrModelItemOperations)
{
//Model item name mismatch
throw new Exception("Model item name mismatch");
}
// create model operation names data
m_ModelOperNames = new Hashtable();
m_ModelOperNames.Add(ModelOperation.Delete,
OperationNames.OperDelete);
m_ModelOperNames.Add(ModelOperation.ReadAuthorizationPolicy,
OperationNames.OperReadAuthorizationPolicy);
m_ModelOperNames.Add(ModelOperation.ReadContent,
OperationNames.OperReadContent);
m_ModelOperNames.Add(ModelOperation.ReadDatasource,
OperationNames.OperReadDatasources);
m_ModelOperNames.Add(ModelOperation.ReadModelItemAuthorizationPolicies,
OperationNames.OperReadModelItemSecurityPolicies);
m_ModelOperNames.Add(ModelOperation.ReadProperties,
OperationNames.OperReadProperties);
m_ModelOperNames.Add(ModelOperation.UpdateContent,
OperationNames.OperUpdateContent);
m_ModelOperNames.Add(ModelOperation.UpdateDatasource,
OperationNames.OperUpdateDatasources);
m_ModelOperNames.Add(ModelOperation.UpdateDeleteAuthorizationPolicy,
OperationNames.OperUpdateDeleteAuthorizationPolicy);
m_ModelOperNames.Add(ModelOperation.UpdateModelItemAuthorizationPolicies,
OperationNames.OperUpdateModelItemSecurityPolicies);
m_ModelOperNames.Add(ModelOperation.UpdateProperties,
OperationNames.OperUpdatePolicy);
if (m_ModelOperNames.Count != NrModelOperations)
{
//Model name mismatch
throw new Exception("Model name mismatch");
}
// create operation names data
m_CatOperNames = new Hashtable();
m_CatOperNames.Add(CatalogOperation.CreateRoles,
OperationNames.OperCreateRoles);
m_CatOperNames.Add(CatalogOperation.DeleteRoles,
OperationNames.OperDeleteRoles);
m_CatOperNames.Add(CatalogOperation.ReadRoleProperties,
OperationNames.OperReadRoleProperties);
m_CatOperNames.Add(CatalogOperation.UpdateRoleProperties,
OperationNames.OperUpdateRoleProperties);
m_CatOperNames.Add(CatalogOperation.ReadSystemProperties,
OperationNames.OperReadSystemProperties);
m_CatOperNames.Add(CatalogOperation.UpdateSystemProperties,
OperationNames.OperUpdateSystemProperties);
m_CatOperNames.Add(CatalogOperation.GenerateEvents,
OperationNames.OperGenerateEvents);
m_CatOperNames.Add(CatalogOperation.ReadSystemSecurityPolicy,
OperationNames.OperReadSystemSecurityPolicy);
m_CatOperNames.Add(CatalogOperation.UpdateSystemSecurityPolicy,
OperationNames.OperUpdateSystemSecurityPolicy);
m_CatOperNames.Add(CatalogOperation.CreateSchedules,
OperationNames.OperCreateSchedules);
m_CatOperNames.Add(CatalogOperation.DeleteSchedules,
OperationNames.OperDeleteSchedules);
m_CatOperNames.Add(CatalogOperation.ReadSchedules,
OperationNames.OperReadSchedules);
m_CatOperNames.Add(CatalogOperation.UpdateSchedules,
OperationNames.OperUpdateSchedules);
m_CatOperNames.Add(CatalogOperation.ListJobs,
OperationNames.OperListJobs);
m_CatOperNames.Add(CatalogOperation.CancelJobs,
OperationNames.OperCancelJobs);
m_CatOperNames.Add(CatalogOperation.ExecuteReportDefinition,
OperationNames.ExecuteReportDefinition);
if (m_CatOperNames.Count != NrCatOperations)
{
//Catalog name mismatch
throw new Exception("Catalog name mismatch");
}
m_FldOperNames = new Hashtable();
m_FldOperNames.Add(FolderOperation.CreateFolder,
OperationNames.OperCreateFolder);
m_FldOperNames.Add(FolderOperation.Delete,
OperationNames.OperDelete);
m_FldOperNames.Add(FolderOperation.ReadProperties,
OperationNames.OperReadProperties);
m_FldOperNames.Add(FolderOperation.UpdateProperties,
OperationNames.OperUpdateProperties);
m_FldOperNames.Add(FolderOperation.CreateReport,
OperationNames.OperCreateReport);
m_FldOperNames.Add(FolderOperation.CreateResource,
OperationNames.OperCreateResource);
m_FldOperNames.Add(FolderOperation.ReadAuthorizationPolicy,
OperationNames.OperReadAuthorizationPolicy);
m_FldOperNames.Add(FolderOperation.UpdateDeleteAuthorizationPolicy,
OperationNames.OperUpdateDeleteAuthorizationPolicy);
m_FldOperNames.Add(FolderOperation.CreateDatasource,
OperationNames.OperCreateDatasource);
m_FldOperNames.Add(FolderOperation.CreateModel,
OperationNames.OperCreateModel);
if (m_FldOperNames.Count != NrFldOperations)
{
//Folder name mismatch
throw new Exception("Folder name mismatch");
}
m_RptOperNames = new Hashtable();
m_RptOperNames.Add(ReportOperation.Delete,
OperationNames.OperDelete);
m_RptOperNames.Add(ReportOperation.ReadProperties,
OperationNames.OperReadProperties);
m_RptOperNames.Add(ReportOperation.UpdateProperties,
OperationNames.OperUpdateProperties);
m_RptOperNames.Add(ReportOperation.UpdateParameters,
OperationNames.OperUpdateParameters);
m_RptOperNames.Add(ReportOperation.ReadDatasource,
OperationNames.OperReadDatasources);
m_RptOperNames.Add(ReportOperation.UpdateDatasource,
OperationNames.OperUpdateDatasources);
m_RptOperNames.Add(ReportOperation.ReadReportDefinition,
OperationNames.OperReadReportDefinition);
m_RptOperNames.Add(ReportOperation.UpdateReportDefinition,
OperationNames.OperUpdateReportDefinition);
m_RptOperNames.Add(ReportOperation.CreateSubscription,
OperationNames.OperCreateSubscription);
m_RptOperNames.Add(ReportOperation.DeleteSubscription,
OperationNames.OperDeleteSubscription);
m_RptOperNames.Add(ReportOperation.ReadSubscription,
OperationNames.OperReadSubscription);
m_RptOperNames.Add(ReportOperation.UpdateSubscription,
OperationNames.OperUpdateSubscription);
m_RptOperNames.Add(ReportOperation.CreateAnySubscription,
OperationNames.OperCreateAnySubscription);
m_RptOperNames.Add(ReportOperation.DeleteAnySubscription,
OperationNames.OperDeleteAnySubscription);
m_RptOperNames.Add(ReportOperation.ReadAnySubscription,
OperationNames.OperReadAnySubscription);
m_RptOperNames.Add(ReportOperation.UpdateAnySubscription,
OperationNames.OperUpdateAnySubscription);
m_RptOperNames.Add(ReportOperation.UpdatePolicy,
OperationNames.OperUpdatePolicy);
m_RptOperNames.Add(ReportOperation.ReadPolicy,
OperationNames.OperReadPolicy);
m_RptOperNames.Add(ReportOperation.DeleteHistory,
OperationNames.OperDeleteHistory);
m_RptOperNames.Add(ReportOperation.ListHistory,
OperationNames.OperListHistory);
m_RptOperNames.Add(ReportOperation.ExecuteAndView,
OperationNames.OperExecuteAndView);
m_RptOperNames.Add(ReportOperation.CreateResource,
OperationNames.OperCreateResource);
m_RptOperNames.Add(ReportOperation.CreateSnapshot,
OperationNames.OperCreateSnapshot);
m_RptOperNames.Add(ReportOperation.ReadAuthorizationPolicy,
OperationNames.OperReadAuthorizationPolicy);
m_RptOperNames.Add(ReportOperation.UpdateDeleteAuthorizationPolicy,
OperationNames.OperUpdateDeleteAuthorizationPolicy);
m_RptOperNames.Add(ReportOperation.Execute,
OperationNames.OperExecute);
m_RptOperNames.Add(ReportOperation.CreateLink,
OperationNames.OperCreateLink);
if (m_RptOperNames.Count != NrRptOperations)
{
//Report name mismatch
throw new Exception("Report name mismatch");
}
m_ResOperNames = new Hashtable();
m_ResOperNames.Add(ResourceOperation.Delete,
OperationNames.OperDelete);
m_ResOperNames.Add(ResourceOperation.ReadProperties,
OperationNames.OperReadProperties);
m_ResOperNames.Add(ResourceOperation.UpdateProperties,
OperationNames.OperUpdateProperties);
m_ResOperNames.Add(ResourceOperation.ReadContent,
OperationNames.OperReadContent);
m_ResOperNames.Add(ResourceOperation.UpdateContent,
OperationNames.OperUpdateContent);
m_ResOperNames.Add(ResourceOperation.ReadAuthorizationPolicy,
OperationNames.OperReadAuthorizationPolicy);
m_ResOperNames.Add(ResourceOperation.UpdateDeleteAuthorizationPolicy,
OperationNames.OperUpdateDeleteAuthorizationPolicy);
if (m_ResOperNames.Count != NrResOperations)
{
//Resource name mismatch
throw new Exception("Resource name mismatch");
}
m_DSOperNames = new Hashtable();
m_DSOperNames.Add(DatasourceOperation.Delete,
OperationNames.OperDelete);
m_DSOperNames.Add(DatasourceOperation.ReadProperties,
OperationNames.OperReadProperties);
m_DSOperNames.Add(DatasourceOperation.UpdateProperties,
OperationNames.OperUpdateProperties);
m_DSOperNames.Add(DatasourceOperation.ReadContent,
OperationNames.OperReadContent);
m_DSOperNames.Add(DatasourceOperation.UpdateContent,
OperationNames.OperUpdateContent);
m_DSOperNames.Add(DatasourceOperation.ReadAuthorizationPolicy,
OperationNames.OperReadAuthorizationPolicy);
m_DSOperNames.Add(DatasourceOperation.UpdateDeleteAuthorizationPolicy,
OperationNames.OperUpdateDeleteAuthorizationPolicy);
if (m_DSOperNames.Count != NrDSOperations)
{
//Datasource name mismatch
throw new Exception("Datasource name mismatch");
}
// Initialize permission collection.
foreach (CatalogOperation oper in m_CatOperNames.Keys)
{
if (!m_fullPermissions.Contains((string)m_CatOperNames[oper]))
m_fullPermissions.Add((string)m_CatOperNames[oper]);
}
foreach (ModelItemOperation oper in m_ModelItemOperNames.Keys)
{
if (!m_fullPermissions.Contains((string)m_ModelItemOperNames[oper]))
m_fullPermissions.Add((string)m_ModelItemOperNames[oper]);
}
foreach (ModelOperation oper in m_ModelOperNames.Keys)
{
if (!m_fullPermissions.Contains((string)m_ModelOperNames[oper]))
m_fullPermissions.Add((string)m_ModelOperNames[oper]);
}
foreach (CatalogOperation oper in m_CatOperNames.Keys)
{
if (!m_fullPermissions.Contains((string)m_CatOperNames[oper]))
m_fullPermissions.Add((string)m_CatOperNames[oper]);
}
foreach (ReportOperation oper in m_RptOperNames.Keys)
{
if (!m_fullPermissions.Contains((string)m_RptOperNames[oper]))
m_fullPermissions.Add((string)m_RptOperNames[oper]);
}
foreach (FolderOperation oper in m_FldOperNames.Keys)
{
if (!m_fullPermissions.Contains((string)m_FldOperNames[oper]))
m_fullPermissions.Add((string)m_FldOperNames[oper]);
}
foreach (ResourceOperation oper in m_ResOperNames.Keys)
{
if (!m_fullPermissions.Contains((string)m_ResOperNames[oper]))
m_fullPermissions.Add((string)m_ResOperNames[oper]);
}
foreach (DatasourceOperation oper in m_DSOperNames.Keys)
{
if (!m_fullPermissions.Contains((string)m_DSOperNames[oper]))
m_fullPermissions.Add((string)m_DSOperNames[oper]);
}
}
/// <summary>
/// You must implement SetConfiguration as required by IExtension
/// </summary>
/// <param name="configuration">Configuration data as an XML
/// string that is stored along with the Extension element in
/// the configuration file.</param>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase"), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2201:DoNotRaiseReservedExceptionTypes"), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2201:DoNotRaiseReservedExceptionTypes")]
public void SetConfiguration(string configuration)
{
}
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase")]
public string LocalizedName
{
get
{
// Return a localized name for this extension
return null;
}
}
}
}
你的项目中还需引用Microsoft.ReportingServices.Interfaces.dll 否则编译会通不过
第二步:修改*:\Program Files\Microsoft SQL Server\MSRS10_50.MSSQLSERVER\Reporting Services\ReportServer 和
*:\Program Files\Microsoft SQL Server\MSRS10_50.MSSQLSERVER\Reporting Services\ReportManager文件中的web.config文件,替换二者中的节点,将
<identity impersonate="true"/>
替换为
<identity impersonate="false"/>
第三步:修改*:\Program Files\Microsoft SQL Server\MSRS10_50.MSSQLSERVER\Reporting Services\ReportServer修改
把
<AuthenticationTypes>
<RSWindowsNegotiate/>
<RSWindowsNTLM/>
</AuthenticationTypes>
<EnableAuthPersistence>true</EnableAuthPersistence>
</Authentication>
修改为
<AuthenticationTypes>
<Custom/>
</AuthenticationTypes>
<EnableAuthPersistence>true</EnableAuthPersistence>
</Authentication>
第四步:修改*:\Program Files\Microsoft SQL Server\MSRS10_50.MSSQLSERVER\Reporting Services\ReportServer修改
在
<Extension Name="Windows" Type="Microsoft.ReportingServices.Authorization.WindowsAuthorization, Microsoft.ReportingServices.Authorization"/>
</Security>
<Authentication>
<Extension Name="Windows" Type="Microsoft.ReportingServices.Authentication.WindowsAuthentication, Microsoft.ReportingServices.Authorization"/>
</Authentication>
节点下,添加
<Extension Name="None" Type="Microsoft.Samples.ReportingServices.AnonymousSecurity.Authorization, Microsoft.Samples.ReportingServices.AnonymousSecurity" />
</Security>
<Authentication>
<Extension Name="None" Type="Microsoft.Samples.ReportingServices.AnonymousSecurity.AuthenticationExtension, Microsoft.Samples.ReportingServices.AnonymousSecurity" />
</Authentication>
到此为止,ReportingServices2008(R2)的匿名访问就大功告成了。
参考资料:
没有找到附件选项,所以大家可以编译上文代码,如有需要AnonymousSecurity.dll 请留下邮箱(诚恳告诉我博客园怎么用附件)