Dyl*_*tie 6 permissions wsh filesystemobject asp-classic
我有一个经典的ASP页面 - 用JScript编写 - 使用Scripting.FileSystemObject将文件保存到网络共享 - 而且它不起作用.("没有权限")
ASP页面在IIS下使用Windows身份验证运行,并启用了模拟.
如果我通过CScript.exe在本地运行以下代码块:
var objNet = new ActiveXObject("WScript.Network");
WScript.Echo(objNet.ComputerName);
WScript.Echo(objNet.UserName);
WScript.Echo(objNet.UserDomain);
var fso = new ActiveXObject("Scripting.FileSystemObject");
var path = "\\\\myserver\\my_share\\some_path";
if (fso.FolderExists(path)) {
WScript.Echo("Yes");
} else {
WScript.Echo("No");
}
Run Code Online (Sandbox Code Playgroud)
我得到(预期)输出:
MY_COMPUTER
dylan.beattie
MYDOMAIN
Yes
Run Code Online (Sandbox Code Playgroud)
如果我在.ASP页面中运行相同的代码,则将Response.Write替换为WScript.Echo,我得到以下输出:
MY_COMPUTER
dylan.beattie
MYDOMAIN
No
Run Code Online (Sandbox Code Playgroud)
现在 - 我的理解是WScript.Network对象将检索实际运行代码的线程的当前安全凭证.如果这是正确的 - 那么为什么在同一个域上的同一个用户从CScript.exe到ASP获得不同的结果?如果我的ASP代码的运行为dylan.beattie,那么为什么我不能看到网络共享?如果它不像dylan.beattie 那样运行,为什么WScript.Network会认为它是?
你的问题很清楚。在当前的实现中,您只能模拟用户而没有委派。我不想重复斯蒂芬·马丁已经写过的信息。我只想添加至少三个解决方案。斯蒂芬·马丁提出的经典授权方式只是一种方式。您可以在这里阅读更多方法:http://msdn.microsoft.com/en-us/library/ff647404.aspx#paght000023_delegation。我看到您解决问题的三种实用方法:
将用户的模拟令牌转换为具有模拟委托级别的令牌或新的主令牌。您可以根据DuplicateToken或来执行此操作DuplicateTokenEx。
使用S4U2Self(请参阅http://msdn.microsoft.com/en-us/magazine/cc188757.aspx和http://msdn.microsoft.com/en-us/library/ms998355.aspx)从以下位置接收新令牌旧的涉及一个简单的 .NET 语句WindowsIdentity wi = new WindowsIdentity(identity);
您可以用一个固定帐户访问另一台服务器。它可以是 IIS 应用程序池帐户上的计算机帐户。它可以是另一个固定定义的帐户,仅用于访问文件系统。
了解运行 IIS 的服务器上的 Windows Server 版本以及您的域的 Active Directory 中的域功能级别非常重要(如果您选择域,您可以在“Active Directory 域和信任”工具中看到这一点)并选择“提升域功能级别”)。了解 IIS 的应用程序池在哪个帐户下运行也很有趣。
第一种和第三种方法总是有效的。第三种方法可能对您的环境和文件系统中的当前权限不利。第二个非常优雅。它允许控制从 IIS 访问哪些服务器(文件服务器)。这种方式有一些限制,并且需要在 Active Directory 中完成一些工作。
由于您使用经典 ASP,因此必须创建一个小型可编写脚本的软件组件来支持您的实施。
您更喜欢哪种方式?
根据评论中的问题进行更新:因为您使用经典 ASP,所以您不能直接使用 Win32 API,但您可以在 VB6 或 .NET 中编写一个小型 COM 组件,其中使用您需要的 API。例如,您可以使用http://support.microsoft.com/kb/248187/en中的代码。但你应该在里面做一些其他的事情。所以我现在解释一下哪个 Win32 API 可以帮助您使用令牌和模拟完成您需要的一切。
首先对模仿进行一个简单的解释。一切都很容易。进程运行时始终有一个主要令牌。可以向任何线程分配另一个令牌(线程令牌)。为此,需要拥有用户的令牌hUserToken并调用 API ImpersonateLoggedOnUser(hUserToken);。
要返回到原始进程令牌(仅适用于当前线程),您可以调用RevertToSelf()function. IIS 将接收并模拟您的用户令牌,因为您是这样配置您的网站的。RevertToSelf()要返回到原始进程令牌,您应该在自定义 COM 组件中实现函数调用。也许,如果您不需要在 ASP 页面中执行任何操作,就足够了,但我建议您更加小心,并在对文件进行操作之前将当前用户令牌保存在变量中。然后,您对文件系统进行所有操作,最后将用户令牌重新分配回当前线程。您可以将模拟令牌分配给线程SetThreadToken(NULL,hUserToken);。要提供(保存)当前线程令牌(在您的情况下为用户令牌),您可以使用OpenThreadTokenAPI。它必须有效。
更新2:也许在一个 ASP 页面末尾使用RevertToSelf()函数对您来说已经没问题了。对应的C#代码可以是这样:
在 C# 中创建一个类型为“类库”、名称为 的新项目LoginAdmin。将以下代码粘贴到里面
using System;
using System.Runtime.InteropServices;
namespace LoginAdmin {
[InterfaceTypeAttribute (ComInterfaceType.InterfaceIsDual)]
public interface IUserImpersonate {
[DispId(1)]
bool RevertToSelf ();
}
internal static class NativeMethods {
[DllImport ("advapi32.dll", SetLastError = true)]
internal static extern bool RevertToSelf ();
}
[ClassInterface (ClassInterfaceType.AutoDual)]
public class UserImpersonate : IUserImpersonate {
public UserImpersonate () { }
public bool RevertToSelf () {
return NativeMethods.RevertToSelf();
}
}
}
Run Code Online (Sandbox Code Playgroud)
检查“构建”部分“注册 COM 互操作”中的项目属性。在项目的“签名”部分中,选中对程序集进行签名,并在“选择强名称密钥文件”中选择<New...>,然后键入任何文件名和密码(或选中“保护我的密钥...”)。最后,您应该在项目的 Properties 部分中修改 AssemblyInfo.cs 中的一行:
[assembly: ComVisible (true)]
Run Code Online (Sandbox Code Playgroud)
编译该项目后,您将获得两个文件:LoginAdmin.dll 和 LoginAdmin.tlb。该 DLL 已在当前计算机上注册。要注册(如果在另一台计算机上),请使用RegAsm.exe。
要在 ASP 页上测试此 COM DLL,您可以执行以下操作
<%@ Language="javascript" %>
<html><body>
<% var objNet = Server.CreateObject("WScript.Network");
Response.Write("Current user: ");Response.Write(objNet.UserName);Response.Write("<br/>");
Response.Write("Current user's domain: ");Response.Write(objNet.UserDomain);Response.Write("<br/>");
var objLoginAdmin = Server.CreateObject("LoginAdmin.UserImpersonate");
var isOK = objLoginAdmin.RevertToSelf();
if (isOK)
Response.Write("RevertToSelf return true<br/>");
else
Response.Write("RevertToSelf return false<br/>");
Response.Write("One more time after RevertToSelf()<br/>");
Response.Write("Current user: ");Response.Write(objNet.UserName);Response.Write("<br/>");
Response.Write("Current user's domain: ");Response.Write(objNet.UserDomain);Response.Write("<br/>");
var fso = Server.CreateObject("Scripting.FileSystemObject");
var path = "\\\\mk01\\C\\Oleg";
if (fso.FolderExists(path)) {
Response.Write("Yes");
} else {
Response.Write("No");
}%>
</body></html>
Run Code Online (Sandbox Code Playgroud)
如果用于运行 IIS 应用程序池的帐户有权访问相应的网络共享,则输出将如下所示
Current user: Oleg
Current user's domain: WORKGROUP
RevertToSelf return true
One more time after RevertToSelf()
Current user: DefaultAppPool
Current user's domain: WORKGROUP
Yes
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
6770 次 |
| 最近记录: |