簡體   English   中英

T-SQL中的HTML編碼?

[英]HTML Encoding in T-SQL?

是否有任何函數可以在T-SQL中編碼HTML字符串? 我有一個遺留數據庫,其中包含諸如“<”,“>”之類的躲避字符等。我可以編寫一個函數來替換字符但是有更好的方法嗎?

我有一個ASP.Net應用程序,當它返回一個字符串時,它包含導致錯誤的字符。 ASP.Net應用程序正在從數據庫表中讀取數據。 它不會寫入表本身。

我們有一個遺留系統,它使用觸發器和dbmail在輸入表時發送HTML編碼的電子郵件,因此我們需要在電子郵件生成中進行編碼。 我注意到Leo的版本有一個小錯誤,編碼&in &lt; &gt; 我用這個版本:

CREATE FUNCTION HtmlEncode
(
    @UnEncoded as varchar(500)
)
RETURNS varchar(500)
AS
BEGIN
  DECLARE @Encoded as varchar(500)

  --order is important here. Replace the amp first, then the lt and gt. 
  --otherwise the &lt will become &amp;lt; 
  SELECT @Encoded = 
  Replace(
    Replace(
      Replace(@UnEncoded,'&','&amp;'),
    '<', '&lt;'),
  '>', '&gt;')

  RETURN @Encoded
END
GO

這有點晚了,但無論如何,這里有正確的方法:

HTML-Encode(HTML編碼= XML編碼):

DECLARE @s NVARCHAR(100)
SET @s = '<html>unsafe & safe Utf8CharsDon''tGetEncoded ÄöÜ - "Conex"<html>'
SELECT (SELECT @s FOR XML PATH(''))

查詢中的HTML編碼:

SELECT 
    FIELD_NAME  
    ,(SELECT FIELD_NAME AS [text()] FOR XML PATH('')) AS FIELD_NAME_HtmlENcoded 
FROM TABLE_NAME

HTML解碼:

SELECT CAST('<root>' + '&lt;root&gt;Test&amp;123' + '</root>' AS XML).value(N'(root)[1]', N'varchar(max)');

如果要正確執行,可以使用CLR存儲過程。
但是,它有點復雜,因為你不能在CLR-stored-procedures中使用System.Web-Assembly(所以你不能做System.Web.HttpUtility.HtmlDecode(htmlEncodedStr);)。 所以你必須編寫自己的HttpUtility類,我不推薦,特別是對於解碼。

幸運的是,您可以從單一源代碼(.NET for Linux)中刪除System.Web.HttpUtility。 然后你可以在不引用system.web的情況下使用HttpUtility。

然后你寫這個CLR存儲過程:

using System;
using System.Collections.Generic;
using System.Text;

using Microsoft.SqlServer.Server;
using System.Data.SqlTypes;
//using Microsoft.SqlServer.Types;


namespace ClrFunctionsLibrary
{


    public class Test
    {


        [Microsoft.SqlServer.Server.SqlFunction]
        public static SqlString HtmlEncode(SqlString sqlstrTextThatNeedsEncoding)
        {
            string strHtmlEncoded = System.Web.HttpUtility.HtmlEncode(sqlstrTextThatNeedsEncoding.Value);
            SqlString sqlstrReturnValue = new SqlString(strHtmlEncoded);

            return sqlstrReturnValue;
        }


        [Microsoft.SqlServer.Server.SqlFunction]
        public static SqlString HtmlDecode(SqlString sqlstrHtmlEncodedText)
        {
            string strHtmlDecoded = System.Web.HttpUtility.HtmlDecode(sqlstrHtmlEncodedText.Value);
            SqlString sqlstrReturnValue = new SqlString(strHtmlDecoded);

            return sqlstrReturnValue;
        }


        // ClrFunctionsLibrary.Test.GetPassword
        //[Microsoft.SqlServer.Server.SqlFunction]
        //public static SqlString GetPassword(SqlString sqlstrEncryptedPassword)
        //{
        //    string strDecryptedPassword = libPortalSecurity.AperturePortal.DecryptPassword(sqlstrEncryptedPassword.Value);
        //    SqlString sqlstrReturnValue = new SqlString(sqlstrEncryptedPassword.Value + "hello");

        //    return sqlstrReturnValue;
        //}

        public const double SALES_TAX = .086;

        // http://msdn.microsoft.com/en-us/library/w2kae45k(v=vs.80).aspx
        [SqlFunction()]
        public static SqlDouble addTax(SqlDouble originalAmount)
        {
            SqlDouble taxAmount = originalAmount * SALES_TAX;

            return originalAmount + taxAmount;
        }


    } // End Class Test


} // End Namespace ClrFunctionsLibrary

並注冊:

GO

/*
--http://stackoverflow.com/questions/72281/error-running-clr-stored-proc
-- For unsafe permission
EXEC sp_changedbowner 'sa'
ALTER DATABASE YOUR_DB_NAME SET TRUSTWORTHY ON 

GO
*/


IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[HtmlEncode]') AND type in (N'FN', N'IF', N'TF', N'FS', N'FT'))
DROP FUNCTION [dbo].[HtmlEncode]
GO


IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[HtmlDecode]') AND type in (N'FN', N'IF', N'TF', N'FS', N'FT'))
DROP FUNCTION [dbo].[HtmlDecode]
GO




IF  EXISTS (SELECT * FROM sys.assemblies asms WHERE asms.name = N'ClrFunctionsLibrary' and is_user_defined = 1)
DROP ASSEMBLY [ClrFunctionsLibrary]

GO


--http://msdn.microsoft.com/en-us/library/ms345101.aspx



CREATE ASSEMBLY [ClrFunctionsLibrary]
AUTHORIZATION [dbo]
FROM 'D:\username\documents\visual studio 2010\Projects\ClrFunctionsLibrary\ClrFunctionsLibrary\bin\Debug\ClrFunctionsLibrary.dll' 
WITH PERMISSION_SET = UNSAFE  --EXTERNAL_ACCESS  --SAFE
;

GO




CREATE FUNCTION [dbo].[HtmlDecode](@value [nvarchar](max))
RETURNS [nvarchar](max) WITH EXECUTE AS CALLER
AS 
-- [AssemblyName].[Namespace.Class].[FunctionName]
EXTERNAL NAME [ClrFunctionsLibrary].[ClrFunctionsLibrary.Test].[HtmlDecode]
GO





CREATE FUNCTION [dbo].[HtmlEncode](@value [nvarchar](max))
RETURNS [nvarchar](max) WITH EXECUTE AS CALLER
AS 
-- [AssemblyName].[Namespace.Class].[FunctionName]
EXTERNAL NAME [ClrFunctionsLibrary].[ClrFunctionsLibrary.Test].[HtmlEncode]
GO



/*
EXEC sp_CONFIGURE 'show advanced options' , '1';
 GO
 RECONFIGURE;
 GO
 EXEC sp_CONFIGURE 'clr enabled' , '1'
 GO
 RECONFIGURE;
 GO

EXEC sp_CONFIGURE 'show advanced options' , '0';
 GO
 RECONFIGURE;
*/

之后,您可以像普通函數一樣使用它:

SELECT
     dbo.HtmlEncode('helloäÖühello123') AS Encoded
    ,dbo.HtmlDecode('hello&auml;&Ouml;&uuml;hello123') AS Decoded 

任何只是復制粘貼的人,請注意,出於效率原因,你會使用

public const double SALES_TAX = 1.086;

// http://msdn.microsoft.com/en-us/library/w2kae45k(v=vs.80).aspx
[SqlFunction()]
public static SqlDouble addTax(SqlDouble originalAmount)
{
     return originalAmount * SALES_TAX;
}

如果你在生產中使用這個功能。

請參閱此處查看已編輯的單音班:
http://pastebin.com/pXi57iZ3
http://pastebin.com/2bfGKBte

您需要在構建選項中定義NET_2_0 構建選項

您不應該在SQL中修復該字符串。 更好的方法是在ASP.net中使用一個名為HtmlEncode的函數,這將烹飪導致您看到的問題的特殊字符,請參閱下面的示例。 我希望這有幫助。

string htmlEncodedStr = System.Web.HttpUtility.HtmlEncode(yourRawStringVariableHere);
string decodedRawStr =  System.Web.HttpUtility.HtmlDecode(htmlEncodedStr);

編輯:因為您是從數據表綁定數據。 使用內聯表達式在GridView的標記或您使用的任何控件中調用HTMLEncode,這仍然可以滿足您的數據綁定要求。 見下面的例子。 或者,您可以循環數據表對象中的每個記錄,並在數據綁定之前使用html編碼的字符串更新每個單元格。

<%# System.Web.HttpUtility.HtmlEncode(Eval("YourColumnNameHere")) %>

我不認為數據庫中的數據應該知道或關心用戶界面。 顯示問題應由表示層處理。 我不希望看到任何混入數據庫的HTML。

您可以在查詢中使用“XML PATH”。 例如;

DECLARE @encodedString VARCHAR(MAX)

SET @encodedString = 'give your html string you want to encode'

SELECT @encodedString
SELECT (SELECT @encodedString FOR XML PATH(''))

現在按照您的意願,您可以在自己的sql函數中使用它。 希望這會有所幫助。

如果您在Web上顯示字符串,則可以使用Server.HTMLEncode()對其進行編碼。

如果要在數據庫中存儲字符串,請確保數據庫字段為“nchar”,而不是“char”。 這將允許它存儲unicode字符串。

如果無法控制數據庫,可以使用Encoding.ASCII.GetString將字符串“展平”為ASCII。

將其分配給標簽的Text屬性,它將由.NET自動編碼

我今天一直在嘗試用T-SQL做這件事,因為我的要求發生變化,這一點主要是為了好玩,但我想出了一條出路。 您可以使用從NCHAR()函數構建的unicode字符表,或者只是導入它,從0到65535迭代(如果您只需要前512或者其他東西,則可以更少)。 然后重建字符串。 可能有更好的方法來重建字符串,但這有點緊張。

---store unicode chars into a table so you can replace those characters withthe decimal value

`

CREATE TABLE #UnicodeCharacters(DecimalValue INT,UnicodeCharacter NCHAR);

--loop from 0 to highest unicode value you want and dump to the table you created
DECLARE @x INT = 0;
WHILE @x <= 65535
    BEGIN
        BEGIN
            INSERT INTO #UnicodeCharacters(DecimalValue, UnicodeCharacter)
            SELECT  @x,NCHAR(@x)
        END
        ;

        SET @x = @x + 1
        ;
    END
;

--index for fast retrieval
CREATE CLUSTERED INDEX CX_UnicodeCharacter_DecimalValue ON #UnicodeCharacters(UnicodeCharacter, DecimalValue);

--this is the string that you want to html-encode...
DECLARE @String NVARCHAR(100) = N'人This is a test - Ñ';

--other vars
DECLARE @NewString NVARCHAR(100) = '';
DECLARE @Word TABLE(Character NCHAR(1));
DECLARE @Pos INT = 1;

--run through the string and check each character to see if it is outside the regex expression
WHILE @Pos <= LEN(@String)
BEGIN
    DECLARE @Letter NCHAR(1) = SUBSTRING(@String,@Pos,1);
    PRINT @Letter;
    --rebuild the string replacing each unicode character outside the regex with &#[unicode value];
    SELECT  @NewString = @NewString + 
                CASE 
                    WHEN @Letter LIKE N'%[0-9abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-!@#$%^&*()_+-= ]%' THEN @Letter
                    ELSE '&#' + CAST(uc.DecimalValue AS VARCHAR(10)) + ';'
                END
    FROM    #UnicodeCharacters uc
    WHERE   @Letter = uc.UnicodeCharacter COLLATE JAPANESE_UNICODE_BIN

    SET @Pos += 1
END

--end result
SELECT @NewString
;

`我通常知道你會使用[0-9A-Za-z],但出於某種原因,當我這樣做時,它會考慮在該表達式范圍內的重音字符。 所以我明確地使用了我不想在表達式中轉換為Unicode的每個字符。

最后一點,我必須使用不同的排序規則來對Unicode字符進行匹配,因為默認的LATIN排序規則(CI或其他)似乎與重音字符不匹配,就像LIKE中的正則表達式一樣。

我自己沒有嘗試過這個解決方案但我會嘗試使用sql server / .NET CLR集成並實際從T-SQL調用C#HTMLEncode函數。 這可能是低效的,但我懷疑它會給你最准確的結果。

我的出發點是如何做到這一點http://msdn.microsoft.com/en-us/library/ms254498%28VS.80%29.aspx

好的,這就是我所做的。 我創建了一個簡單的函數來處理它。 它遠非完整,但至少處理標准<>&字符。 隨着我的進展,我會加入它。

CREATE FUNCTION HtmlEncode
(
    @UnEncoded as varchar(500)
)
RETURNS varchar(500)
AS
BEGIN
    DECLARE @Encoded as varchar(500)   
    SELECT @Encoded = Replace(@UnEncoded,'<','&lt;')
    SELECT @Encoded = Replace(@Encoded,'>','&gt;')
    SELECT @Encoded = Replace(@Encoded,'&','&amp;')   
    RETURN @Encoded    
END

然后我可以使用:

Select Ref,dbo.HtmlEncode(RecID) from Customers

這給了我一個HTML安全記錄ID。 可能有一個內置功能,但我找不到它。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM