UWInfo Blog
發表新文章
[Join] | [忘記密碼] | [Login]
搜尋

搜尋意見
文章分類-#Author#
[所有文章分類]
所有文章分類
  • ASP.NET (48)
  • ASP.NET2.0 (15)
  • ASP.NET4.0 (34)
  • JavaScript (49)
  • jQuery (26)
  • FireFox (4)
  • UW系統設定 (3)
  • SQL (39)
  • SQL 2008 (25)
  • mirror (4)
  • SVN (4)
  • IE (9)
  • IIS (20)
  • IIS6 (1)
  • 閒聊 (7)
  • W3C (6)
  • 作業系統 (9)
  • C# (24)
  • CSS (12)
  • FileServer (1)
  • HTML 5 (11)
  • CKEditor (3)
  • UW.dll (13)
  • Visual Studio (16)
  • Browser (8)
  • SEO (1)
  • Google Apps (3)
  • 網站輔助系統 (4)
  • DNS (5)
  • SMTP (4)
  • 網管 (11)
  • 社群API (3)
  • SSL (4)
  • App_Inventor (1)
  • URLRewrite (2)
  • 開發工具 (6)
  • JSON (1)
  • Excel2007 (1)
  • 試題 (3)
  • LINQ (1)
  • bootstrap (0)
  • Vue (3)
  • IIS7 (3)
  • foodpanda (2)
  • 編碼 (2)
  • 資安 (3)
  • Sourcetree (1)
  • MAUI (1)
  • CMD (1)
  • my sql (1)
最新回應
  • Newtonsoft.Json.JsonConvert.DeserializeObject 失敗的情況
    test...more
  • dotnet ef dbcontext scaffold
    ...more
  • [ASP.NET] 利用 aspnet_regiis 加密 web.config
    ...more
  • IIS ARR (reverse proxy) 服務安裝
    ...more
  • [錯誤訊息] 請加入 ScriptResourceMapping 命名的 jquery (區分大小寫)
    ...more
  • 用 Javascript 跨網頁讀取 cookie (Cookie cross page, path of cookie)
    ...more
  • 線上客服 - MSN
    本人信箱被盜用以致資料外洩,是否可以請貴平台予以協助刪除該信箱之使用謝謝囉...more
  • 插入文字到游標或選取處
    aaaaa...more
  • IIS 配合 AD (Active Directory) 認証, 使用 .Net 6.0
    太感謝你了~~~你救了我被windows 認證卡了好幾天QQ...more
  • PostgreSQL 的 monitor trigger
    FOR EACH ROW 可能要改為 FOR EACH STATEMENT ...more
標籤
  • en
  • uw
  • 網址
  • dead lock
  • vb.net
  • 鏡像
  • jq
  • 問題
  • ad
  • ios
  • javascript
  • 20
  • [U2]
  • �
  • 80
  • sqldepende
  • visual
  • 下載
  • 具有潛在危險
  • 594
  • date
  • unicode
  • -5137 UNIO
  • ashx
  • aspx
  • 8
  • net
  • visualsvn
  • .net
  • C
  • NxFRfXz6
  • 0
  • a
  • html
  • tls
  • HTTP 錯誤 50
  • EN ORDER B
  • 16
  • Certificat
  • 150
  • validateco
  • aspnet_reg
  • 3072
  • Xml
  • orm
  • 2981
  • 1
  • fredck.fck
  • WU
  • window
頁數 1 / 5 下一頁
搜尋 user 結果:
.Net 7 的坑 UseStaticFiles 無效, 被 Routing Rule 攔截了
在新增 .Net 7 專案時。不用特別指定 app.UseRouting() 就可以使用 attribute routing.

但會遇到一個問題:

原來應該出靜態檔案的 Request 會被符合 Routing Rule 的 Action 攔截。

解決的方法是 :

在 UseStaticFiles 之後手動再加上 app.UseRouting(), 範例如下:

app.UseStaticFiles(new StaticFileOptions
{
    OnPrepareResponse = ctx =>
    {
        const int durationInSeconds = 60 * 60 * 24 * 365; //一年
        ctx.Context.Response.Headers[HeaderNames.CacheControl] =
            "public,max-age=" + durationInSeconds;
    }
});

app.UseRouting();
More...
Bike, 2023/3/2 下午 03:32:41
Sourcetree 重新安裝
Sourcetree重新安裝(完整清除舊資料)

1. 移除電腦上的Sourcetree軟體
2. 備份以下檔案後,然後刪除:
路徑:C:\Users\<UserName>\AppData\Local  刪除 SourceTree 資料夾
路徑:C:\Users\<UserName>\AppData\Local\Atlassian 刪除 SourceTree 資料夾
路徑:C:\Users\<UserName>\AppData\Roaming\Atlassian 刪除 SourceTree 資料夾
3. 重新下載Sourcetree軟體進行安裝

參考來源:
https://community.atlassian.com/t5/Sourcetree-questions/How-do-I-fully-remove-SourceTree-so-that-I-can-do-a-quot-fresh/qaq-p/1448403
More...
choco, 2023/2/2 上午 08:13:27
Orable table lock soluiton
當發現於Developer下Script時,ScriptRunner一直在跑都不會停的時候,請先暫停該Query。

1. 查出哪隻Session將Table lock住了
select b.owner,b.object_name,a.session_id,a.locked_mode from v$locked_object a,dba_objects b where b.object_id = a.object_id;

2. 取得該Session SID與SERIAL#,順便可以看是哪個SQL帳號Lock的
select b.username,b.sid,b.serial#,logon_time from v$locked_object a,v$session b where a.session_id = b.sid order by b.logon_time;

3. 使用下面這段SQL,帶入SID與SERIAL#即可將該Session Kill
alter system kill session'{SID}, {SERIAL#}';
More...
梨子, 2022/10/26 下午 08:35:31
Windows AD 登入後,使用 DirectoryServices 取得使用者的資訊
今天解了一個 Bug.

在網路上找到AD 登入後, 使用 DirectoryServices 取得使用者的資訊的 Sample Code 如下:
            var name = User.Identity.Name.Split('\\')[1]; //*@I was getting name as domain\\name @*
            DirectorySearcher ds = new DirectorySearcher();
            ds.Filter = "(&(objectClass=user)(objectcategory=person)(name=" + name + "))";
            SearchResult userProperty = ds.FindOne();


User 反應有一些員工登入後會沒有查到使用者資訊,後來發現若是在 AD 中建立使用者時,使用者的名稱和登入帳號不一致的話,會抓不到使用者資料。

最後經過一翻努力後,終於找到要改用 "samaccountname" 來做為 Filter 的條件。

            var name = User.Identity.Name.Split('\\')[1]; //*@I was getting name as domain\\name @*
            DirectorySearcher ds = new DirectorySearcher();
            ds.Filter = "(&(objectClass=user)(objectcategory=person)(samaccountname=" + name + "))";
            SearchResult userProperty = ds.FindOne();
More...
Bike, 2022/4/18 下午 05:30:49
使用 Gmail API 及 Google API 憑證的取得流程
這裡是我測試 Gmail API 和 Google API 憑証的一些記錄。

如果你的目的是要使用 Gmail Api 取代舊的 Gmail SMTP 來發送通知信,建議你先跳到最下方看一下結論。

如果你是想要看一下 Gmail API 和 Google API 憑証的使用方法,可以看一下這篇文章。

1. 在 google cloud platform 建立新的專案.
https://console.cloud.google.com/

 
 



啟用 Gmail API







 



 


 
 



因為我們要透過 OAuth  取得使用者授權,所以要設定使用 OAuth 的同意畫面。

 
指定授權的範圍
 

 
因為剛建立的專案,不會被公開,所以要指定測試使用者
 
如果要給任意使用者,必需經過發布的流程,但準備工作有點麻煩,所以這次就不發布了。
 




建立 OAuth 2.0 用戶端 ID 憑証
 
這裡除了名稱外,還有一個設定重導 Uri 的項目。現在不填寫,但稍後要回來補這個資料。
 
 
 下載 json 之後,命名為 client_secret.json 保留後續使用。


再來就要建立專案了. 用 VS2022 建立一個新專案
  


 




記錄網址, 本測試專案是 https://localhost:44340/ ,請依實際網址為準。



回到 OAuth 2.0 用戶端 ID 的設定頁. 在已授權的重新導向 URI 中填入 https://localhost:44340/Home/AuthReturn (填入的網址依實際專案的狀況,可能會有變化)
 
 

在 VS2022 中,使用 Nuget 安裝套件: (有漏的再麻煩和我說)
Google.Apis.Gmail.v1
Google.Apis.Auth
MimeKit (發送 gmail 時使用)

建立認証用的網址:
建立一個 Action, 用來取得認証用的網址:
        /// <summary>
        /// 取得授權的項目
        /// </summary>
        static string[] Scopes = { GmailService.Scope.GmailSend };

        // 和登入 google 的帳號無關
        // 任意值,若未來有使用者認証,可使用使用者編號或登入帳號。
        string Username = "ABC";

        /// <summary>
        /// 存放 client_secret 和 credential 的地方
        /// </summary>
        string SecretPath = @"D:\project\GmailTest\Data\Secrets";

        /// <summary>
        /// 認証完成後回傳的網址, 必需和 OAuth 2.0 Client Id 中填寫的 "已授權的重新導向 URI" 相同。
        /// </summary>
        string RedirectUri = $"https://localhost:44340/Home/AuthReturn";

        /// <summary>
        /// 取得認証用的網址
        /// </summary>
        /// <returns></returns>
        public async Task<string> GetAuthUrl()
        {
            using (var stream = new FileStream(Path.Combine(SecretPath, "client_secret.json"), FileMode.Open, FileAccess.Read))
            {
                FileDataStore dataStore = null;
                var credentialRoot = Path.Combine(SecretPath, "Credentials");
                if (!Directory.Exists(credentialRoot))
                {
                    Directory.CreateDirectory(credentialRoot);
                }

                //存放 credential 的地方,每個 username 會建立一個目錄。
                string filePath = Path.Combine(credentialRoot, Username);
                dataStore = new FileDataStore(filePath);

                IAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow(new GoogleAuthorizationCodeFlow.Initializer
                {
                    ClientSecrets = GoogleClientSecrets.Load(stream).Secrets,
                    Scopes = Scopes,
                    DataStore = dataStore
                });

                var authResult = await new AuthorizationCodeWebApp(flow, RedirectUri, Username)
                .AuthorizeAsync(Username, CancellationToken.None);

                return authResult.RedirectUri;
            }
        }


執行結果:
 
用 chrome 開啟產生的網址: 


選取任一帳號,如果出現以下錯誤,請回到 "OAuth 同意畫面" 去新增測試使用者


 
因為應用程式尚未發布,所以會看到警告,勇敢的繼續下去


這裡會要求授權使用你的名義發送信件。(這是在程式中取得授權的項目 Scopes 中所指定的)


再繼續之後,會被重導至我們在 redirectUri  指定的網址。因為我們尚未完成,所以會看到錯誤,順便也可以看一下,會帶回哪一些參數。有 state, code, scope,共三個。


順便看一下,google 的套件會在 Credentials 的目錄下幫使用者建立一個目錄,在完成驗証前,會先放一個 System.String-oauth_XXX 的檔案,裡面的值和回傳的 state 是一樣的,這個應該是用來驗証回傳資料的。



接下來我們要新增 Action "AuthReturn" 如下:

        public async Task<string> AuthReturn(AuthorizationCodeResponseUrl authorizationCode)
        {
            string[] scopes = new[] { GmailService.Scope.GmailSend };

            using (var stream = new FileStream(Path.Combine(SecretPath, "client_secret.json"), FileMode.Open, FileAccess.Read))
            {
                //確認 credential 的目錄已建立.
                var credentialRoot = Path.Combine(SecretPath, "Credentials");
                if (!Directory.Exists(credentialRoot))
                {
                    Directory.CreateDirectory(credentialRoot);
                }

                //暫存憑証用目錄
                string tempPath = Path.Combine(credentialRoot, authorizationCode.State);            

                IAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow(
                new GoogleAuthorizationCodeFlow.Initializer
                {
                    ClientSecrets = GoogleClientSecrets.Load(stream).Secrets,
                    Scopes = scopes,
                    DataStore = new FileDataStore(tempPath)
                });

                //這個動作應該是要把 code 換成 token
                await flow.ExchangeCodeForTokenAsync(Username, authorizationCode.Code, RedirectUri, CancellationToken.None).ConfigureAwait(false);

                if (!string.IsNullOrWhiteSpace(authorizationCode.State))
                {                
                    string newPath = Path.Combine(credentialRoot, Username);
                    if (tempPath.ToLower() != newPath.ToLower())
                    {
                        if (Directory.Exists(newPath))
                            Directory.Delete(newPath, true);

                        Directory.Move(tempPath, newPath);
                    }
                }

                return "OK";
            }
        }


再跑一次上面的流程,最後回到 AuthReturn

在 D:\project\GmailTest\Data\Secrets\Credentials\ABC 裡面會產生一個檔案: 這個就是我們的 token 了。


看一下裡面的內容, 有 access_token, refresh_token, scope 等等, 用途應該很好猜了.. 不知道各項目的目途也沒有關係。只要有這個 token 就可以了。


refresh_token 的效期請參考以下文件:
https://developers.google.com/identity/protocols/oauth2 。也可以參考下圖, 若是要用 gmail api 來發送通知信(例如連絡我們),紅色的地方是比較令人困擾的,例如 6 個月以上,沒有人留言,原來留下的 refresh_token 就失效了。使用者必需重新建立一個 refresh_token 。

 
最後來使用 gmail api 發送通知信, 直接看程式碼如下: 在這個過程中遇到最大的問題除了憑証問題之外,另一個問題是編碼。直到最後找到可以用 MimeKit 把 System.Net.Mail.MailMessage 編碼成 Gmail API 的格式才解決。程式碼如下:

        public async Task<bool> SendTestMail()
        {
            var service = await GetGmailService();

            GmailMessage message = new GmailMessage();
            message.Subject = "標題";
            message.Body = $"<h1>內容</h1>";
            message.FromAddress = "bikehsu@gmail.com";
            message.IsHtml = true;
            message.ToRecipients = "bikehsu@gmail.com";
            message.Attachments = new List<Attachment>();

            string filePath = @"C:\Users\bike\Pictures\Vegetable_pumpkin.jpg";    //要附加的檔案
            Attachment attachment1 = new Attachment(filePath);
            message.Attachments.Add(attachment1);

            SendEmail(message, service);
            Console.WriteLine("OK");

            return true;
        }

        async Task<GmailService> GetGmailService()
        {
            UserCredential credential = null;

            var credentialRoot = Path.Combine(SecretPath, "Credentials");
            if (!Directory.Exists(credentialRoot))
            {
                Directory.CreateDirectory(credentialRoot);
            }

            string filePath = Path.Combine(credentialRoot, Username);

            using (var stream = new FileStream(Path.Combine(SecretPath, "client_secret.json"), FileMode.Open, FileAccess.Read))
            {
                credential = await GoogleWebAuthorizationBroker.AuthorizeAsync(
                GoogleClientSecrets.Load(stream).Secrets,
                Scopes,
                Username,
                CancellationToken.None,
                new FileDataStore(filePath));
            }

            var service = new GmailService(new BaseClientService.Initializer()
            {
                HttpClientInitializer = credential,
                ApplicationName = "Send Mail",
            });

            return service;
        }


        public class GmailMessage
        {
            public string FromAddress { get; set; }
            public string ToRecipients { get; set; }

            public string Subject { get; set; }
            public string Body { get; set; }
            public bool IsHtml { get; set; }

            public List<System.Net.Mail.Attachment> Attachments { get; set; }
        }


        public static void SendEmail(GmailMessage email, GmailService service)
        {
            var mailMessage = new System.Net.Mail.MailMessage();
            mailMessage.From = new System.Net.Mail.MailAddress(email.FromAddress);
            mailMessage.To.Add(email.ToRecipients);
            mailMessage.ReplyToList.Add(email.FromAddress);
            mailMessage.Subject = email.Subject;
            mailMessage.Body = email.Body;
            mailMessage.IsBodyHtml = email.IsHtml;

            if (email.Attachments != null)
            {
                foreach (System.Net.Mail.Attachment attachment in email.Attachments)
                {
                    mailMessage.Attachments.Add(attachment);
                }
            }

            var mimeMessage = MimeKit.MimeMessage.CreateFromMailMessage(mailMessage);

            var gmailMessage = new Google.Apis.Gmail.v1.Data.Message
            {
                Raw = Encode(mimeMessage)
            };

            Google.Apis.Gmail.v1.UsersResource.MessagesResource.SendRequest request = service.Users.Messages.Send(gmailMessage, "me");

            request.Execute();
        }

        public static string Encode(MimeMessage mimeMessage)
        {
            using (MemoryStream ms = new MemoryStream())
            {
                mimeMessage.WriteTo(ms);
                return Convert.ToBase64String(ms.GetBuffer())
                    .TrimEnd('=')
                    .Replace('+', '-')
                    .Replace('/', '_');
            }
        }



收到的信件:



結論:
使用 Gmail API 最大的原因是要增加安全性,和舊的 smtp 不同的地方是,使用 gmail api 之後,客戶不需要提供 gmail 的帳號和密碼就可以讓系統使用 gmail 發送信件,不過由於 refresh_token 的效期問題,可能會造成無法發送通知信而沒有任何人發現的情況,整個實用性會變的很低。

另一個還沒有測試的部份是應用程的啟用。這個審核不知道會不很麻煩,不過可以而知的時,整個流程會花更多的時間。

取代的做法: 可能要改用 Amazon 的 SES 來寄信,而且為了避免每個小網站都要跑 SES 的建立流程,準備來寫一個 API 給各網站使用,可以發送簡單的通知信。

以上的程式碼可以在這裡下載: https://github.com/bikehsu/GmailTest
More...
Bike, 2022/4/10 下午 09:31:15
IIS 配合 AD (Active Directory) 認証, 使用 .Net 6.0
環境說明:

AD Server: dc1 (192.168.101.109)
PC: pc110 (192.168.101.110)
PC: pc111 (192.168.101.111)

第一步,把 PC 加入 AD, 這個算是基本操作,網路上說明很多, 就不再截圖了。不過在這裡還是遇到了第一個問題,解決過程請參考另一份文件: https://blog.uwinfo.com.tw/Article.aspx?Id=486

第二步,在 Visual Studio 的測試環境中測試:
一開始是使用 .Net 6.0 來實作,沒想到找到的文件都是 .Net Core 3.1 的,所以先用 .Net Core 3.1 實做了一次,後來改用 .Net 6.0 實作才成功。使用 .Net 6.0 實作的過程如下:

1. 建立一個 MVC 的標準專案: 
 
為了避免憑証問題,所以拿掉了 HTTPS 的設定


2. 改寫 launchSettings.json:
iisSettings 中的 windowsAuthentication 改為 True, anonymousAuthentication 改為 false。如下圖:
 
3. 修改 Program.cs, 加入以下四行指令:
builder.Services.AddAuthentication(IISDefaults.AuthenticationScheme);
builder.Services.AddAuthorization();
app.UseAuthentication();
app.UseAuthorization();
(注意: UseAuthentication 要加在 UseAuthentication 之後, VS 2022 應該會提示要新增 using Microsoft.AspNetCore.Server.IISIntegration;)
 
4. 在 HomeController 增加一個 Action, 以讀取驗証資料:

        [Route("GetAuthenticatedUser")]
        [HttpGet("[action]")]
        public IdentityUser GetUser()
        {
            return new IdentityUser()
            {
                Username = User.Identity?.Name,
                IsAuthenticated = User.Identity != null ? User.Identity.IsAuthenticated : false,
                AuthenticationType = User.Identity?.AuthenticationType
            };
        }

        public class IdentityUser
        {
            public string Username { get; set; }
            public bool IsAuthenticated { get; set; }
            public string AuthenticationType { get; set; }
        }
 
5. 啟動時記得要改用 IIS Express (感覺早上花了兩三個小時在為了這個問題打轉):


6. 執行結果:

第三步,在 IIS 中安裝網站:
1. 在安裝 IIS 時,記得要勾選 windows 驗證


2. 安裝 .Net 6.0 的 Hosting Bundle
https://dotnet.microsoft.com/en-us/download/dotnet/6.0
 
3. 新增網站:
主機名稱留空白 (AD 驗証在網域內好像不會使用指定的主機名稱,這個有待後續再做確認)


如果沒有刪除預設網站,會遇到警告,直接確認即可.


要把 Default Web Site 關閉,再啟動測試站
 
要啟動 windows 驗証: 
在 web.config 中增加 
      <security>
        <authentication>
          <anonymousAuthentication enabled="false" />
          <windowsAuthentication enabled="true" />
        </authentication>
      </security>



修改 applicationHost.config:

檔案位置: %windir%\system32\inetsrv\config\applicationHost.config
這兩地方的 Deny 改為 Allow
<section name="anonymousAuthentication" overrideModeDefault="Deny" />
<section name="windowsAuthentication" overrideModeDefault="Deny" />

 
參考文件: https://docs.microsoft.com/zh-tw/iis/get-started/planning-for-security/how-to-use-locking-in-iis-configuration

3. 可以取得登入資訊如下:

4. 從 Domain 中另一台主機來存取,不用登入,自動取得目前登入者的資訊。
 
5. 從非網域主機連線: 會要求認証
 

目前遇到問題: 在網域中的電腦只能用主機名稱登入,非網域的電腦,才能夠使用網址登入。

測試專案下載: https://github.com/bikehsu/AD60
 
More...
Bike, 2022/3/19 下午 09:10:08
Client IP 判斷資安上的問題
由於 CDN 模式下,網站在判別 client ip 是透過 X-Forwarded-For 來判別來源IP
但因為 X-Forwarded-For 是可以偽裝的 header value,所以 hacker 會在裡面帶入特殊的IP,例如 127.0.0.1

這在正常 CDN 模式下,基本上應該沒有問題,因為程式上抓到的 X-Forwarded-For 會是最後一組IP
但萬一 client 端 不走CDN直連主機,開發者抓 client IP 是先抓 X-Forwarded-For,而不判斷網站是不是在 CDN 模式下
就會誤判來源IP。

解決方式可分為兩方面
1. 抓 X-Forworded-For 的 function 要判別內網IP (包括127.0.0.1),剔除掉
2. 網站程式判別白名單時,要用 Reuest.UserHostAddress 來判別內部IP
    使用 ClientIP_After_CDN 只能用來判別外部IP 
    * 如果允許IP清單寫在系統參數或資料庫,但內容是 (內網IP + 外網IP)混用,最好是分開來

另外有一個防火牆的設定有關,也是建置網站很重要的設定
也就是設定 policy 時 wan -> virtual ip ,要記得把 NAT 關掉,
不然網站抓到的 UserHostAddress 都會是 190.168.x.254 之類的IP,這樣問題就大了。

    
    
 
More...
darren, 2022/3/1 下午 02:11:45
CORS 實做 (jQuery + ASP.NET Core Web API)
加構獨立的 API Server 時, 要使用 Cookie 認証必需有以下條件:

1. Web Server 和 API Server 有相同的父網域.
2. Cookie 的網域指定到相同的父網域.
3. 在 API 的 Application 中允許 CORS Request, 需要修改 Startup.cs

3.1 在 ConfigureServices 中要加入  AddCors, 而且要記得 AllowCredentials()
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddCors(options =>
            {
                options.AddPolicy(name: "Cors(PolicyName",
                                 builder =>
                                 {
                                     builder.WithOrigins("https://web1.yourdomain.com",
                                                         "https://web2.yourdomain.com")
                                     .AllowCredentials();
                                 });
            });

            services.AddControllers()
                .AddNewtonsoftJson(opt =>
                 opt.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver());


3.2 在 Configure 中, 要加入 app.UseCors("Cors(PolicyName"), 記得要在  UseAuthorization() 之前.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            app.UseExceptionMiddleware();

            app.UseHttpsRedirection();

            app.UseHttpsRedirection();

            app.UseRouting();

            app.UseCors(MyAllowSpecificOrigins);

            app.UseAuthorization();



4. 在 Client 端要加上 withCredentials: true
                            $.ajax({
                                url: apiRoot + "apiurl",
                                type: 'GET',
                                dataType: 'json', // 預期從server接收的資料型態
                                success: function (res) {
                                    console.log("success: ");
                                    console.log(res);                                    
                                },
                                xhrFields: {
                                    withCredentials: true
                                },
                                error: function (XMLHttpRequest, textStatus, errorThrown) {
                                    alert("發生錯誤");
                                }
                            });
More...
Bike, 2021/10/24 下午 05:17:54
最簡單的 SQL Availability Group (沒有 Active Directory, 也沒有 Shared Storage)
1. 安裝 Failover-Clustering
Install-WindowsFeature Failover-Clustering –IncludeManagementTools


2. 建立 Cluster 用的帳號, 並加入管理員群組 (記得要換密碼
net user /add clustadm Sup33P@ssw0Rd!
net localgroup administrators clustadm /add


參考以下四篇文章, 有些地方可能要改一下, 有空來做一份中文版的.


https://www.mssqltips.com/sqlservertip/4951/deploy-a-windows-server-2016-failover-cluster-without-active-directory-part-1/
https://www.mssqltips.com/sqlservertip/4962/deploy-a-windows-server-2016-failover-cluster-without-active-directory--part-2/

https://www.mssqltips.com/sqlservertip/4991/implement-a-sql-server-2016-availability-group-without-active-directory-part-1/
https://www.mssqltips.com/sqlservertip/4996/implement-a-sql-server-2016-availability-group-without-active-directory-part-2/


這個也可以參考, 有很多指令碼, 可以省不少時間:

http://woshub.com/workgroup-failover-cluster-windows-server-2016/
More...
Bike, 2020/9/8 上午 08:14:15
命名規則

名命規則

C#: 

    參數, 區域變數: 小駝峰(CamelCasing)
    其它: 大駝峰(PascalCasing)
    參考:
    
https://docs.microsoft.com/zh-tw/dotnet/standard/design-guidelines/naming-guidelines

Javascript:
    小駝峰(CamelCasing)


網址:
    全小寫, 用 - (減號) 分隔單字
    參考:

    https://www.seoseo.com.tw/article_detail_609.html
    https://blog.miniasp.com/post/2011/01/14/Avoid-using-underline-as-domain-name-character
    http://epaper.gotop.com.tw/pdf/acn023600.pdf


class 名命 HTML : 
    全小寫, 用 - (減號) 分隔單字 

複合字範列:
Pascal Camel Not
BitFlag bitFlag Bitflag
Callback callback CallBack
Canceled canceled Cancelled
DoNot doNot Don't
Email email EMail
Endpoint endpoint EndPoint
FileName fileName Filename
Gridline gridline GridLine
Hashtable hashtable HashTable
Id id ID
Indexes indexes Indices
LogOff logOff LogOut
LogOn logOn LogIn
Metadata metadata MetaData, metaData
Multipanel multipanel MultiPanel
Multiview multiview MultiView
Namespace namespace NameSpace
Ok ok OK
Pi pi PI
Placeholder placeholder PlaceHolder
SignIn signIn SignOn
SignOut signOut SignOff
UserName userName Username
WhiteSpace whiteSpace Whitespace
Writable writable Writeable
DateTimePicker dateTimePicker DatetimePicker
More...
Bike, 2020/7/28 上午 08:00:08
|< 12345 >|
頁數 1 / 5 下一頁
~ Uwinfo ~