SQL Server - FileTable拒絕存取之問題

15 July 2013 — Written by Sky Chang
#IIS#SQL Server

最近,連續發了幾篇SQL Server的文章,這大概也是有史以來連續最多的一次…Orz…,回歸正題,不知道大家還記不記得之前寫的FileTable文章,經過一段時間的使用,我們終於把他佈署到半正式的環境了!!

然後就發生了錯誤…Orz…但這次發生的問題一開始還覺得滿詭異的,因為使用Web Api,所以只吐回來發生錯誤…,重點是,Local開的IIS Express是正常的,完全不知道哪裡錯,後來想辦法把問題調閱出來,才發現這次發生的問題,如下圖,答案就是"拒絕存取",而詳細的錯誤訊息如下,不過大家約略看看就可以跳過了,不是重點= =+。

image

"Message":"發生錯誤。","ExceptionMessage":"類型 'MultipartFormDataStreamProvider' 的資料流提供者擲回例外狀況。","ExceptionType":"System.InvalidOperationException","StackTrace":" 於 System.Net.Http.MimeBodyPart.GetOutputStream(HttpContent parent)\r\n 於 System.Net.Http.HttpContentMultipartExtensions.MultipartWriteSegmentAsync(MultipartAsyncContext context)\r\n 於 System.Net.Http.HttpContentMultipartExtensions.MoveNextSegment(MultipartAsyncContext context)\r\n--- 先前擲回例外狀況之位置中的堆疊追蹤結尾 ---\r\n 於 System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n 於 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n 於 System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()\r\n 於 CSW.Controllers.API.ActivityImgController.<Post>d0.MoveNext()","InnerException":{"Message":"發生錯誤。","ExceptionMessage":"拒絕存取路徑 '\\localhost\sqldb\FileTable\Activities\BodyPart_4329878c-2610-4f2d-ba16-f5ce595f603f'。","ExceptionType":"System.UnauthorizedAccessException","StackTrace":" 於 System.IO.Error.WinIOError(Int32 errorCode, String maybeFullPath)\r\n 於 System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, Int32 rights, Boolean useRights, FileShare share, Int32 bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy, Boolean useLongPath, Boolean checkHost)\r\n 於 System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize, FileOptions options, String msgPath, Boolean bFromProxy)\r\n 於 System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize, FileOptions options)\r\n 於 System.Net.Http.MultipartFileStreamProvider.GetStream(HttpContent parent, HttpContentHeaders headers)\r\n 於 System.Net.Http.MimeBodyPart.GetOutputStream(HttpContent parent)"}}

好的,我們回頭看一下這次的問題,這次的問題是"拒絕存取",但Local可以正常運作,那為何佈署上去後,就不行了呢??,我想聰明的大家,應該都已經想到了!?

是的,既然問題是"拒絕存取",那就表示是因為權限不足,那為何Local又可以執行呢??( 總覺得鋪梗鋪得很像藍色蜘蛛網- -… ),答案很簡單,因為小弟執行Visual Studio是使用Administrator的權限執行,所以IIS Express也是Administrator的權限…那存取FileTable的資料夾,自然也暢行無阻。

但在現實的環境中,就沒那麼單純了,在正式的Server上,IIS並不會有最高的權限執行…( 因該也不會有人想用最高的權限執行吧… ),所以自然而然,就變得沒有權限去存取FileTable的資料夾…( 怕有人誤會,所以補充一下,這邊是代表,沒有權限使用Windows IO機制來直接存取FileTable的檔案,也就是說,沒有權限使用檔案總管來新增檔案,而不是在敘說寫入到db的權限 )

既然知道問題了,那該怎麼做呢!?,基本上,小弟也不太會XDDD,所以今天搬出了公司所有SQL Team的救兵,最後動用到許致學老師才幫忙解決…( 深深感謝大家QQ~~ )

首先,雖然權限的問題,在一般的Web應用也會碰到,但FileTable的設定權限是沒辦法從檔案總管那邊下手去設定的,因為FileTable的權限會透過SQL Server來控管,所以我們要透過SSMS來針對SQL Server的權限設定下手,簡單的說,就是把IIS的權限加到SQL Server裡面去。

首先,我們先從登入的地方,來新增一個新的登入,畢竟,要透過SQL Server,那一定要先有登入帳號阿!!,不然連SQL Server都沒登入的權限,那還有啥權限可以去讀取FileTable…

所以我們可以如下圖,按下搜尋,來把IIS的Windows帳號加入。

image

但有那麼單純嗎?當然沒有,因為新版的IIS帳號,已經變成虛擬帳號了,對於虛擬帳號有興趣的朋友們,可以參考保哥這篇文章;所以我們要加入到SQL Server裡面的是一個IIS的虛擬帳號,那帳號名稱到底是甚麼呢?就要開啟IIS來看一下,目前我們到底用到的是哪個應用程式集區;由下圖可以發現,我們用到的是ASP.NET v4.0。( IIS的虛擬帳號,會隨著應用程式集區的不同,而有不同的名稱。 )

image

所以我們回到SQL Server,就可以選擇剛剛找到的虛擬帳號,而IIS的虛擬帳號,預設是IIS AppPool{應用程式集區的名稱},所以我們上面是ASP.NET v4.0,所以這邊要輸入IIS AppPool\ASP.NET v4.0,輸入完成後,就可以檢查名稱一下,如果無誤,就可以發現,變成了有底線的ASP.NET v4.0。

image

那真的那麼簡單嗎??當然不是那麼簡單,如果這樣就OK了,小弟也不用寫這篇文章記錄了,雖然我們上面輸入了正確的帳號名稱,但當我們按下確定的時候,SSMS又會很"聰明"的幫我們加上主機名稱…變成"主機名稱\ASP.NET v4.0",也因此,這個帳號還是不對的,所以我們還是必須手動的回到如下圖的地方,輸入正確的虛擬帳號…( 所以上圖的那個步驟,其實是可以不用做的…只是想提醒大家,因為SSMS太聰明了,所以造成了我們的困擾- -+ )

image

輸入完成後,我們到伺服器角色的地方,選擇public就可以了,也不用太多的權限。

image

接下來,使用者對應這邊,我們要讓剛剛輸入好的SQL Server登入帳號對應到有FileTable的資料庫,簡單的說,就是資料庫會對應剛剛我們建立好的SQL Server登入帳號,而這個登入帳號又會是Windows的IIS虛擬帳號… ( 真多帳號阿- - ),如下圖,印象中寫入和讀取的權限可以不用勾,但有點忘記了,如果做完還是不行的話,可以考慮再回來勾一下。( 歹勢,中間測試太多東西… ),然後就可以按下確定來建立SQL Server登入帳號,並且和資料庫有關聯了。

image

接下來,我們到FileTable的地方,並且選擇權限,我們就可以透過搜尋找到剛剛建立的SQL Server登入帳號,那這邊我給的權限也是刪除、更新、插入、選取,理論上改變應該是可以不用勾選,同樣的,如果真的不行,大家還是可以回來勾勾看。

image

這邊是插入和選取的地方。

image

完成之後,終於就可以順利的寫入進去了( 淚 )。

image

這樣,就完成了權限的設定~~

後記

最後,還是要感謝各位同事的支援,與老師的協助也花了大家非常多的時間…重點是,到最後帳號其實都ok,但小弟程式有誤,所以還以為不行,在那邊繞圈子…真是對不起阿 ( 遮臉.. ),總之,造成大家困擾了,在這邊感謝大家協助,也希望這篇文章能協助到有遇到相同困難的朋友~~

Sky & Study4.TW