[ASP.NET][ASP] 傳遞登入狀態

Standard

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

搜尋過有幾種作法:

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

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

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

1.
依照上方參考連結,增加一支加密方法
[code language=”VB”]
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
[/code]

2.
作一支 WebService:

[code language=”VB”]
<%@ 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]

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

[code language=”VB”]
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
[/code]

然後使用 encryptQueryString 方法去產生加密過的帳號 ..
例如:
[code language=”VB”]
".asp?account=" & encryptQueryString(Session("帳號"))
[/code]

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

[code language=”VB”]
<%
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
%>
[/code]

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

4.
另外.. Web Service 這邊的 Web.config 中須加入:
[code language=”html”]
<webServices>
<protocols>
<add name="HttpGet"/>
<add name="HttpPost"/>
</protocols>
</webServices>
[/code]

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

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

發表迴響

你的電子郵件位址並不會被公開。 必要欄位標記為 *