需求是這樣的,ASP.NET 的網站登入(Session)後,點選其他 ASP 的網站,也要變成登入狀態。

搜尋過有幾種作法:

  1. 透過資料庫,存入 Session_id 供查閱。
  2. 透過 ASP.NET2ASP POST 的方法,但要注意安全性。
  3. 將帳號加密,用 GET 方式附帶在 .asp 網址後方,ASP 端使用該加密字串丟到 ASP.NET 的 Web Service 解密並查詢該帳號是否正確,若正確則傳回 true,ASP 再設定 Session 登入狀態。

最後在條件考量下,決定使用第三種方法。
也許有更便捷的方式,有高手路過請提點一下囉 😀

* 以 ASP.NET (VB) 為例
* 加密方法參考來源:http://stackoverflow.com/questions/240713/how-can-i-encrypt-a-querystring-in-asp-net

依照上方參考連結,增加一支加密方法

Imports Microsoft.VisualBasic  
Imports System.Security.Cryptography  
Imports System  
Imports System.IO  
Imports System.Xml  
Imports System.Text

Public Class Encryption64  
Private key() As Byte = {}  
Private IV() As Byte = {&H12, &H34, &H56, &H78, &H90, &HAB, &HCD, &HEF}  
Public Function Decrypt(ByVal stringToDecrypt As String, _  
ByVal sEncryptionKey As String) As String  
Dim inputByteArray(stringToDecrypt.Length) As Byte  
Try  
key = System.Text.Encoding.UTF8.GetBytes(Left(sEncryptionKey, 8))  
Dim des As New DESCryptoServiceProvider()  
inputByteArray = Convert.FromBase64String(stringToDecrypt)  
Dim ms As New MemoryStream()  
Dim cs As New CryptoStream(ms, des.CreateDecryptor(key, IV), _  
CryptoStreamMode.Write)  
cs.Write(inputByteArray, 0, inputByteArray.Length)  
cs.FlushFinalBlock()  
Dim encoding As System.Text.Encoding = System.Text.Encoding.UTF8  
Return encoding.GetString(ms.ToArray())  
Catch e As Exception  
Return e.Message  
End Try  
End Function  
Public Function Encrypt(ByVal stringToEncrypt As String, _  
ByVal SEncryptionKey As String) As String  
Try  
key = System.Text.Encoding.UTF8.GetBytes(Left(SEncryptionKey, 8))  
Dim des As New DESCryptoServiceProvider()  
Dim inputByteArray() As Byte = Encoding.UTF8.GetBytes( _  
stringToEncrypt)  
Dim ms As New MemoryStream()  
Dim cs As New CryptoStream(ms, des.CreateEncryptor(key, IV), _  
CryptoStreamMode.Write)  
cs.Write(inputByteArray, 0, inputByteArray.Length)  
cs.FlushFinalBlock()  
Return Convert.ToBase64String(ms.ToArray())  
Catch e As Exception  
Return e.Message  
End Try  
End Function  
End Class

作一支 WebService:

<%@ WebService Language="VB" Class="Member" %>

Imports System.Web  
Imports System.Web.Services  
Imports System.Web.Services.Protocols  
Imports System.Data  
Imports System.Data.SqlClient  
Imports System.Security.Cryptography  
Imports System

‘ 若要允許使用 ASP.NET AJAX 從指令碼呼叫此 Web 服務,請取消註解下一行。  
‘ <System.Web.Script.Services.ScriptService()> _  
<WebService(Namespace:="http://localhost/")> _  
<WebServiceBinding(ConformsTo:=WsiProfiles.BasicProfile1_1)> _  
Public Class Member  
Inherits System.Web.Services.WebService

<WebMethod(EnableSession:=True)> _  
Public Function LoginAccount(ByVal UserName As String) As String  
Try

If UserName.Trim() = "" Then  
Return "登入失敗"  
End If

Dim Acct As String = decryptQueryString(UserName)  
If ChkLogin(Acct) Then  
Return Acct  
Else  
Return "登入失敗"  
End If  
Catch ex As Exception  
Return "登入失敗"  
End Try  
End Function

Private _key As String = "000000" ‘加密金鑰

Public Function decryptQueryString(ByVal strQueryString As String) As String  
Dim oES As New Encryption64()  
Return oES.Decrypt(strQueryString, _key)  
End Function

Public Function ChkLogin(ByVal UserName As String) As Boolean  
‘連線至資料庫做查詢,若正確則返回 True,反之返回 False  
End Function

End Class

加密的 Code 如下:(會用在 .aspx 頁面,某個目的 .asp 網址後方)

Public Function encryptQueryString(ByVal strQueryString As String) As String  
Dim _key As String = "000000" ‘要跟上面用的金鑰一樣,比較好的方式是拔出來寫在一個地方啦.. 像可以放在 Web.config 中  
Dim oES As New Encryption64()  
Return oES.Encrypt(strQueryString, _key)  
End Function

然後使用 encryptQueryString 方法去產生加密過的帳號 ..
例如:

".asp?account=" & encryptQueryString(Session("帳號"))

ASP 端收到加密過的帳號之後,連線到 ASP.NET 的 Web Service 中做帳號比對,若正確則輸出帳號,反之會吐出「登入錯誤」(可以依需求改成正確的話就取得登入 Session)。

<%  
Set objHTTP = Server.CreateObject("MSXML2.XMLHTTP")  
Set xmlDOC =Server.CreateObject("MSXML.DOMDocument")  
strWebserviceURL = "http://放置WebService的host/WebService.asmx/LoginAccount"  
strRequest = "username=" & Replace(Server.URLEncode(Request.QueryString("account")),"+","%2b")  
objHTTP.Open "POST", strWebserviceURL, False  
objHTTP.SetRequestHeader "Content-Type", "application/x-www-form-urlencoded"  
objHTTP.Send strRequest  
bOK = xmlDOC.load(objHTTP.responseXML)  
if objHTTP.Status=200 then  
xmlStr = xmlDOC.xml  
xmlStr = Replace(xmlStr,"<","<",1,-1,1)  
xmlStr = Replace(xmlStr,">",">",1,-1,1)  
Response.Write xmlStr  
else  
Response.Write objHTTP.Status  
end if  
%>

其中要注意的,此種加密方法可能會產生+號,若不編碼一下,可能會造成錯誤「Base-64 字串中的無效字元」無法解析,因此利用 Replace(加密字串,"+","%2b") 將+號編碼再做傳遞。

另外.. Web Service 這邊的 Web.config 中須加入:

<webServices>  
<protocols>  
<add name="HttpGet"/>  
<add name="HttpPost"/>  
</protocols>  
</webServices>

讓非本機也可對 WebService 進行 HttpGet, HttpPost 方式的存取 ..

作法粗略如上,Code 尚未整理過.. 先作個解法紀錄囉 😛