macのlocal環境にtypescriptを導入
職場が静的型付け言語使ってきた人が多いので、
その人達の学習コストの事だったり
コンパイル時にバグを発見できたりであったり
そんな事情でtypescriptを使っています。
導入の仕方の備忘録。
typescriptの導入
1. typescriptをglobal install
npm install -g typescript
2 . コードを書く
class Dog { private name: string; constructor(name: string) { this.name = name; } } const dog = new Dog('pochi');
3. typescriptからJavaScriptにコンパイルする
tsc hello.ts
こんなjsファイルが生成されます。
var Dog = /** @class */ (function () { function Dog(name) { this.name = name; } return Dog; }()); var dog = new Dog('pochi');
webpackの導入
いちいちコンパイルするの面倒くさいよね。
ファイル保存時に自動でコンパイルしてくれたらうれしい
コンパイルが終わった後にいちいちブラウザリロードするの、 面倒くさいよね。
コンパイルが終わったら自動でブラウザをリロードしてくれるとうれしい
コード量が増えたらファイル分けたいよね。
外部ファイルが読み込めるようになったらうれしい
webpackを導入しましょう。
(次回の記事)
地下アイドル「私、ぜったい売れっ子アイドルになるんだから!」で学ぶデザインパターン(Observer)〜アイドルとオタクを疎結合にしてみた〜
ある日の地下アイドル
地ア「は〜あ。今日もライブは3人しかこなかったなぁ」
地ア「きょう来てくれたのは、たっくんと、しのぶんと、ゆっきーか」
地ア「この3人、いつも来てくれるんだよねぇ。大事にしなくちゃ」
地ア「私、ぜったいに売れっ子アイドルになるんだから!」
地ア「…そろそろCD発売だから、告知しよっと」
アイドルクラス
/** アイドルクラス */ function ChikaIdle() { } ChikaIdle.prototype.noticeCdRelease = function() { /** わたし、みんなの名前も顔も覚えてるよ! */ var takkun = new Otaku('takkun'); var shinobun = new Otaku('shinobun'); var yukki = new Otaku('yukki'); /** CD買って(はあと) */ console.log('みんなだいすき!CD買ってね!'); takkun.getCd(); shinobun.getCd(); yukki.getCd(); }
アイドルによる告知
var chikaIdle = new ChikaIdle(); chikaIdle.noticeCdRelease();
オタククラス
/** オタククラス */ function Otaku(name) { this.name = name; } Otaku.prototype.getCd = function() { console.log(this.name + 'はCDをぜってーかうぜ!!'); }
告知結果
みんなだいすき!CD買ってね! takkunはCDをぜってーかうぜ!! shinobunはCDをぜってーかうぜ!! yukkiはCDをぜってーかうぜ!!
だんだん売れてきた地下アイドル
地ア「今日は10人もライブに来てくれた!!」
地ア「きょう来てくれたのは、たっくんと、しのぶんと、ゆっきーと、ちーくんと、るなくんと、、、」
地ア「ほげくんとほげくんとほげくんかぁ」
地ア「そろそろCD発売だから、また告知しよっと」
アイドルクラス
/** アイドルクラス */ function ChikaIdle() { } ChikaIdle.prototype.noticeCdRelease = function() { /** わたし、みんなの名前も顔も覚えてるよ! */ var takkun = new Otaku('takkun'); var shinobun = new Otaku('shinobun'); var yukki = new Otaku('yukki'); var chi = new Otaku('chi'); var luna = new Otaku('luna'); var hoge1 = new Otaku('hoge1'); var hoge2 = new Otaku('hoge2'); var hoge3 = new Otaku('hoge3'); var hoge4 = new Otaku('hoge4'); var hoge5 = new Otaku('hoge5'); console.log('みんなだいすき!CD買ってね!'); /** CD買って(はあと) */ takkun.getCd(); shinobun.getCd(); yukki.getCd(); chi.getCd(); luna.getCd(); hoge1.getCd(); hoge2.getCd(); hoge3.getCd(); hoge4.getCd(); hoge5.getCd(); }
アイドルによる告知
var chikaIdle = new ChikaIdle(); chikaIdle.noticeCdRelease();
メッチャ売れてきたアイドル
地ア「すごい!今日ははじめて箱(ライブハウスのこと)がいっぱいになったよ!」
地ア「200人も来てくれた!」
地ア「今日来てくれたのはたっくんと、しのぶんと、ゆっきーと、ちーくんと、るなくんと、、、」
地ア「アアアアアアアアアアアアアアアアアアアアアア!!!!!!!」
しのぶん「地下アイドルちゃん!僕の事今日から、しのぶーって読んでね!」
/** アイドルクラス */ function ChikaIdle() { } ChikaIdle.prototype.noticeCdRelease = function() { /** わたし、みんなの名前も顔も覚えてるよ! */ // var shinobun = new Otaku('shinobun'); var shinobu = new Otaku('shinobu'); // shinobun.getCd(); shinobu.getCd(); }
地ア「ア゛ア゛ア゛ア゛ア゛ア゛ア゛ア゛ア゛ア゛ア゛ア゛ア゛!!!!!!!」
どうしてこうなったのか
地下アイドルがいろいろ知りすぎです。
このままでは、
オタク達が増えるたびに地下アイドルクラスに変更が行われ、
オタク達のあだ名が変わるたびにまた、地下アイドルクラスに変更が行われます。
つまり、
地下アイドルクラスはめちゃくちゃ仕様変更に弱いクラスということになります。
その時、地下アイドルは気づいた
地ア「そうだ!」
地ア「私は別に、みんなの名前を覚えなくていいんだ!」
これがObserverパターンの始まりです(嘘)
Observerパターンで書き直す
アイドルクラス
/** アイドルクラス */ function ChikaIdle() { this.fans = []; } ChikaIdle.prototype.addFan = function(fan) { this.fans.push(fan); } ChikaIdle.prototype.noticeCdRelease = function() { console.log('みんなだいすき!CD買ってね!'); /* * アイドルはファンの名前は誰も知らない。 * 知っているのはCDを買ってくれるということだけ */ this.fans.forEach(function(fan, index, fans) { fan.getCd(); }); }
アイドルクラスから、
Otakuクラス、
Otakuの名前が全て消えました。
アイドルが知っているのは、
fanが「getCd」というメソッドを持っていることだけです。
もう、アイドルはオタクの顔も名前も思い出せません。
知っているのは、「告知をしたら、CDを買ってくれる」というただ1つだけ。。。
アイドルとオタクが非常に疎結合な、良い設計になりました。
使い方
var chikaIdle = new ChikaIdle(); var takkun = new Otaku('takkun'); var shinobun = new Otaku('shinobun'); var yukki = new Otaku('yukki'); var chi = new Otaku('chi'); var luna = new Otaku('luna'); var hoge1 = new Otaku('hoge1'); var hoge2 = new Otaku('hoge2'); var hoge3 = new Otaku('hoge3'); var hoge4 = new Otaku('hoge4'); var hoge5 = new Otaku('hoge5'); chikaIdle.addFan(takkun); chikaIdle.addFan(shinobun); chikaIdle.addFan(yukki); chikaIdle.addFan(chi); chikaIdle.addFan(luna); chikaIdle.addFan(hoge1); chikaIdle.addFan(hoge2); chikaIdle.addFan(hoge3); chikaIdle.addFan(hoge4); chikaIdle.addFan(hoge5); chikaIdle.noticeCdRelease();
さらなるメリット
アイドルは、CDを買ってくれる人ならだれでも通知することが出来ます。
/** 一般ピーポークラス */ function IppanPeople(name) { this.name = name; } IppanPeople.prototype.getCd = function() { console.log(this.name + 'はちょっと興味があるからCDかうよ'); }
getCdメソッドを持つクラスをまとめて扱うことが出来ます。
疎結合にしたことにより、ポリモーフィズムも使えるようになりました。
まとめ1
Observerパターンは、通知する側とされる側を疎結合にする。
まとめ2
アイドルとオタクを疎結合にすると、
アイドルはオタクの顔も名前も覚えなくなり、
知っているのは「告知をしたら、CDを買ってくれる」というただ1つだけという
夢も希望もなくなる感じになる。
【JavaScript】画像をdrag and dropしてサムネイルを表示する〜DragEvent, DataTransfer, File, FileReaderオブジェクトについて〜
こういうのがやりたかった
手順
簡単に言うと、
DragEventからDataTransferを取得
DataTransferからFileを取得
FileをFileReaderで読み込み、サムネイルとして表示
という手順になります。
1. dropエリアの準備
1-1. まずはdropエリアを作成する
imgは後でサムネイルを表示する際に使います。
<div id='droparea'> </div> <img src='' id='thumb'>
#droparea { width: 200px; height: 100px; border: 3px dotted #ccc; }
1-2. dropエリアにイベントリスナを登録
const droparea = document.getElementById('droparea'); droparea.addEventListener('drop', function(evt) { console.log('dropしたよ'); /** 以下、drop後の処理 */ }, true);
この中にdrop後の処理を書き込んでいきます。
2. dragしたファイル(Fileオブジェクト)を受け取る
dropしたファイルを取得します。
まず、dropイベントの中身を見てみましょう。
console.log(evt);
DragEventというオブジェクトのようです。
今回用があるのは、このオブジェクトが持つ
DataTransferというオブジェクトです。
console.log(evt.dataTransfer);
DataTransferオブジェクトがもつfilesというプロパティから、
ドラッグされたFileオブジェクトにアクセスすることが出来ます。
/** 全件取得 */ console.log(evt.dataTransfer.files); /** 1件取得 */ console.log(evt.dataTransfer.files[0]);
複数件まとめて扱うこともできそうですね。
3. 取得したFileオブジェクトを、FileReaderで読み込む
ソースコード
droparea.addEventListener('drop', function(evt) { // ファイルオブジェクトの取得 const file = evt.dataTransfer.files[0]; // FileReaderの生成 const reader = new FileReader(); reader.onload = function() { // ファイルを読み込んだ後の処理 console.log(reader.result); // サムネイルとして表示 const thumb = document.getElementById('thumb'); thumb.src = reader.result; }; // ファイルの読み込み reader.readAsDataURL(file); // ブラウザのデフォルト挙動を抑制 evt.preventDefault(); }, true);
FileReaderの解説
html5から、
FileReaderというローカルファイルを読み込めるAPIが使えるようになりました。
FileReaderが扱えるのはFileオブジェクト(またはBlobオブジェクト)です。
reader.onload = function() { // ファイルを読み込んだ後の処理 // reader.resultでファイル内容にアクセスできる };
としてファイルを読み込んだ後の処理を記載します。
読み込んだ結果は、
reader.resultでアクセスできます。
reader.readAsDataURL(file);
としてファイルオブジェクトを読み込みます。
完成したソースコード
const droparea = document.getElementById('droparea'); // dropイベントのリスナーを設定 droparea.addEventListener('drop', function(evt) { // Fileオブジェクトの取得 const file = evt.dataTransfer.files[0]; // FileReader生成 const reader = new FileReader(); // ファイルを読み込んだ後の処理 reader.onload = function() { // サムネイルとして表示 const thumb = document.getElementById('thumb'); thumb.src = reader.result; }; // ファイルの読み込み reader.readAsDataURL(file); evt.preventDefault(); }, true);
bashで特定の文字列を含むファイルの名前を、一括置換する
bashである文字列を含むファイルについて、一括置換したかった
カレントディレクトリにあるファイルのうち、
無題を含むものをmudaiに変える、みたいなことがしたかった。
結論
解説
まず、以下のようにファイルを準備します。
$ touch hogeA hogeB fugaC
これらのファイルのうち、以下の2つのファイル名を
hogeA -> ho:)geA hogeB -> ho:)geB
と変更することにします。
for文
こう書けば、カレントディレクトリのファイルについて
ループ処理をすることが出来ます。
# run.sh for file in * do echo ${file} done
$ sh run.sh fugaC hogeA hogeB
sed
新しいファイル名を生成する際、正規表現を使うことがあります。
そのときはこのsedを使いましょう。
以下のように使うことが出来ます。
$ echo hogeA | sed -E 's/(ho)(ge)/\1:)\2/g' ho:)geA
-E オプション
正規表現が使えます。
's/(ho)(ge)/\1:)\2/g' について
ho, geという文字をかっこでくくることにより、キャプチャを撮っています。
そして、\1, \2で再度アクセスしてます。
\1, \2の間にhappy simbolをいれてます。
mv
forとsedを組み合わせて、
sedで新しいファイル名を生成しつつ、
mvでその新しいファイル名に変更していきます。
for file in * do after_file=`echo ${file} | sed -E 's/(ho)(ge)/\1:)\2/g'` mv -i "${file}" "${after_file}" done
まとめ
sedコマンド、とても便利。
とくにキャプチャを取り始めるとその便利さに驚く。
今回、xargsなどを用いるともっと簡単にかけるかもしれないが、
可読性のためにココらへんでとどめておくことにした。
またチャレンジしたい。
bashは最強のポータビリティ言語。
MySQLにて、特定のカラムに日本語が含まれているかどうかを抽出
あるカラムに日本語が含まれていることを検出したい
結論
あるカラムに対して、
LENGTH
CHARACTER_LENGTH
の値が異なることを利用する。
SQLの例
SELECT * FROM table_name WHERE LENGTH(column_name) != CHARACTER_LENGTH(column_name);
解説
LENGTHは「バイト」数
CHAR_LENGTHは「文字」数
なるほどねぇ。
sshのセキュリティ設定で、なぜポートを22から変えるとよいのか〜サーバとポートと/etc/ssh/sshd_configと〜
サーバのsshdプロセスに対して、1日900回以上の不正アクセスがあった
詳しくはこの記事。
対応方法の一つ
sshdがlistenしているポートを22→10022に変える。
そもそもポートとは
サーバでは、いろんなアプリケーションが動いている
nginx、sshd、mysqld、telnetdなど、
いろんなアプリケーションが動いている。
サーバを利用するときは、このアプリケーションと通信することになる。
nginxアプリケーションと通信したい時
webサイトを見る場合は、この場合nginxと通信することになる。
ipアドレスによって、サーバにはたどり着くが、
これだけではnginxと通信することが出来ない。
「nginxというアプリケーションと通信したいです、とお願いすればよいのでは?」
と思うかもしれないが、ユーザ側からはサーバの中が見れないので、
webサーバがnginxなのかapacheなのか、
はたまたIISなのかはわからない。
実際は
実際、アプリケーションは「ポート」という部屋のようなものの中にいる。
(正確にはポートをlistenしている、というがわかりやすさのため部屋にいる、とした)
サーバにはポートという部屋がある
サーバには、
1〜65535の番号が振られた、ポートという部屋を持っている。
それぞれの部屋にはアプリケーションが住んでいる
上記のように、22番にはsshd、80番にはnginx、、、というように、
部屋の中にはアプリケーションが住んでいる。
通信するときは部屋番号を指定して通信している
httpアクセスが送られる時、
サーバのipアドレス: ポート番号
という形で送られている。
これで、通信したいアプリケーションと通信ができる。
これは、マンションのある部屋に郵便物をおくるイメージと似ている。
通信は、コンピュータからコンピュータではなく、
ポートからポート、と覚えておくと良い。
アプリケーションには定められた部屋番号がある
22番にはsshd、80番にはnginxというように、
色んな人が使う可能性が高いアプリケーションは、予め決められた部屋番号がある。
これにより、
「サーバの中でどんなアプリケーションが動いているかは分かんないけど、
80番ポートにアクセスしたらwebサイトみれるんじゃね?」
くらいの知識でwebサービスが使える。
使う側は、ipとポートさえわかっていればよい。
「アプリケーションには定められた部屋番号がある」が逆手に取られることがある
ハッカー「22番ポートにはsshdがすんでるハズだから、鬼ノックしてやろ!!!!」
と思った人がいたからである。
対策としては、sshdのお引っ越し
こんな感じでsshdを10022番に引越ししてもらう。
そうすると、
ハッカーは空部屋を鬼ノックし続けるという悲しいことになる。
まとめ
みんなが使うアプリケーションは、予め定められたポート番号に住まわせる
他の人に使ってほしくないアプリケーションは、自分だけが知っていればよいポート番号に住まわせる
とすればよいはず。
今回ポート周りの知識が整理されたので良かった。
user「PPAP」からの不正アクセスを検出しました〜sshdのログ(/var/log/secure)から不正ユーザの名前を取り出し、セキュアじゃないユーザ名について考えてみた〜
存在しないユーザからのアクセスがあった
Failed password for invalid user *** from ...
これは、
「linux上で登録されていないユーザ *** からのアクセスがありました」
ということ。
今回、攻撃者がどんな名前を用いてアクセスしてくるのか
探ってみる。
手順
ログからinvalid userだけ取り出す
awkを使おう。
cat /var/log/secure | awk -F' ' '/Invalid/{print$ 8}' | sort | uniq
0 1 1111 111111 123123 1234 12345 123456 123456789 12345qwert 1234qwer 12qwaszx 1q2w3e4r 1q2w3e4r5t 1qaz2wsx 1qaz@WSX
出てきた。
ついでに集計もしてみる。
cat secure | awk -F' ' '/Invalid/{print$ 8}' | awk '{count[$0]++}END{for(i in count)print count[i], i}' | sort -nr
15 minecraft 14 www 14 user1 14 steam 14 server 14 debian
出てきた。
不正アクセス者ランキング
5位
centos: 1023件
なお、ubuntuは63件でした。
単純にサーバとしてよく使われているから・・・?
それともnmapでOSがわかるから・・・?
(自分のサーバにnmapしてみましたが、unixという情報しか出てきませんでした)
4位
guest: 1096件
ありがち。
3位
user: 1126件
これもありがち。
2位
test: 1178件
これすごくありがち。
1位
admin: 1300件
これやったことあるな。
これからは安易に使わないようにしよう。。。
なお、6位から20位はこんな感じ。
順位 | 回数/month | ユーザ名 |
---|---|---|
6 | 112 | oracle |
7 | 98 | nagios |
8 | 90 | git |
9 | 63 | ubuntu |
10 | 54 | hadoop |
11 | 52 | pi |
12 | 46 | ftpuser |
13 | 43 | teamspeak |
14 | 41 | zabbix |
15 | 41 | vagrant |
16 | 37 | vnc |
17 | 37 | ubnt |
18 | 35 | support |
19 | 31 | ts |
20 | 30 | ts3 |
上位5位が圧倒的すぎる。
分類
数字 + ランダムアルファベット系
0 1 1111 111111 123123 1234 12345 123456 123456789
管理者系
ADMIN Admin123 Administrator admin admin1 admin123 admin2 administrador administrator
有名人系
adam eva
特定のクラウドサービスを狙ったもの
ec2-user
人名系
外国人
alberto aleksei alessandro alex alfresco ali alice alicia allison ally alma
日本人
dai daichi daiki daisuke hideaki hideki hideo hikaru hiro hiroaki hiroki hiroshi hiroyuki
ソフトウェア名
nagios git hadoop nginx nodejs redis vagrant
デプロイ用ユーザを狙ったと思われる系
deploy1 deploy123 deploy1234 deploy12345 deploy123456 deploy2 deploy3 deploy4 deploy5
明らかに悪意がある系
exploit
番外編
PPAP
これで日本人だと特定できたかなと思ったのもつかの間、
これ世界的に流行ったやつだからどこからアクセスされてもおかしくねえぞ。
まとめ
user名で避けるべき名前
- admin
- test
- user
- guest
- centos
よく使われているからこそ、狙われる。
感想
割と日本人の名前が多い。
どこまで考えて攻撃しているのかはしらないけど、
安易に自分の名前をユーザ名にするのは良くないと感じた。
せめて記号や数値と織り交ぜたい。
また、ソフトウェア名も良くない。