加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > asp.Net > 正文

asp-classic – 使用FileSystemObject的文件权限 – CScript.exe

发布时间:2020-12-15 21:03:36 所属栏目:asp.Net 来源:网络整理
导读:我有一个经典的ASP页面 – 用JScript编写 – 使用Scripting.FileSystemObject将文件保存到网络共享 – 而且它不起作用. (“没有权限”) ASP页面在IIS下使用Windows身份验证运行,并启用了模拟. 如果我通过CScript.exe在本地运行以下代码块: var objNet = new
我有一个经典的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 = "\myservermy_sharesome_path";
if (fso.FolderExists(path)) {
    WScript.Echo("Yes");
} else {
    WScript.Echo("No");
}

我得到(预期)输出:

MY_COMPUTER
dylan.beattie
MYDOMAIN
Yes

如果我在.ASP页面中运行相同的代码,则将Response.Write替换为WScript.Echo,我得到以下输出:

MY_COMPUTER
dylan.beattie
MYDOMAIN
No

现在 – 我的理解是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()函数. IIS将收到用户令牌并已为您模拟,因为您已配置了您的网站.要返回原始进程令牌,您应该在自定义COM组件中实现函数RevertToSelf()的调用.也许,如果你不需要在ASP页面中做更多的事情,那就足够了,但我建议你在使用文件操作之前要更加小心并将当前用户令牌保存在变量中.然后使用文件系统进行所有操作,最后将用户令牌重新分配回当前线程.您可以根据SetThreadToken(NULL,hUserToken);为模拟分配模拟令牌.要提供(保存)当前线程令牌(在您的情况下为用户令牌),您可以使用OpenThreadToken API.它必须工作.

更新2:在一个ASP页面的末尾使用RevertToSelf()函数可能已经可以了.相应的C#代码可以是这样的:

使用名称LoginAdmin在“类库”类型的C#中创建一个新项目.将以下代码粘贴到其中

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();
        }
    }
}

在“构建”部分“注册COM互操作”中签入项目属性.在项目的“签名”部分检查签署程序集并在“选择强名称密钥文件”中选择< New ...>,然后键入任何文件名和密码(或选中“保护我的密钥…” ).最后,您应该在项目的Properties部分中的AssemblyInfo.cs中修改一行:

[assembly: ComVisible (true)]

编译此项目后,您将获得两个文件: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 = "\mk01COleg";
       if (fso.FolderExists(path)) {
          Response.Write("Yes");
       } else {
          Response.Write("No");
       }%>
</body></html>

如果用于运行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

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读