Design

Design
asp.net mvc

2020年11月24日 星期二

K8S

 



2020年4月29日 星期三

[紀錄]HOTP TOTP計算邏輯

 
namespace OTP
{
    class Program
    {
        static void Main(string[] args)
        {
            //密鑰
            byte[] key = Encoding.ASCII.GetBytes("lnh_key");

            for (var i = 0; i < 100; i++)
            {
                //每十秒更變一次密碼
                var otp = TOTP(key, 10, 6);
                Console.WriteLine(otp);
                Thread.Sleep(1000);
            }
        }
        


        public static string HOTP(byte[] key, byte[] counter, int length = 6)
        {
          
            var hmac = ToHMACSHA1(counter, key);

            var offset = hmac[hmac.Length - 1] & 0xF;
           
            var b1 = (hmac[offset] & 0x7F) << 24;
            var b2 = (hmac[offset + 1] & 0xFF) << 16;
            var b3 = (hmac[offset + 2] & 0xFF) << 8;
            var b4 = (hmac[offset + 3] & 0xFF);

            var code = b1 | b2 | b3 | b4;

            var value = code % (int)Math.Pow(10, length);

            return value.ToString().PadLeft(length, '0');
        }


        public static string TOTP(byte[] key, int step = 60, int length = 6)
        {
            var unixTime = (DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc)).TotalSeconds;
            var counter = ((int)unixTime) / step;
            var counterBytes = BitConverter.GetBytes(counter);
            return HOTP(key, counterBytes, length);
        }


        public static byte[] ToHMACSHA1(byte[] value, byte[] key)
        {
            if (value == null || value.Length == 0)
            {
                throw new ArgumentNullException(nameof(value));
            }
            if (key == null || key.Length == 0)
            {
                throw new ArgumentNullException(nameof(key));
            }
            using (var macAlgorithm = new HMACSHA1())
            {
                macAlgorithm.Key = key;
                return macAlgorithm.ComputeHash(value);
            }
        }

    }

}

2020年3月19日 星期四

[TOOL] clumsy 模擬弱網路環境工作(windows環境)


一般我們使用fiddler或是其他工具想要模擬弱網路的狀況,卻都沒有丟包的功能這邊我稍微找了一下推薦一個簡單操作實用的工具詳細功能如下,用的語法可以參考官網.
https://jagt.github.io/clumsy/manual.html



1.延遲(Lag),把資料包快取一段時間後再發出,這樣能夠模擬網路延遲的狀況。

2.掉包(Drop),隨機丟棄一些資料。

3.節流(Throttle),把一小段時間內的資料攔截下來後再在之後的同一時間一同發出去。

4.重發(Duplicate),隨機複製一些資料並與其本身一同傳送。

5.亂序(Outof order),打亂資料包傳送的順序。 6.篡改(Tamper),隨機修改小部分的包裹內容。


這邊做個簡單的模擬
例如今天我們想針對IP *.*.*.* 的進行環境的弱化我們直接看圖,可以看到我們ping這IP時已經有延遲跟丟包的狀況,相對比較進階其他功能大家可以研究看看


2019年12月3日 星期二

Sumitomo Mitsui Trust Bank Programming Contest 2019


I found a website that help promotes logical thinking , there will be a period of competition , you can register get start for the competition and get points , Let's take a look at recent matches .


















A - November 30

Solution

2019-M2-D2 follows 2019-M1-D1 so we just check M1 & M2 are they equal

m1, d1 = map(int, input().split())
m2, d2 = map(int, input().split())
 
if m1 == m2:
 print(0)
else:
 print(1)



B - Tax Rate

Solution

this question the point is rounded down to the nearest integer , math.ceil(N / 1.08) is before tax  ,  round down math.ceil(N / 1.08) times 1.08 to an integer if result equal N Takahashi's memory is true  print(result) else false print(":(")
import math
N = int(input())
 
B = math.ceil(N / 1.08)
if math.floor(B * 1.08) == N:
  print(B)
else:
  print(':(')

C - 100 to 105

Solution

if one items cost range is 100~105 , two items is 200 ~210 , three items is 300~315 , and so on ,
each item plus 5 tens digit , so we can get the rules
x = int(input())
count = x//100
res = x%100
if count*5 >= res:
    print(1)
else:
    print(0)

D - Lucky PIN

Solution

Use three loops to get three unique values. Loops meet the condition index value +1 to find the value of the next position
N = int(input())
S = input()
cnt = 0

 
for i in range(10):
    for j in range(10):
        for k in range(10):
            idx = S.find(str(k))
            if idx != -1:
                idx = S.find(str(j),idx+1)
                if idx != -1:
                    idx = S.find(str(i),idx+1)
                    if idx != -1:
                        cnt += 1
                        print(k,j,i)
 
print(cnt)
to be continued....

2019年11月7日 星期四

[紀錄]nodejs Mongodb分頁模糊查詢

 
app.post('/api/video', function (req, res) {
  try {
    var PageSize = req.body.PageSize;
    var PageIndex = req.body.PageIndex;
    if (!PageSize || !PageIndex) {
      return;
    }

    var Search = {};
    if (req.body.Search) {
      Search = {
        'name': {
          $regex: `^.*${req.body.Search}.*`,
          $options: 'i'
        }
      }
    }
    var dbo = client.db("db");

    dbo.collection('video').find(Search).sort({
      upload_at: -1
    }).skip(PageSize * PageIndex - PageSize).limit(PageSize).toArray((err, items) => {
      if (err) {
        console.log(err)
        throw err;
      }
      dbo.collection('video').countDocuments(Search, function (err, count) {
        res.end(JSON.stringify({
          "result": items,
          "pageCount": Math.ceil(count / PageSize),
          "videoCount": count,
        }));
      client.close();
      })
    });
  } catch (e) {
    console.error(e);
  }
});

MessagePack vs json.Net 效能PK

Perf comparison graph

一張圖吸引了我去測試MessagePack的效能
至於是不是真的這麼神  我們時間跑看看測試程式碼跟執行結果如下

Main:
    public  static void Main(string[] args)
        {
            MessagePackSerializer.SetDefaultResolver(MessagePack.Resolvers.ContractlessStandardResolver.Instance);

            var summary = BenchmarkRunner.Run();
            Console.Read();
        }


Measure:

 
using BenchmarkDotNet.Attributes;
using MessagePack;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;

namespace SerializationPerformance
{
    [MemoryDiagnoser]
    public class Measure
    {

        public readonly MyClass data;
        public byte[] bytes;
        public string Json_string;
        public Measure()
        {
            MessagePackSerializer.SetDefaultResolver(MessagePack.Resolvers.ContractlessStandardResolver.Instance);
            data = new MyClass
            {
                Age = 99,
                FirstName = "hoge",
                LastName = "huga",
            };
            bytes = LZ4MessagePackSerializer.Serialize(data);
            Json_string = LZ4MessagePackSerializer.ToJson(bytes);
        }



        [Benchmark]
        public byte[] MessagePack_Serialize_Bytes()
        {
           byte[] result = MessagePackSerializer.Serialize(data);
            return result;
        }


        [Benchmark]
        public string MessagePack_Serialize_String()
        {
            byte[] result = MessagePackSerializer.Serialize(data);
            
            return MessagePackSerializer.ToJson(result);
        }


        [Benchmark]
        public MyClass MessagePack_Deserialize()
        {
            MyClass result = MessagePackSerializer.Deserialize(LZ4MessagePackSerializer.FromJson(Json_string));
            return result;
        }


        [Benchmark]
        public byte[] LZ4MessagePack_Serialize_Bytes()
        {
            var result = LZ4MessagePackSerializer.Serialize(data);
            return result;
        }


        [Benchmark]
        public string LZ4MessagePack_Serialize_String()
        {
            var result = LZ4MessagePackSerializer.Serialize(data);
            return MessagePackSerializer.ToJson(result);
        }

    
        [Benchmark]
        public MyClass LZ4MessagePack_Deserialize()
        {
           
            MyClass result = LZ4MessagePackSerializer.Deserialize(LZ4MessagePackSerializer.FromJson(Json_string));
            return result;
        }

        [Benchmark]
        public string jsonNet_Serialize()
        {

            string result = JsonConvert.SerializeObject(data);
            return result;
        }



        [Benchmark]
        public MyClass jsonNet_Deserialize()
        {
            var result = JsonConvert.DeserializeObject(Json_string);
            return result;
        }
    }

    public class MyClass
    {

        public int Age { get; set; }


        public string FirstName { get; set; }


        public string LastName { get; set; }

        public string FullName { get { return FirstName + LastName; } }
    }

}
可以看到我們較常用的object跟string之間的轉換速度上其實沒太大差異,如果單純只是二進制的轉換會快非常多 至於內存消耗可以看到MessagePack是優於json.Net不過型別的支援程度json.Net還是比較好用的 如果對於效能有要求這邊是滿推薦使用MessagePack只是在一些型別例如datetime jobject jarray等等格式就需要做另外formatter處理,就看個人的喜好決定了 轉為json字串也需要多打一串他的方法

2019年7月20日 星期六

心情上轉換

題外話..最近2T硬碟壞掉,多半一些隨興測試跟一些架構上原本要打在BLOGGER上的CODE,重要的還好有備份雲端,不過寫很多東西也算是滿珍貴的內容,會去修吧看能不能多少救回來一些.

拉回來 
我每天都會關注一些國內外投資跟軟體業相關資訊跟和一些電子報,綁定我的mail或通訊軟體,國外我推薦fastcompany,國內其中科技橘報算是內容滿符合我胃口的,可能因為我是軟體開發工程師? 

前幾天剛好聽到個橘報電台內容覺得滿值得思考的,也是我平常一直在調適自己的心態上跟作息上的方法,有興趣可以點下面.



一開始算是閒聊內容,介紹投資書的內容跟一些心得.
中半段開始談到如何優先投資自己的時間在重要的事情上面,我覺得比較有趣的接下來說的一些內容,查理.蒙格書有提到貪婪、恐懼、盲目樂觀、從眾、嫉妒,這些都是人類的在投資上的弱點,反過來說在工作上也都會這些情形,每個人往往都會有情緒,內容有提到我們今天覺得工作做的很得心應手很有成就感,我們就可以多做一點,今天我們心情差就少做一點,但不至於完全不做,今天你覺得你在工作是最重要的那就在工作多花點時間,今天你覺得你額外時間做其他事情比較重要,就把重要的時間在額外的事物上面,你最終一定要會有取捨,我還記得有次我在跟矽谷的前輩聊天,也是討論到取捨的問題,他說了why not both...,當時覺得果然是高手,其實現在想想有時候不是你能力範圍做不到,而是你心態上能否保持平衡,最重要還是你最終的選擇,你選擇了工作,還有啥好抱怨的,真的做不下去離開走人,也不要主觀做任何批判,有時候你想要的也不一定你承擔的住,凡事盡力而為,你最後雖然可能不能贏,但是你心態心境上至少都可以隨時保持進步的狀態,今天你對的起自己也能跟別人交代,機會還是會有的,跟自己是這樣說,我真的能做到嗎?
如何看待 Facebook 总部一中国男性职工因面临被辞退于 2019 年 9 月 19 日跳楼自杀?

2019年7月11日 星期四

FTP主動模式 & 被動模式

主動模式 ACTIVE


FTP客戶端隨機開啟一個大於1024的端口N向服務器的21號端口發起連接,發送FTP用戶名和密碼,然後開放N+1號端口進行監聽,並向服務器發出PORT N+1命令,告訴服務端客戶端採用主動模式並開放了端口。 FTP服務器接收到PORT命令後,會用其本地的FTP數據端口(通常是20)來連接客戶端指定的端口N+1,進行數據傳輸。
命令連線: 用戶端 port N –> 伺服器 port 21
資料連線: 伺服器 port 20 –> 用戶端 N+1
常見問題:
伺服器防火牆需開20、21,因為用戶端因為是隨機PORT作為連接,通常被擋都是用戶端防火牆,而且這風險也滿大的用戶端隨機開個PORT給外部連接.


被動模式 PASSIVE
FTP客戶端隨機開啟一個大於1024的端口N向服務器的21號端口發起連接,發送用戶名和密碼進行登陸,同時會開啟N+1端口。然後向服務器發送PASV命令,通知服務器自己處於被動模式。服務器收到命令後,會開放一個大於1024的端口P(端口P的範圍是可以設置的)進行監聽,然後用PORT P命令通知客戶端,自己的數據端口是P。客戶端收到命令後,會通過N+1號端口連接服務器的端口P,然後在兩個端口之間進行數據傳輸。
命令連線: 用戶端 port N –> 伺服器 port 21
資料連線: 用戶端 port N+1 –> 伺服器 port P
其中 NP 都必須大於 1023
常見問題:
被動模式就是變伺服器開隨機PORT給客戶端作為連接使用,現在的FTP SERVER軟體都有支援開範圍的PORT,還有一點是要注意如果是外部連內網,有可能回的IP會是內部網路IP造成用戶端無法連接,這個在軟體上也可以設定

2019年6月6日 星期四

拓元驗證碼辨識為例 python + tensorflow(卷積神經網路CNN) +Flask(API)

我們直接看結果吧  以下是我針對拓元驗證碼 一萬次的訓練結果 成功率99%
最後把方法透過Flask把python封裝成API可以調用.
這東西很好玩,因為可以應用的場景非常廣,想的到的複雜辨識都可以一套解決,最重要的是可以一直訓練,所以就算很複雜的驗證碼邏輯,只要餵好資料其他基本上就都可以解決
而且速度非常快,不過CNN缺點就是需要大量訓練素材,而且我這邊是訓練四碼如果是不同碼又需要重新訓練,當然可以做文字切割後再去各別辨識這樣效率成功率也會更高,下次再來玩玩GAN或許可以解決需要大量素材的問題,可能牽涉違法 程式碼就不貼了,單純練習應用.



tensorflow,python,神經網絡的相關知識我滿推薦 騰訊工程師周莫煩的youtube頻道講解得很簡單明瞭,特別這類的中文教學本來就不多,有興趣可以點下面網址看看
https://www.youtube.com/channel/UCdyjiB5H8Pu7aDTNVXTTpcg



以下也都是寫得不錯的文章
http://puremonkey2010.blogspot.com/2017/07/toolkit-keras-mnist-cnn.html
https://www.zhihu.com/question/22298352
https://medium.com/@syshen/%E5%85%A5%E9%96%80%E6%B7%B1%E5%BA%A6%E5%AD%B8%E7%BF%92-2-d694cad7d1e5

2019年5月6日 星期一

ASP.NET MVC 三層架構Three tier 實作

滿久之前有跟大家提三到層架構,回顧可以先點這裡,卻一直少了實作的部分,這範例專案其實三年前就做好了只是一直放著沒時間補上,這架構其實也算很古老了,今天就把這部分補上.

這邊的範例就是簡單的identity登入功能 透過三層架構的方式
順序從前端輸入登入  打Controller層自己建的登入WabApi方法 再到Service層驗證登入的邏輯  最後在Repository層跟DB溝通 完整降低耦合 邏輯切割 邏輯也只須關注Service層 不管在系統開發業務切割都有很大的好處.首先我們先看下面這張專案圖
當然以上不是一定的,純粹給大家一個基本三層的建構概念體驗當中的魅力
首先我們要進行分層我們需要熟悉一種技術Dependency injection(DI 依賴注入) 
Interface(https://aspnetmars.blogspot.com/2017/05/interface-c.html)透過介面的方式實作,這也都算滿老的基礎技術網路上也滿多文章的,這有時間再整理一篇,我們繼續.


首先我們需要使用先nuget我們的di套件這邊使用Unity(https://aspnetmars.blogspot.com/2017/05/unity-di.html),也不一定要用unity也有其他種大同小異
有兩種MVC跟WebAPI的版本 我這邊是兩個都載 差別就是一個是Controller用跟WebAPI用.其實也只要用WebApi,MVC版是看你們有沒要在Controller的地方注入


然後官方也有提醒記得在Global.asax加入以下這段
然後可以發現我們App_Start多了兩個檔案UnityConfig.cs跟UnityMvcActivator.cs 
我們重點放在UnityConfig.cs注入的相關參數都會在這執行,UnityMvcActivator基本上不太會動到主要功用就是程序剛執行要跑的部分


相關可以發現我依照名稱尾端名稱分別注入了Service跟Repository其實簡略點可以只注入Service
然後FormAllInterfaces自動就去找Interface完成我們的注入
然後可以發現我們多了個getInjectionMembers底下實作了LoggingInterceptionBehavior
主要功用為去攔截我們每個注入的方法,這好處是什麼.你應該也猜到了.就是可以記錄我們的log這邊我是使用了Nlog(https://aspnetmars.blogspot.com/2017/05/nlog-bug.html+ Slack再來就跟各位演示整個流程

還沒忘記我們一開始的功能吧 開始登入網站 看看這架構的魅力吧

1.首先登入這沒問題



















2.再來就是打API來到我們Controller層 可以發現我們這邊又去呼叫Service層
































3.來到Service層,這邊又去呼叫我們Repository層要資料 這邊就是可以寫我們商業邏輯的地方,可以發現我們吧一些驗證邏輯寫在這如果我們邏輯需要異動只要改這個部分也不會影響到Controller 做到業務分層,在共同開發下也更為清楚,好處可以說是非常多,特別是在東西越來越多的狀況下越能體會到這架構的好處






























4.來到Repository層 這邊就是可以去我們資料庫要資料了 像我們每一層都需要定義Model分層的話又可以讓每個階層的東西放在各自位置這也是好處之一.























5.最後在Repository > Service > Controller  當然就是登入成功啦


然後剛剛有跟各位提到LoggingInterceptionBehavior
我這邊自己寫的 基本上是長這樣  紀錄 呼叫 , 回傳 或 Exception 這邊紀錄是使用Nlog我也有寫過一篇大家可以去看看,然後我範例記錄位置我是記錄在Slack 因為那時候Slack很潮XD 

Slack就會長這樣 完整記錄有注入過的方法的資訊 紀錄格式就不一定看各位想紀錄什麼

錯誤的話就會像這樣 我在哪一層哪個方法錯誤


以上就大概是簡單的範例  
架構上要說簡單也簡單 要說繁雜就是繁雜  後續還要考慮單元測試 自動部屬 等等等  還有很多可以在說明跟優化,有任何問題可以在底下留言.