SQLServer存储过程访问数据库权限异常问题的解决方案

server|sqlserver|存储过程|访问|解决|数据|数据库|问题

最近用ASP.net 2.0 + SQL Server做一个网页表单的提交,使用C#编写存储过程来完成向SQL Server数据库表中插入记录的操作。在调用这个存储过程时,出现了关于存储权限的一个异常。下面详述异常产生的过程和解决方案。

1.操作步骤:
1)使用ASP.net 2.0,用C#写了一个存储过程,对数据库test中的一个表进行操作,代码如下:

public class StoredProcedures
{
[Microsoft.SqlServer.Server.SqlProcedure]
public static void Submit(string strAnswer)
{
using (SqlConnection connection = new SqlConnection("Data Source=WS;Initial Catalog=test;Integrated Security=False;Trusted_Connection=yes;"))
{
connection.Open();     // ***执行到这一步出现异常,详见下文所述***
String cmdTxt = "INSERT INTO dbo.Response_SCL90 VALUES(" + strAnswer + ")";
SqlCommand command = new SqlCommand(cmdTxt, connection);
SqlDataReader reader = command.ExecuteReader();

}
}
}

2)编译生成了Submit_Answer.dll,接着,在SQL Server中注册这个dll,并创建存储过程,SQL脚本如下:

CREATE ASSEMBLY Submit_Answer
FROM 'D:\study\C#\测评系统\WebSite1\StoredProcedure\Submit_Answer\bin\Debug\Submit_Answer.dll';
GO

CREATE PROCEDURE dbo.Submit_Answer
(
@strAnswer nvarchar(256)
)
WITH EXECUTE AS OWNER
AS
EXTERNAL NAME Submit_Answer.StoredProcedures.Submit
GO

3)最后,在.net中调用这个存储过程,代码如下:
SqlConnection connection = new SqlConnection("Data Source=WS;Initial Catalog=test;Integrated Security=False;Trusted_Connection=yes;");

String cmdTxt = "dbo.Submit_Answer";
SqlCommand command = new SqlCommand(cmdTxt, connection);
command.CommandType = CommandType.StoredProcedure;

command.Parameters.Add("@strAnswer", SqlDbType.NVarChar);
command.Parameters["@strAnswer"].Value = strAnswer;

command.Connection.Open();
SqlDataReader dr = command.ExecuteReader();

command.Connection.Close();

2. 异常描述:
在执行到存储过程 connection.Open();一句时,出现异常,异常描述和当时的堆栈信息如下:
异常详细信息: System.Data.SqlClient.SqlException: A .NET Framework error occurred during execution of user defined routine or aggregate 'Submit_Answer':
System.Security.SecurityException: Request for the permission of type 'System.Data.SqlClient.SqlClientPermission, System.Data, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' failed.
System.Security.SecurityException:
at System.Security.CodeAccessSecurityEngine.Check(Object demand, StackCrawlMark& stackMark, Boolean isPermSet)
at System.Security.PermissionSet.Demand()
at System.Data.Common.DbConnectionOptions.DemandPermission()
at System.Data.SqlClient.SqlConnection.PermissionDemand()
at System.Data.SqlClient.SqlConnectionFactory.PermissionDemand(DbConnection outerConnection)
at System.Data.ProviderBase.DbConnectionClosed.OpenConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory)
at System.Data.SqlClient.SqlConnection.Open()
at StoredProcedures.Submit(SqlChars strAnswer)

3.简要分析:
看来是在存储过程中没有对数据库的访问权限,因为在数据库连接Open时就出错了,查找了一些资料,也没发现问题在哪。后来便在社区中提问了。

4.解决方案:
在“MS-SQL Server 疑难问题”版面,zlp321002(龙卷风2006)对这个问题进行解答,详情请见:
http://community.csdn.net/Expert/TopicView3.asp?id=4790457
现整理和总结如下:
(非常感谢zlp321002(龙卷风2006),下面描述的解决方案源自zlp321002(龙卷风2006))

1)打开数据库的外部访问选项(external_access_option)

Alter Database 数据库名
SET TRUSTWORTHY ON

reference:关于数据库外部访问选项(external_access_option)的描述(摘录自SQL Server Books Online)

TRUSTWORTHY { ON | OFF }

    ON

        Database modules (for example, user-defined functions or stored procedures) that use an impersonation context can access resources outside the database.

    OFF

        Database modules in an impersonation context cannot access resources outside the database.

    TRUSTWORTHY is set to OFF whenever the database is attached.

    By default, the master database has TRUSTWORTHY set to ON. The model and tempdb databases always have TRUSTWORTHY set to OFF, and the value cannot be changed for these databases.

    To set this option, requires membership in the sysadmin fixed server role.

    The status of this option can be determined by examining the is_trustworthy_on column in the sys.databases catalog view.

2)设置存储过程dll的PERMISSION_SET为EXTERNAL_ACCESS

将操作步骤第2)步中原来的
CREATE ASSEMBLY Submit_Answer
FROM 'D:\study\C#\测评系统\WebSite1\StoredProcedure\Submit_Answer\bin\Debug\Submit_Answer.dll'
GO
改为:
CREATE ASSEMBLY Submit_Answer
FROM 'D:\study\C#\测评系统\WebSite1\StoredProcedure\Submit_Answer\bin\Debug\Submit_Answer.dll'
WITH PERMISSION_SET = EXTERNAL_ACCESS
GO

reference:关于CREATE ASSEMBLY中PERMISSION_SET 设置(摘录自SQL Server Books Online)

PERMISSION_SET { SAFE | EXTERNAL_ACCESS | UNSAFE }
Specifies a set of code access permissions that are granted to the assembly when it is accessed by SQL Server. If not specified, SAFE is applied as the default.

We recommend using SAFE. SAFE is the most restrictive permission set. Code executed by an assembly with SAFE permissions cannot access external system resources such as files, the network, environment variables, or the registry.

EXTERNAL_ACCESS enables assemblies to access certain external system resources such as files, networks, environmental variables, and the registry.

UNSAFE enables assemblies unrestricted access to resources, both within and outside an instance of SQL Server. Code running from within an UNSAFE assembly can call unmanaged code.

Security Note: 
SAFE is the recommended permission setting for assemblies that perform computation and data management tasks without accessing resources outside an instance of SQL Server. We recommend using EXTERNAL_ACCESS for assemblies that access resources outside of an instance of SQL Server. EXTERNAL_ACCESS assemblies include the reliability and scalability protections of SAFE assemblies, but from a security perspective are similar to UNSAFE assemblies. This is because code in EXTERNAL_ACCESS assemblies runs by default under the SQL Server service account and accesses external resources under that account, unless the code explicitly impersonates the caller. Therefore, permission to create EXTERNAL_ACCESS assemblies should be granted only to logins that are trusted to run code under the SQL Server service account. For more information about impersonation, see CLR Integration Security. Specifying UNSAFE enables the code in the assembly complete freedom to perform operations in the SQL Server process space that can potentially compromise the robustness of SQL Server. UNSAFE assemblies can also potentially subvert the security system of either SQL Server or the common language runtime. UNSAFE permissions should be granted only to highly trusted assemblies. Only members of the sysadmin fixed server role can create and alter UNSAFE assemblies.
 

做完上述修改后,再次运行网页,提交表单,不再出现异常了。

5. 小结:

看来这个存储过程访问权限的解决是从下面两个方面进行:首先打开数据库的外部访问选项,允许数据库的模块访问外部资源;接着设置那个存储过程dll的PERMISSION_SET,即设置这个dll的访问权限为允许访问外部资源。这样,存储过程就可以访问数据库了。

时间: 2024-08-07 05:20:53

SQLServer存储过程访问数据库权限异常问题的解决方案的相关文章

ADO.NET使用存储过程访问数据库

using System; using System.Data; using System.Data.SqlClient; namespace Northwind { class Program { static void Main(string[] args) { SqlConnection sqlConn = null; SqlCommand sqlCmd = null; SqlDataReader sqlDR = null; try { //创建连接对象,使用集成安全方式连接,更安全 sq

sql server-sqlserver中导入数据库后,把由windowds验证改成sqlserver后,数据库中的表消失

问题描述 sqlserver中导入数据库后,把由windowds验证改成sqlserver后,数据库中的表消失 解决方案 数据库选对了吗?如果选不对,肯定找不到表的 解决方案二: 新手表示没遇到过这种问题 解决方案三: 用windows账号重新登陆查看下表是否真的消失.然后检查下你使用的sql server账号的权限.

delphi 通过 ado 访问数据库存储过程,如果有插入动作,为什么会执行两遍?

问题描述 delphi 通过 ado 访问数据库存储过程,如果有插入动作,为什么会执行两遍? 20C 如题.这是我反复测试后得出的结论.我实在不理解为什么. 具体测试过程是这样子的:我用ado连接数据库.然后我写了一个简单的存储过程,就是往表里插入数据.然后我用ado调用这个存储过程.然后我就发现,虽然程序里我只调用了一次,但实际上表里的数据却被插入了完全一模一样的两条. 这算是bug还是怎么回事?是不是有什么我不曾注意到的细节没处理好? 存储过程代码如下: create procedure p

ado.net-求一个无参数 调用存储过程的方法,我调用的是列转行的存储过程 但是访问数据库的方法不知道怎么写

问题描述 求一个无参数 调用存储过程的方法,我调用的是列转行的存储过程 但是访问数据库的方法不知道怎么写 访问数据不知道写 存储过程已经写好 解决方案 prepareCall()方法调用存储过程 解决方案二: use 数据库名称 这不是方法 解决方案三: use 数据库名称 用这个语句就能指向数据库 解决方案四: exec 存储过程名称

SQLServer客户端访问远程数据库报错

问题描述 SQLServer客户端访问远程数据库报错 SQLServer客户端访问远程数据库报错. 远程数据库是使用tomcat7.0回调阿里云的数据库. 解决方案 该问题很常见,解决方案请点击查看:http://blog.csdn.net/piaoshisun/article/details/6029174 解决方案二: 防火墙? 网络连接? 身份验证失败? 解决方案三: 网络名不再可用是连接中断,重新连下,或者检查下网络是否稳定 解决方案四: 如果是握手发生了错误,检查 (1)你的客户端是否

接手别人的JavaEE项目之前运行正确,添加访问数据库后报tomcat异常

问题描述 接手别人的JavaEE项目之前运行正确,添加访问数据库后报tomcat异常 我重装了tomcat,重新导入了项目又再将我修改的添加进去,运行时报tomcat异常,所以应当不是环境问题 报错截图: 访问数据库按照MVC形式,数据显示在getData.jsp中,servlet为GetDServlet.java, 实现从数据库中取数据的类为getD.java,数据表对应的类为inemo_bean, 下面贴代码: package Servlet; import java.io.IOExcept

mssql server把数据库所有用户存储过程的EXEC权限赋另一角色

mssql server把数据库教程所有用户存储过程的EXEC权限赋另一角色 $sql="create   procedure   sp_GrantProce(@username   varchar(40)) as begin         declare   @user   varchar(20),@name   varchar(40)         declare   t_cursor   cursor   for         select   user_name(uid)   as

详解SQLServer 2008 R2数据库SSAS建模及扩展能力_mssql2008

SQLServer 2008 R2数据库中提供的SSAS建模工具包括包括SQL Server Management Studio 和Business Intelligence Development Studio,那么建模的过程是怎样的呢?本文我们就来介绍这些,接下来就让我们来一起了解一下SQLServer 2008 R2数据库的建模工具和关键过程以及数据挖掘.权限和访问接口等的知识吧. 建模工具和关键过程 SSAS的建模的目的是设计多维数据库对象,建模的工具包括SQL Server Manag

JAVA访问数据库之连接数据库

开发一个访问数据库的应用程序,首先要加载数据库的驱动程序,只需要在第一次访问数据库时加载一次,然后每次运行时创建一个Connection实例,紧接着执行操作数据库的SQL语句,并处理返回的结果集,最后在完成完成此次操作时销毁前面创建的Connection,释放与数据库的连接. 加载数据库驱动 在连接数据库之前,首先要把JDBC驱动类加载到java虚拟机,可以使用java.lang.Class类的静态方法forName(String className).成功加载后会将加载的驱动类注册给Drive