yuw27b’s blog

技術メモと雑記

CSSの擬似要素を使ったあれこれ

この記事は、今年お世話になったCSS Advent Calendar 2016の20日目です。

擬似要素自体は特に今年どうこうなった仕様ではありませんが、大変お世話になりました。

擬似要素をよく使う場面

自分的頻出パターンとしてはこんな感じです:

counterと組み合わせたリスト

See the Pen List with counter by Yu Watanabe (@yuw27b) on CodePen.


パンくずリスト

See the Pen Breadcrumb by Yu Watanabe (@yuw27b) on CodePen.


三角形

See the Pen Css triangle by Yu Watanabe (@yuw27b) on CodePen.


上下中央揃え

See the Pen Align middle by Yu Watanabe (@yuw27b) on CodePen.



「:」なの?「::」なの?

擬似要素は、CSS 2.1の仕様ではコロン1つの「:before」「:after」でしたが、CSS3ではコロン2つになりました。
CSS3はモダンブラウザとIE9以上が対応しているので、IE8のサポートが切れた今年(2016年)からは「::before」「::after」を使用すれば良いと思います。
とはいえ、IE8でも・・・という案件がなぜかまだあったり、各ブラウザも後方互換のため「:before」でもきちんと解釈してくれるし、という状況で、結局コロン1つで書くことも多かった1年でした。

Safariのバグに出会った

擬似要素とcurrentColorを組み合わせたときに発生します。Safari9で修正されたようです。
親要素のcurrentColorがうまく継承されない、というものです。
css - currentColor seems to get "stuck" in Safari - Stack Overflow
Bug 133420 – `currentColor` computes to the same colour on all elements, even if 'color' is inherited differently

ターゲットブラウザにSafari8が含まれそうなら、擬似要素内でのcurrentColorの使用は避けたほうが良いと思います。


来年の抱負は、Flexible Boxにお世話になりたい!です。
未だにIE9〜対応の案件もあるので難しそうですが、スマートフォン専用サイトならそろそろ使えそうですね。

SVGをReact.js/JSXで使う

この記事はSVG Advent Calendar 2016の19日目です。
去年に引き続きグラフを描いての参加です。


React × SVG

React.jsなプロジェクトでSVGを描画したときのメモです。
React.jsでは、JSXという記法でJavaScriptコード内にHTMLタグを記述していきますが、SVGタグも記述できます。
React.jsの特徴は仮想DOMですが、SVGSVG DOMというインターフェースを持っているので、HTML同様にサポートされているのですね。

Attributeはキャメルケースを基本に

まずタグ内の属性名については、基本的にハイフンがキャメルケースになります。ネームスペースを表すコロンも同様です。

通常のSVG

<svg version="1.1" width="200" height="200"  xmlns="http://www.w3.org/2000/svg">
  <rect width="100" height="100" x="10" y="10" fill="#900" stroke="#666" stroke-width="5" />
  <a xlink:href="http://blog.hatena.ne.jp/yuw27b/"> 
    <text x="20" y="40" fill="#FFF" text-anchor="start" font-size="20">Text</text>
  </a>
</svg>


JSX内のSVG

<svg version="1.1" width="200" height="200"  xmlns="http://www.w3.org/2000/svg">
  <rect width="100" height="100" x="10" y="10" fill="#900" stroke="#666" strokeWidth="5" />
  <a xlinkHref="http://blog.hatena.ne.jp/yuw27b/"> 
    <text x="20" y="40" fill="#FFF" textAnchor="start" fontSize="20">Text</text>
  </a>
</svg>

JSXはあくまでもJavaScriptの中なので、ハイフンやコロンが使えないからだと思われます。
サポートされている属性名のリストは以下の公式ページの最下部にあります。
https://facebook.github.io/react/docs/dom-elements.html

上記のリストには含まれていないのですが(HTMLと同じだから?)、「class」も「className」になります。

ブラウザにReactのDeveloper Toolsを入れておけば、使用できない属性名についてはコンソールに警告が出るので、まずはそのままSVGを書いてしまって、エラーが出たら都度修正、でもいいと思います。

または、自動的に変換してくれるnpmパッケージと、それを元にしたオンラインサービスもあります。
svg-to-jsx
SVG to JSX Online Converter
ただし、若干バグがあるような感じなので、全部お任せはちょっと難しいかもしれません。


簡単なグラフ(もどき)

プルダウンからソート順を選択すると再描画する棒グラフっぽいSVGを書いてみました。

See the Pen xRMYzQ by Yu Watanabe (@yuw27b) on CodePen.

※仮想DOMなので、再描画の動作も軽いのでは、と思いますが、もっと大規模なものを作らないと差が分からないですね・・・。



SVGのグラフライブラリ×Reactも試しているのですが、それはまた別の記事にしたいと思います。

RESTful APIで長い検索クエリを扱う

Webアプリケーション用のRESTfulっぽいAPI*1を作っていて、複雑な検索クエリを受け取る必要が出てきたときのメモです。

悩み

RESTfulの原則に従うと、検索クエリを投げて結果の一覧を取得する、というリクエストは、
「リソースの取得」なので、GETを使うべきです。
/api/entries/?q=xxx とか
/api/entries/?created=20161129&status=active
みたいなURIになりますよね。

こんな感じで検索キーワードが1つ2つなら良かったのですが、
今回作っていたのが限定されたユーザー向けのアプリで、多少検索に時間がかかってもいいから複雑なクエリを投げたい、というのが要件でした。
こんなふうに検索条件を組み合わせられるようになっていました。
f:id:yuw27b:20161202233544p:plain

問題は、
①検索条件がいくつ来るか分からない
②「q=xxx」の形式では「equals」「not equals」のところが渡せない
という点です。

まず①で、GETのクエリパラメータが長くなる==URIが長くなるので、ブラウザ〜ファイアウォール〜サーバまでのどこかで制限される可能性がありそうです。
さすがにそこまで長くは・・・とは思うものの、理論上は無制限に検索ワードを指定できるので、「たぶん大丈夫」ではやっぱりダメですよね。

②も、そのままJSONを文字列にエンコードするとか、「?key__equals__value&…」とか考えるものの、やはりクエリが長くなってきます。
そもそもフロント側でクエリを文字列に変換し、それをサーバ側でまたパースする、というのがあまりイケてないような気もします。

POST使っちゃダメ?

GETが厳しいとなるとPOSTで、と思うものの、
RESTful APIでは、POSTはリソースの新規作成なので、検索クエリを投げて良いのだろうか、と悩むし、
そもそも「/api/entries/」に対するPOSTリクエストは、当然"entry"の新規作成用に使ってしまっています。

解決策:検索用エンドポイントを用意してPOSTする

「/api/entries/search」というURIにPOSTでJSONを投げることにしました。
参考にしたのはこれ↓です。
rest - Design RESTful query API with a long list of query parameters - Stack Overflow

レスポンスのステータスは迷いましたが「201 Created」を返しています。
上のリンク先にもあるように「検索結果というリソースを生成している」と捉えています。まあ200でも良さそうですが。

新たな悩み

検索条件が設定されているかどうかをフロント側で判別して、あれば「POST /api/entries/search」、なければ「GET /api/entries」にリクエストをかけているのですけど、
もう全部POSTに統一のほうがいいのだろうか・・・?


ひとまず、そこまでREST原理主義でなくてもいいかと思いこんな感じにしましたが、何かもっといい方法があれば知りたいです!

*1:最近、業務で作っているWebアプリケーション専用のAPIなので、API単体で一般に公開するような性質のものではないです。Ruby(Sinatra)+MySQLで、フロントエンドからのリクエストにJSONを返しています。

Content Security Policyの今後(2016年10月現在)

先月の勉強会での発表の内容と少し重なりますが、CSPの各レベルの仕様とブラウザ対応状況などのまとめです。

Content Security Policyとは

CSP (Content Security Policy) - Web セキュリティ | MDN

ざっくりですが、WebサイトからXSSの危険を取り除くための仕様です。
現在は、サーバ側でHTTPヘッダーにCSPを追加することで利用できます。

きちんと指定すればWebサイトの安全性が高まるということで、私もJavaScriptがいろいろしているサイトには導入してみているのですが、まだまだ仕様が変わっていきそうな雰囲気ですね・・・。


Content Security Policy Level1

W3Cの公式ページ

Content Security Policy 1.0
※最終バージョンの内容はここにある↓
https://www.w3.org/TR/2012/CR-CSP-20121115/

ブラウザ対応状況

Can I use... Support tables for HTML5, CSS3, etc

  • 長い間「勧告候補」だったが、Level2に引き継がれてこちらは今後の更新はないようです。
  • IE10以降とモダンブラウザが対応。※ただしIEは「X-Content-Security-Policy」
主な機能
  • 「default-src」「script-src」「style-src」等のディレクティブに、コンテンツの読み込みを許可するドメインを指定できる
  • inlineでの実行を許可するかどうかを指定できる
  • script-src(JavaScript)に関しては、evalの実行を許可するかどうかを指定できる
  • レポートの機能


Content Security Policy Level2

W3Cの公式ページ

Content Security Policy Level 2
2016年10月現在勧告候補

ブラウザ対応状況

Can I use... Support tables for HTML5, CSS3, etc


Content Security Policy Level3

W3Cの公式ページ

Content Security Policy Level 3

  • Working draftの段階なので、ブラウザ実装等はこれからと思われる。
  • fetchやService Workersなどの、新しい(?)仕様への対応
  • strict-dynamic他、いくつかのディレクティブの追加

いろいろと追加されているようですが、草案段階なのでまだ変わるかもしれないですね。


本当に安全なのか問題

Googleのエンジニアによる論文

発表のスライドでも触れましたが、CSP Is Dead, Long Live CSP! On the Insecurity of Whitelists and the Future of Content Security Policy という論文が発表されています。
これによれば、現在のCSPではXSSの危険を完全に取り除けているケースはほとんどないそうです。
特にホワイトリスト経由の攻撃が可能である場合が多い、と指摘されているのですが、
そうなると外部ドメインからJavaScriptを読み込む場合は、CSP(Level 1)ではXSSを防げないことになります。

論文中ではそこで、CSP Level2および3で実装予定のnonceとstrict-dynamicが有効だ、と述べられています。
が、CSPの実装を待てず(?)に、XSS-Protectionヘッダという新しい仕様の提案も出ているようです。
こちらが詳しいです:
XSSを防ぐ新しいXSS-Protectionヘッダ - あすのかぜ

使う側としては、仕様の混在はできれば避けてほしいところですが、今後どうなるのでしょうか。


nonceによるホワイトリスト

※CSP Level 2における「nonce」についてです。XSS-Protectionのnonceはまた別の仕様です。

例えば、https://example.comから、JavaScriptファイルを読み込みたい、とします。
Level 1では以下のようにCSPを記述していました。

Content-Security-Policy: default-src 'self';
script-src 'self' https://example.com

Level 2では、上記に加えてnonceを利用した記述ができるようになります。

Content-Security-Policy: default-src 'self';
script-src 'self' 'nonce-Nc3n83cnSAd3wc3Sasdfn939hc3'

HTML側でexample.comJavaScriptファイルを読み込むときには、

<script src="https://example.com/lib.js" nonce="Nc3n83cnSAd3wc3Sasdfn939hc3"></script>

のようにすれば読み込むことができます。

どちらもホワイトリストの指定ですが、nonceを使用するほうが安全性が高い、と前述の論文でも述べられています。
また、JavaScriptだけでなく、例えばCSSを外部から読み込む場合も、同様にして使用できます。



hashによるホワイトリスト

こちらはなかなか豪快(?)な仕様です。
インラインスクリプトのコードを暗号化したものをあらかじめCSPに記述しておくと、そのコードは実行可能、というものです。
なので、CSPのほうには暗号を記述します:

Content-Security-Policy: script-src 'sha512-YWIzOWNiNzJjNDRlYzc4MTgwMDhmZ..............'

例として考え付くのは、Google Analyticsのコードを暗号化したものを指定しておき、
HTML側ではいつもの(?)var _gaq = 〜のようなAnalyticsのコードを貼り付ける、という場合でしょうか。

※CSPではデフォルトでinline-scriptを許可しておらず、また許可してしまうと安全性は下がるので、不許可が好ましいのですが、
そうするとGoogle Analyticsのコードをわざわざ個別のファイルにしてのように読み込む必要がありました。
このhashを使えば外部ファイルにする必要はなくなります。


strict-dynamicとは

JavaScriptを対象とした仕様です。
こちらはLevel 3からの仕様なので、今後変わるかもしれませんが、2016年10月現在の仕様書によれば以下のようなものです。
仕様書の例そのままですが、

Content-Security-Policy: script-src 'nonce-abcdefg' 'strict-dynamic'

のようにCSPを記述し、HTMLでは以下のようにJavaScriptを読み込むとします。(nonceが一致しているので読み込まれます!)

<script src="https://cdn.example.com/script.js" nonce="abcdefg" ></script>

さらに、
https://cdn.example.com/script.js」内に以下のようなコードがあるとします。

document.write('<scr' + 'ipt src="/sadness.js"></scr' + 'ipt>');

このとき、「'strict-dynamic'」があると、この「sadness.js」は読み込まれません。
(逆に考えると、CSP Level2までは読み込めてしまうということですよね・・・だから安全でない、と言われるのでしょうか。)

ただし、

var s = document.createElement('script');
s.src = 'https://othercdn.not-example.net/dependency.js';
document.head.appendChild('s');

のような記述の場合は読み込めるそうです。



おわりに

仕様書やら論文やら、それなりにまじめに読んだつもりですが、そこまで英語に自信があるわけでもなく、おかしな解釈をしている点があるかもしれません。
何かお気付きの点があればコメントいただければ幸いです。

NDS第49回勉強会に行ってきたよ

少々日が経ってしまいましたが、NDS(長岡IT開発者勉強会)第49回勉強会に行ってきました。
今回のテーマは「セキュリティ」ということでしたが、貴重なお話がたくさん聞けました。
めずらしく(?)メモを取りながら聞いていたので、感想など書き残しておこうと思います。
そしてそんなところに紛れて発表もしてきたので、スライドも貼っておきます。

情報セキュリティ研修応用編ダイジェスト (30min) hiro_ishibashiさん

サイバー攻撃の歴史から!意外と通史で見ることはなかったので、新鮮な視点。
標的型攻撃
FireEye
ITストーキング
gmailはexeが送れないらしい。exe.zipも検知されるらしい。
ファイル共有サービスを使う
従業員より役員の方が標的型メールを開封しやすい
標的型攻撃は、社内で1人でも開封したら意味がない。10人が1人になっても同じこと。
→訓練は開封させない訓練ではなく、開封後の対策を訓練すべき。
ルールと運用の不整合。セキュリティといえども経営レベルの問題。
TCP/IPは善意を前提とした仕様
CSIRTと消防署、インシデントカード
未来には119番みたいな番号ができたりする・・・?
メール・FAX禁止の金融機関。まあ金融機関は仕方ない気もする。

Webサイト改ざんの事例紹介について (15min) nomeshi さん

事例というので汎用的(?)事例かと思ったら、知人の例だった。具体的でありがたい!
FFFTPで接続すると知らないファイルが・・・というのは、実は大昔に身に覚えがある。大事には至らなかったけど。)
Web diary professionalの脆弱性とのこと。まあ、WordPressにもあったし・・・。
Webサイトの放置はなんであれ危険ですよね。
ルワンダgoogle。あるのかgoogle・・・。
偽のショッピングサイトに飛ばされるようなので、クレジットカードの番号を盗んだりするんだろうか。
google search consoleっぽいファイルもウイルスらしい。sitemap.xmlも。

Content Security PolicyとWebサービスのセキュリティ対策 (15min)

自分の発表です。
スライドはこちらに

結局パスワードってどうしたらいいの? (30min) occhie3さん

情報モラルの布教大事!素晴らしいお仕事だと思う。
今の学校ではそういう講習があるのか。
情報セキュリティワークショップ
パスワードリスト攻撃ってやっぱりなくならないのね。不正ログインもすごく多い。
うちのサービスも簡単なパスワードは撥ねるべきなのか・・・。うーん、無理そうw
同一ホストからの連続ログイン試行を拒否、これも実装すべきか。
sha-1はもうダメ。sha-2とsalt化でDBに入れるべき。ハッシュ化を1000回くらい繰り返すのも有効。

セキュリティ (30min) MasatoMatsuokaさん

INTERPOLにサイバー警察ができたとのこと。ニューロマンサー)の時代が来るのか(違)。
情報セキュリティ>サイバーセキュリティ(情報のほうは紙とかも入るからくくりが大きい)
アリアンツの格付け(?)によると、サイバーの脅威は経営リスクの第3位。
いまは変電設備もデジタルなので、攻撃できるとのこと→サイバーでフィジカルを壊すことができる。
銀行口座のお金を移された例もある。
ネットで繋がってないところも→例えば工場の内部に入る従業員や保守業者のパソコンから侵入する。
工場に(保守に)行く人がアクセスするようなページにマルウエアを仕込む。JARファイルとかドライバとか。
一般的なハッカーより、発電所なら発電所に詳しい人の方が早くハッキングできてしまう。
システムが動かなくなるとしてもパッチを当てろ!
2016年の予想:APTはメモリ等に移行(ファイルではない)、ランサム継続、モバイル、IoT
Android Pay, Apple Pay、株取引などが狙われる。iPhone7気をつけろ、とのこと。少額で広範囲から詐取する見込みとのこと。
・個人としては、とにかく踏み台にされないように。ウイルスソフト絶対。パスワードは複雑に。
とにかく自分のアカウントを守れば世界は平和に。他人に迷惑をかけない!
ご自身はMacカスペルスキーファイアウォールLittle Snitch)を使っていらっしゃるそう。

emailを安全に使うための心がけ (15min) civicさん

メール開くだけなら大丈夫そう。確かに。添付ファイルを開くのがダメなんですよね。
メールのFromはあてにならない。つまりオレオレ詐欺
メール内のリンクは使わない。
メールソフトやOSの警告は無視しない。基本だけど大事ですね。
メールの添付ファイルはOSはガードしていない。例えばzipだとセキュリティソフトも処理できないケースがある。
添付ファイルそのものが危険。
Adobe,microsoft,Javaは最新に。MacJava危険。
一般人の場合は、添付ファイルを開く前にウイルスチェックすればほぼ大丈夫。
IPAのバージョンチェッカー
zipやexcelのパスワードを別メールで送るのは全く意味がない。日本だけ。
.exeを暗号化して.zipにするとgmailでも送れるらしい。
MMSにもウイルス乗せられる。

C#関連で何か (15min) alightさん

MSのMVPの方。
Azure Active Directory B2Cについて
パスワードの変更対応サービス自作するの、確かに面倒だった。し、自前のユーザー管理システムはセキュリティに不安が残るのも事実。
なので、認証の外部サービスいいなあ。
(うちのサービスクラウドにできない、というか月額みたいな契約ができないから無理、というつらみ。。。)
Azureのコンソール画面けっこうかっこいい。
APIとして使えるの良さそう。
契約できそうなプロジェクトがあったらぜひ試してみたい。

SG受験のすすめ (LT 5min) ゑぬぽいさん

管理部門の人向けの試験、というの良さそう。「マネジメント」が入っているのはそういうことなのか。
全国的にリテラシーが上がるといいですね。
合格率すごい高い。のは最初の試験だったから?
今のところIT関連の資格とは無縁で来てしまっているので、何か勉強するのも良いかも、と思ったり。



以上、ちょっと自分用メモの側面が大きいですが、大変有意義な会でした。
ぜひまた長岡まで足を伸ばしたいと思います。
ありがとうございました!