2020年10月19日 星期一

{WebForm}Forms驗證 登入登出頁

 四年前有寫過利用MVC架構建立Form 表單驗證

這次又有新的前輩寫的火星文web form版本的表單驗證

以下就來一一破解一下

首先,

利用web form的架構下都會以web.config去設定一些有的沒的

首先,在config 中利用authenticution 設定好的login 的頁面

<authentication mode="Forms">

      <forms protection="All" timeout="480" slidingExpiration="true" cookieless="UseDeviceProfile" loginUrl="backend/login.aspx" defaultUrl="backend/index.aspx" requireSSL="false" enableCrossAppRedirects="false">

        <credentials passwordFormat="SHA1" />

      </forms>

</authentication>

上面提到可見文件來了解每個項目的定義

接著實作backend/login.aspx,進行帳密的驗證

驗證成功後透過FormsAuthentication類別去寫入cookie

FormsAuthentication.RedirectFromLoginPage

(UsernameTextbox.Text, NotPublicCheckBox.Checked);


但天殺的前輩就要用FormsAuthenticationticket用自已的力量寫一次cookie

結果就會像下面這樣

FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(1, user.Name, DateTime.Now, DateTime.Now.AddHours(8), true, user.Serno.ToString());

string encryptedTicket = FormsAuthentication.Encrypt(ticket);

HttpCookie authCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket);

authCookie.Expires = ticket.Expiration;

 Response.Cookies.Add(authCookie);

那...config其實也不用設到這麼多參數了!!


那經過幾年後,問題來了,這個網站有四個相似的網站,分別for不同的狀態去操作

都架在同一個網域下的情況,就會發生明明是不同網站卻cookie互蓋的問題

主要就是同網域都把cookie寫在path:/ 下,那有二個解法:

1.cookie 名稱都取不同

2.path改位置

這裡用2這個項目進行調整,因為網站本來就放在同一個網域不同的子資料夾下,就直覺用path區分不同網站所存取的驗證cookie

首先在web.confg增加path這個參數設定

<forms protection="All" timeout="480" slidingExpiration="true" cookieless="UseDeviceProfile" loginUrl="backend/login.aspx" defaultUrl="backend/index.aspx" requireSSL="false" enableCrossAppRedirects="false" path="/a">

接著因為在login.aspx.cs中前輩又自已寫了add cookie段,也需要跟著調整,參數可見

FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(1, user.Name, DateTime.Now, DateTime.Now.AddHours(8), true, user.Serno.ToString(),FormsAuthentication.FormsCookiePath);


於似乎就能解決同一個網域下發生明明是不同網站卻cookie互蓋的問題


後記:因為logout.aspx.cs 也被「手動」的remove一些cookie,這些都是key point要注意連同修改cookie 路徑,以省的還是有被蓋的問題


2016年4月21日 星期四

{PowerShell} 執行ps1 停用指令碼問題

執行 ps1 檔時出現: 檔案無法載入,因為這個系統上已停用指令碼執行


開啟 系統管理員下的Powershell

2016年3月29日 星期二

{Excel-VBA} 取得當前的Sheet Name 與巨集的函數建立使用

剛好有閒來玩玩當時大學把老師嚇的半死的VBA程式
教大家如何建立一個簡單的巨集(VBA)

這邊主要是要利用Function的方式讓大家可以在Excel上呼叫自已寫的程式

首先,要先把Excel中的開發人員這個頁籤打開
1.選擇檔案>選項
2.接著將開發人員項目勾起來

2016年2月18日 星期四

{C#} 取連結Json資料作法

今天工作覺的無聊,打開「政府資料開放平臺」看看有什麼資料可以拿來用,創造出東西出來

第一次接觸這樣的東西,覺的相當有趣,而最初淺的就是直接看別人怎麼用這個網站的資訊創造出來東西



而身為最「弱」的程式開發員,今天就來試試,當不用前端程式呼叫某個網頁傳回的資料(俗稱Service),該怎麼做?
而一開始要準備好一個Service 網址,可以抓資料回來

2016年2月16日 星期二

{Interview 專區} 什麼是Forms驗證 登入登出頁

今天要來說說FormsAuthentication
每個網站與應用程式幾乎都要用登入的功能
就是要驗證使用者是否有權限這件事
而我從來沒在實作FormsAuthentication的經驗
面試被問到的時候還是一臉茫然
然後面試官就覺的這是人生絕望的失望情結
其實真的不太懂,有這麼嚴重嗎?
這個東西,通常前輩寫了一回,後輩就不會去改動到
只有沒事的時候去「偷翻」然後摸一摸
但你覺的摸一摸就會寫
我的領悟力沒這麼高....

回到主題
using System.Web.Security 之下有FormsAuthentication這個類別
裡面就包好了很多寫好的程式,簡單來說就是做帳戶登入登出轉址等等
而這裡面的原理就是寫一個cookie在使用者的電腦,並用加密的方式保留著
點選擇登出才會刪除cookie,或是使用者去做「網際網路選項」裡面把cookie刪掉
不然就算關掉網頁,再打開網頁依然是登入的狀態,不少網頁都是這樣,就像我剛登入的博客來,而我沒清掉我的cookie

利用網路上的範例,終於實現自已寫出一個登入登出的頁面,也許老手會覺的這三小,而對不想研究技術的我來說,已經是一個目標達成

首先,這是一個MVC的範例
Control:
//以下所有未加AllowAnonymous者,都一定要經過login 成功才可以進入
[Authorize]
    public class MainController : Controller
    {
        //不一定要經過login 成功才可以進入
        [AllowAnonymous]
        public ActionResult Login()
        {
            return View();
        }
        [AllowAnonymous]
        [HttpPost]
        public ActionResult Login(Log_Xml logxml)
        {
            //這邊就會進到Log_Xml 做Validate func
            if (!ModelState.IsValid)
            {
                return View();
            }
            //要讓會員登入成「已驗證」狀態的話
            FormsAuthentication.RedirectFromLoginPage(logxml.Account, false);
         
            return null;
        }
        [AllowAnonymous]
        [HttpPost]
        public void LogOut()
        {
            //清除Session中的資料
            Session.Abandon();
            //登出表單驗證
            FormsAuthentication.SignOut();
            //導至登入頁
            //return RedirectToAction("Login", "Main");
        }
}

{Interview 專區}什麼是Interface 與運用 by C#

這個年頭誰都可以當程式設計師,一直說服自已就是這樣所以沒啥好難
每個「很強」的部落客寫的落落長,裡面有多少的字看的懂,只能說我知道這是英文與中文

為何當一個程式設計師不能簡單一點?
今天,要講什麼是interface ,OO是三小,只有在課本上背著背著考,其他懶的管
現在回到正題「interface 是什麼」
interface 就是介面,好像一個好手寫I-N-T-E-R-F-A-C-E就很強,所以在自已的專案上也跟著寫,然後,不知道要幹麼用

在網路上不少範例,但簡單來說,介面就是在上面宣告幾個屬性、方法,然後給別人Implements。
interface Interface1
    {
        List<Class1> allData();
        Class1 Databycode(string code);
        string CreateData(Class1 newData);
    }

2016年2月15日 星期一

{C#}利用LDAP協定與AD Server驗證

主要語法:
//要驗證的username與pwd
string domainAndUsername = domain + @"\" + username;
DirectoryEntry entry = new DirectoryEntry(_path, domainAndUsername, pwd);
DirectorySearcher search = new DirectorySearcher(entry);
//要驗證的username
search.Filter = "(SAMAccountName=" + username + ")";
search.PropertiesToLoad.Add("cn");
SearchResult result = search.FindOne();
result 為null即AD無此帳號或帳密錯誤


未驗證的要求會被重新導向到 Logon.aspx 頁面
Web.config 檔
<configuration>
  <system.web>
    <authentication mode="Forms">
      <forms loginUrl="logon.aspx" name="adAuthCookie" timeout="10" path="/">
      </forms>
    </authentication>
    <authorization>
      <deny users="?"/>
      <allow users="*"/>
    </authorization>
<!--此組態,所有對此應用程式發出的要求都會以已設定之帳戶的安全性內容執行。使用者必須提供認證以向 Active Directory 網域服務驗證,但只有已設定的帳戶可存取 Active Directory 網域服務。--!>
    <identity impersonate="true"/>
  </system.web>
 </configuration>


2016年1月25日 星期一

{SQL} 產生Script 好好用之「匯出Insert Into Table資料」「匯出Stored Procedure」

因為要做一些文件,需要運用到「把table的資料轉為insert into 語法」與「匯出預存程序」的問題 在此做一個記錄
1.把table的資料轉為insert into 語法
1.1物件總管裡要轉出的Table的資料庫按「右鍵」>「工作」>「產生指令碼」
1.2打開「產生和發佈指令碼」>「下一步」
1.3選取特定的資料庫物件
1.4出現樹狀結溝的樣貌,打開「資料庫」,選擇所要的Table名稱
1.5點擊「下一步」出現指定指令碼的儲存或發行方式
1.6點擊「進階」>「一般」有一個「要編寫指令碼的資料類型」
1.7在「要編寫指令碼的資料類型」中有三個選項
1.7.1僅限資料:只會有insert into 所有Table資料的指令
1.7.2僅限結構(預設):只會有create table 的指令
1.7.3「結構描述和資料」:create table 的指令與insert into 所有Table資料的指令
1.8如果希望拿到指令的人可以先drop table再重新建立table的指令,那在「一般」有一個「編寫DROP和CREATE的指令碼」
1.8.1「編寫CREATE指令碼」(預設):只產出Create指令碼
1.8.2「編寫DROP和CREATE的指令碼」:產出Drop 和Create指令碼
1.8.3「編寫DROP指令碼」:只產出Drop指令碼
1.9接著就是不斷下一步,完成 

2016年1月14日 星期四

{SQL} 單欄資料列取值方式(資料指標-FETCH 迴圈)

逐列處理資料的方式其一Cursor
 DECLARE @temp_addr NVARCHAR(100)=NULL
 DECLARE @temp_zipcode NVARCHAR(10)
 DECLARE @temp_district NVARCHAR(50)
 DECLARE @temp_city NVARCHAR(50)
 DECLARE @temp_IsPostAddr NVARCHAR(1)
 DECLARE @temp_ori NVARCHAR(400)
 DECLARE @data_count INT=0
 SET @temp_ori= dbo.f_AddressMerge(@mail_addr_dis,@mail_road,@mail_lane,@mail_alley,@mail_number_start,@mail_number_end,@mail_floor_start,@mail_floor_end,@mail_room,@mail_remark,@mail_post_name,@mail_postal_address,@mail_lane_l,@mail_alley_l,@mail_hong,@mail_hong_l,@mail_number_start2) ----宣告一個指標
DECLARE  my_cur CURSOR FOR (
--回傳純量函數
         SELECT res from  f_SplitToTable(@temp_ori,',')
        )
--開啟指標
open my_cur
--當指標的狀態為0, 即指標內尚有資料
--如知道資料列中有多少資料,可以用data_count變數來判斷
--WHILE @@fetch_status = 0 AND @data_count<5
WHILE @data_count<5
            BEGIN
--By不同列指定給不同的變數
                SET @data_count=@data_count+1
                IF @data_count='1'
                BEGIN
                FETCH NEXT FROM my_cur INTO @temp_IsPostAddr--,@temp_zipcode,@temp_city,@temp_district,@temp_addr
                END
                IF @data_count='2'
                BEGIN
                FETCH NEXT FROM my_cur INTO @temp_zipcode--@temp_city,@temp_district,@temp_addr
                END
                IF @data_count='3'
                BEGIN
                FETCH NEXT FROM my_cur INTO @temp_city--,@temp_district,@temp_addr
                END
                IF @data_count='4'
                BEGIN
                FETCH NEXT FROM my_cur INTO @temp_district--,@temp_addr
                END
                IF @data_count='5'
                BEGIN
                FETCH NEXT FROM my_cur INTO @temp_addr
                END
            END
--關閉指標
        CLOSE my_cur
--釋放記憶體
        DEALLOCATE my_cur

--方式二 DECLARE @temp_addr NVARCHAR(100)=NULL DECLARE @temp_zipcode NVARCHAR(10) DECLARE @temp_district NVARCHAR(50) DECLARE @temp_city NVARCHAR(50) DECLARE @temp_IsPostAddr NVARCHAR(1) DECLARE @temp_ori TABLE (IsPostAddr nvarchar(1), zipcode nvarchar(6), city nvarchar(20), district nvarchar(20), result nvarchar(300)) DECLARE @data_count INT
--回傳多重式資料表直函式 INSERT INTO @temp_ori(IsPostAddr,zipcode,city,district,result)  
(SELECT * FROM dbo.tf_AddressMerge(@mail_addr_dis,@mail_road,@mail_lane,@mail_alley,@mail_number_start,@mail_number_end,@mail_floor_start,@mail_floor_end,@mail_room,@mail_remark,@mail_post_name,@mail_postal_address,@mail_lane_l,@mail_alley_l,@mail_hong,@mail_hong_l,@mail_number_start2)) SET @data_count=(SELECT COUNT(*) CT FROM @temp_ori) IF @data_count>0 BEGIN SET @temp_IsPostAddr =(SELECT TOP 1 IsPostAddr FROM @temp_ori) SET @temp_zipcode =(SELECT TOP 1 zipcode FROM @temp_ori) SET @temp_city =(SELECT TOP 1 city FROM @temp_ori) SET @temp_district =(SELECT TOP 1 district FROM @temp_ori) SET @temp_addr =(SELECT TOP 1 result FROM @temp_ori) END

2015年10月12日 星期一

{SQL}tempdb 的temp table 釋放

Tempdb:建立temp table ,讓資料暫時放置在寫到實體的Table

確認TEMP TABLE 是否在用完後有釋放掉:
IF Object_id('tempdb..TEMPTABLENAME') IS NOT NULL

BEGIN

      DROP TABLE #temp

END

參考資料
http://www.dotblogs.com.tw/justforgood/archive/2014/02/20/144091.aspx

2015年10月5日 星期一

{C#}實作IEnumerable 介面 讀出列舉陣列

下列示範在MVC架構中,實作IEnumerable介面
在Yahoo 字典中,Enumerable的意思是「可列舉的」adj.
主要就是把一個集合中的資料一 一讀出的運作流程

1.首先建立一個Class 並繼承Franmework的IEnumerable介面
在IEnumerable介面上只有一個Function
這可以從MSDN上可以看到
https://msdn.microsoft.com/zh-tw/library/system.collections.ienumerable(v=vs.110).aspx
接著開始寫自已的列舉器

//1.繼承IEnumerable
//資料結構中的資料,是否可被列舉
public class IEnumeratorClass:IEnumerable {
private string[] EmployeeList = { "John", "Jay", "Bobo" };
//IEnumerable界面下的function
public IEnumerator GetEnumerator()
{ return new EmployeeEnumerator(this); }
//2.自定義「資料結構實作的列舉器」
public class EmployeeEnumerator : IEnumerator
{ //元素
string[] _elements;
//指標
int _flag = -1;
//建構子
public EmployeeEnumerator(IEnumeratorClass source) { _elements = source.EmployeeList; }
//實作Reset Void 重新設定Flag
public void Reset() { this._flag = -1; }
//實作Current 回傳當前的值
public object Current { get { if (this._flag == -1 || this._flag > this._elements.Length) { //Exception throw new InvalidOperationException(); } return this._elements[this._flag]; } }
//指標移至下一筆是否可行
public bool MoveNext() { if (this._flag + 1 == this._elements.Length) return false; else { this._flag++; return true; } }
//取資料結束後,要做任何Release、關閉資料庫連結等覆寫
public void Dispose() { } } }



在Controller中

public ContentResult EmployeeGet() { string allEmployee = ""; IEnumeratorClass employeeName = new IEnumeratorClass(); IEnumerator enumerator = employeeName.GetEnumerator(); //當可以移至下一筆時 while (enumerator.MoveNext()) { //Show出所有的集合資料 allEmployee += enumerator.Current; } return Content(allEmployee); }
參考資料:
http://xingulin.tumblr.com/post/48831985749/ienumerable-ienumerator

2015年10月2日 星期五

{MVC} Linq to sql 搭配MVC 基本運作

離開程式三個多月,重拾卻步步難走
不如就記錄一下,最最最基礎的東西
建立一個MVC專案
最簡單就是建一個Textbox 與一個Button
以db first的方式寫入資料庫
這是一個最簡單的例子

Views:
//整頁做Postback
@using (Html.BeginForm("Test", "Home", FormMethod.Post))
{
//建立一個address 的textbox
@Html.TextBox("address")
//建立一個按鈕
    <input type="submit" name="btnSubmit" value="Convert" />
}

按鈕Type為submit ,一點下就會Postback 到指定的Action


Control:
傳入為Textbox 的內容,放上Textbox 的name屬性
Linq to Sql 建立一個db連線,接著就可以將資料寫入db

 [HttpPost]
        public ContentResult Test(string address)
        {
            try {
           
                MyProject_GoogleMapLocation newItem = new MyProject_GoogleMapLocation();
                newItem.ADDRESSCHT = address;
                //Save Database
                using (var context = new HomeDataContext())
                {
                    context.MyProject_GoogleMapLocation.InsertOnSubmit(newItem);
                    context.SubmitChanges();
                }
            }
            catch(Exception e)
            {
                return Content( e.Message);
            }
           
            return Content("Successful");
        }

2015年10月1日 星期四

{工具} Azure Create Table (Sql Server-SSMS)

在SSMS 建立新的Table 方法:
1.先在Azure 取得連接字串


2.開啟SSMS
 2.1 依據Azure 上提供的連接字串,登入Azure DB SSMS,點擊新建立的資料庫,新增查詢
(以下圖來說新建立的資料庫為WalkCarDB)
2.2 並下Create Table Sql



參考資料:
https://www.youtube.com/watch?v=NnXXEFxH228



{工具} Visual Studio 發行網站至Windows Azure

1.先去Windows Azure 下載發行檔


2.在專案下的架構是這樣

3.在專案按右鍵選取「發行」


4.發行檔匯入

5.發行檔自動就會帶出下列訊息(含服務URL)








2015年9月24日 星期四

{IIS}發行網站遇到的問題(HTTP 錯誤 500.19 權限不足、錯誤碼:0x80070021、網頁伺服器已設為不列出此目錄的內容)

今天嘗試將寫好的MVC網站Publish 到IIS,建立新的網站
過去的工作都有「專人」都設定好,工程師就是傻傻的搬到指定的位置
放錯還要被念之類的,今天獨立架入本機的IIS,但礙於非個人電腦,權限上限制很多
最多就是Localhost讀出網頁囉!
首先在VS上發行網站
一連串就有下列問題,先來看一下怎麼發行網站
先在VS的專案右鍵「發行」就會出現下面的畫面
一開始如果沒有發行過會先新增設定檔。

 接著就是要發行去哪,過去都是放到另一個資料夾,在透過資料夾Publish 網站上IIS
所以這裡用「檔案系統」,目標位置就自已找想放的地方

接著到IIS的網址上建一個「應用程式」,實體路徑當然要跟上圖目標位置一樣,就可以了。

HTTP 錯誤 500.19 權限不足:
因為不是自已的電腦,常是很卡,這個原因就是資料夾的權限少了「Users」
加上Users的權限就可以了


錯誤碼:0x80070021:
控制台>程式集>程式和功能>開始或邊關閉Windows功能>IIS>World wide web 服務>應用程式開發功能>ASP.NET(打勾)

網頁伺服器已設為不列出此目錄的內容:
將下圖的功能啟用



參考資料
http://silanors.blogspot.tw/2011/04/iisiis7.html
http://blog.xuite.net/s900aaaa/Program/42544521-IIS7%E5%9F%B7%E8%A1%8C%E6%99%82,%E7%94%A2%E7%94%9F%E9%8C%AF%E8%AA%A4%E7%A2%BC%3A+0x80070021+
https://support.microsoft.com/zh-tw/kb/942062

2015年9月22日 星期二

{SSIS} OLE DB 來源匯入Excel

Build SSIS時,出現下列的問題:(問題只找關鍵字)
64位元版本的SSIS不支援Excel連接管理員

一查預設專案的運行來源跑64位元的Runtime,但Microsoft OLE DB Provider for Jet 64 位元版本沒有for Excel的版本 ,所以解決方式就是讓他運行來源跑32位元Runtime

而設定就在專案右鍵「屬性」
「偵錯」Tag下的偵錯選項:Run64bitRuntime 選擇False

資料來源:
https://support.microsoft.com/zh-tw/kb/2323097
http://www.dotblogs.com.tw/jamesbi/archive/2010/02/11/13651.aspx

2015年9月10日 星期四

{SQL}SSMS 管理工具 intellisense 失效

 SQL Server 2008 R2 SSMS 管理工具 intellisense 因VS 2010 SP1 安裝、升級而失效問題
主要是因為VS 2010 SP1對SSMS 管理工具intellisense 相容性的問題
直接解決的方式是升級  SQL Server 2008 R2



參考資料:
http://sharedderrick.blogspot.tw/2011/04/vs-2010-sp1-ssms-intellisense.html

2015年1月8日 星期四

{SQL} 取相同年月數量總合

SELECT
CAST(MONTH(DocumentDate) AS VARCHAR(2)) + '-' + CAST(YEAR(DocumentDate) AS VARCHAR(4)) AS DocumentDate,
SUM(QTY) AS qty
FROM [FAToolService].[dbo].[ConsolidatedGPRawDataDetail]
GROUP BY   CAST(MONTH(DocumentDate) AS VARCHAR(2)) + '-' + CAST(YEAR(DocumentDate) AS VARCHAR(4))


DocumentDate 是年-月-日 的Datetime 格式。
取每個月的數量總合....

2014年7月10日 星期四

{JavaScript} Close 畫面 並將父畫面Reload

Close 畫面 並將父畫面Reload

Script:
window.opener.location.reload();
window.close();

C# 編寫JavaScript 語法
//直接關閉視窗
        public void Close()
        {
            Page p = (Page)System.Web.HttpContext.Current.Handler;
            ClientScriptManager CSM = p.ClientScript;
            String ScriptName = "close";
            String ScriptMsg = "window.opener.location.reload();window.close();";
            Type CsType = p.GetType();
            if (!CSM.IsStartupScriptRegistered(CsType, ScriptName))
            {
                CSM.RegisterStartupScript(CsType, ScriptName, ScriptMsg, true);
            }
        }

參考資訊:
http://stackoverflow.com/questions/19027959/how-to-refresh-parent-page-after-closing-popup-window-in-javascript