SlideShare a Scribd company logo
1 of 42
Download to read offline
はてなブックマークにおけるアクセス制御
半環構造に基づくモデル化
伊奈 林太郎
id:tarao @oarat
2015-11-24
@ WebDB Forum 2015
◮ 国内最大のソーシャルブックマークサービス
◮ 国内最大のソーシャルブックマークサービス
◮ Scala でいちから作り直すプロジェクトが進行中
DISCLAIMER
◮ 内容は開発中のもの
◮ 実際のリリース時には変更の可能性あり
◮ 最終的にどうなったか公表するかどうか未定
話すこと
◮ B!のアクセス制御はかなり複雑
◮ さまざまな画面/設定
◮ AND/OR 条件
◮ 統一的なモデル化でバグの作り込みを避けたい
◮ モデルの数学的な正しさ
◮ コード上で一貫して扱うしくみ
◮ 効率化したい
◮ DB クエリ等で権限に応じたフィルタリング
アクセス制御のモデル化
単純なアクセス制御
◮ 非公開ユーザの設定
◮ ブックマークが他人からは見えなくなる
◮ 本人にはもちろん見える
単純なアクセス制御
◮ 非公開ユーザの設定
◮ ブックマークが他人からは見えなくなる
◮ 本人にはもちろん見える
コード
if (bookmark.owner == visitor)
Some(bookmark)
else None
少し複雑なアクセス制御
◮ 閲覧許可ユーザの設定
◮ 本人に加えて許可された人にも見える
少し複雑なアクセス制御
◮ 閲覧許可ユーザの設定
◮ 本人に加えて許可された人にも見える
愚直なコード
if (bookmark.owner == visitor ||
bookmark.owner.allowedUsers.contains(visitor))
Some(bookmark)
else None
少し複雑なアクセス制御
◮ 閲覧許可ユーザの設定
◮ 本人に加えて許可された人にも見える
愚直なコード
if (bookmark.owner == visitor ||
bookmark.owner.allowedUsers.contains(visitor))
Some(bookmark)
else None
◮ 少し複雑
◮ そのうちチェックしわすれが発生
少し複雑なアクセス制御
◮ 閲覧許可ユーザの設定
◮ 本人に加えて許可された人にも見える
愚直なコード
if (bookmark.owner == visitor ||
bookmark.owner.allowedUsers.contains(visitor))
Some(bookmark)
else None
◮ 少し複雑
◮ そのうちチェックしわすれが発生
なにか統一的に扱いたい
アクセス制御のモデル
属性 A の羃で表現
要求 r ∈ P(A) = requestOf(viewer)
許可 p ∈ P(A) = permissionOf(target)
確認 p allows r ⇔ p ∩ r = ∅
アクセス制御のモデル
属性 A の羃で表現
要求 r ∈ P(A) = requestOf(viewer)
許可 p ∈ P(A) = permissionOf(target)
確認 p allows r ⇔ p ∩ r = ∅
例
ユーザ 閲覧許可 要求 許可
u1 なし {u1} {u1}
u2 u1, u3 {u2} {u1, u2, u3}
u3 u2 {u3} {u2, u3}
permissionOf(u1) allows requestOf(u2) = false
permissionOf(u2) allows requestOf(u3) = true
permissionOf(u3) allows requestOf(u1) = false
アクセス制御のモデル
属性 A の羃で表現
要求 r ∈ P(A) = requestOf(viewer)
許可 p ∈ P(A) = permissionOf(target)
確認 p allows r ⇔ p ∩ r = ∅
コードによる表現
val r = requestOf(visitor)
val p = permissionOf(bookmark.owner)
if (p allows r) Some(bookmark)
else None
◮ オブジェクトから属性集合へのマッピング
(permissionOf, requestOf)
◮ オブジェクト型ごとの一貫したメンテが可能
アクセス制御のモデル
r {a, b, c}
r {a, b} {a, c} {b, c}
r {a} {b} {c}
p {a} {b} {c}
p {a, b} {a, c} {b, c}
p {a, b, c}
◮ Lattice-based access control (LBAC)
◮ 権限の強弱関係が束をなす
もっと複雑なアクセス制御
◮ 個別のブックマークを非公開にできる
◮ 閲覧許可ユーザにも見えない
もっと複雑なアクセス制御
◮ 個別のブックマークを非公開にできる
◮ 閲覧許可ユーザにも見えない
愚直なコード
if (bookmark.owner == visitor ||
(bookmark.owner.allowedUsers.contains(visitor) &&
bookmark.isPublic))
Some(bookmark)
else None
もっと複雑なアクセス制御
◮ 個別のブックマークを非公開にできる
◮ 閲覧許可ユーザにも見えない
愚直なコード
if (bookmark.owner == visitor ||
(bookmark.owner.allowedUsers.contains(visitor) &&
bookmark.isPublic))
Some(bookmark)
else None
◮ LBAC では表現不能
もっと複雑なアクセス制御
◮ 個別のブックマークを非公開にできる
◮ 閲覧許可ユーザにも見えない
愚直なコード
if (bookmark.owner == visitor ||
(bookmark.owner.allowedUsers.contains(visitor) &&
bookmark.isPublic))
Some(bookmark)
else None
◮ LBAC では表現不能
(※実際はあと 5 段階くらい複雑)
もっと複雑なアクセス制御
◮ 個別のブックマークを非公開にできる
◮ 閲覧許可ユーザにも見えない
愚直なコード
if (bookmark.owner == visitor ||
(bookmark.owner.allowedUsers.contains(visitor) &&
bookmark.isPublic))
Some(bookmark)
else None
◮ LBAC では表現不能
(※実際はあと 5 段階くらい複雑)
もっとよいモデル化が必要
アクセス制御のよいモデル
属性 A の半環で許可を表現
要求 r ∈ P(A) = requestOf(viewer)
許可 p ∈ P(P(A)) = permissionOf(target)
確認 p allows r ⇔ ∃q ∈ p. q ⊆ r
半環 P(P(A)), ⊕, ⊗, ∅, {∅}
◮ p1 ⊕ p2 = p1 ∪ p2
◮ p1 ⊗ p2 = p1 ⋒ p2 = {q1 ∪ q2 | q1 ∈ p1 ∧ q2 ∈ p2}
アクセス制御のよいモデル
属性 A の半環で許可を表現
要求 r ∈ P(A) = requestOf(viewer)
許可 p ∈ P(P(A)) = permissionOf(target)
確認 p allows r ⇔ ∃q ∈ p. q ⊆ r
半環 P(P(A)), ⊕, ⊗, ∅, {∅}
◮ p1 ⊕ p2 = p1 ∪ p2
◮ p1 ⊗ p2 = p1 ⋒ p2 = {q1 ∪ q2 | q1 ∈ p1 ∧ q2 ∈ p2}
直感
◮ p = {{a1, a2}, {a3}, {a4, a5}}
◮ (a1 かつ a2) または a3 または (a4 かつ a5) の属性
アクセス制御のよいモデル
属性 A の半環で許可を表現
要求 r ∈ P(A) = requestOf(viewer)
許可 p ∈ P(P(A)) = permissionOf(target)
確認 p allows r ⇔ ∃q ∈ p. q ⊆ r
半環 P(P(A)), ⊕, ⊗, ∅, {∅}
◮ p1 ⊕ p2 = p1 ∪ p2
◮ p1 ⊗ p2 = p1 ⋒ p2 = {q1 ∪ q2 | q1 ∈ p1 ∧ q2 ∈ p2}
コードによる表現
val r = requestOf(visitor)
val p1 = permissionOf(bookmark.owner)
val p2 = permissionOf(bookmark)
val p = p1 & p2 // p1 ⊗ p2
if (p allows r) Some(bookmark)
else None
半環構造の妥当性
もしこう書いてしまったら?
val r = requestOf(visitor)
val p1 = permissionOf(bookmark.owner)
val p2 = permissionOf(bookmark)
if (p1 allows r) {
if (p2 allows r) Some(bookmark)
else None
} else None
半環構造の妥当性
Theorem (ブール代数への準同型写像)
∀r. allows r : P(P(A)) → B は準同型写像
もしこう書いてしまったら? → OK!
val r = requestOf(visitor)
val p1 = permissionOf(bookmark.owner)
val p2 = permissionOf(bookmark)
if (p1 allows r) {
if (p2 allows r) Some(bookmark)
else None
} else None
半環構造の妥当性
Theorem (ブール代数への準同型写像)
∀r. allows r : P(P(A)) → B は準同型写像
注意
◮ B, ∨, ∧, ⊥, ⊤ : ブール代数
◮ p allows r : B
◮ allows : P(P(A)) → P(A) → B
◮ allows r : P(P(A)) → B (部分適用)
半環構造の妥当性
Theorem (ブール代数への準同型写像)
∀r. allows r : P(P(A)) → B は準同型写像
p1, p2 p1 ⊗ p2
p1 allows r,
p2 allows r
(p1 ⊗ p2) allows r
p1 allows r ∧ p2 allows r
⊗
allows r
allows r
∧
◮ 条件を分解してチェックしても OK
出典
G. Karvounarakis and T. J. Green.
Semiring-annotated data: Queries and
provenance?
SIGMOD Record, 41(3):5–14, 2012.
R. Thion, F. Lesueur, and M. Talbi.
Tuple-based access control: a provenance-based
information flow control for relational data.
In 30th ACM/SIGAPP SAC, 2015.
実装戦略
基本戦略
Controller Business Logic
Domain Logic
Infrastructure
HTTP
(Adapter)
Application
Service
CLI
(Adapter)
Domain
Model
Repository
Interface
Domain
Service
Database
External
Service
複数層に権限チェックを分離可能 (∵ 準同型定理)
◮ アプリ層 : 前提条件でフィルタ
◮ ドメイン層 : 完全な権限チェック
◮ インフラ層 : 効率化のためのフィルタ
各層でのチェック
アプリ層 : 前提条件でフィルタ
◮ (例) 非公開ユーザのページは他人に見せない
ドメイン層 : 完全な権限チェック
◮ ⊗ された完全な権限をチェック
◮ アクセス制御の完全性はこの層に集中させる
インフラ層 : 効率化のためのフィルタ
◮ 権限の要求を検索クエリに対応させる
◮ 各テーブルごとでよい
◮ 完全でなくてよい
整合性のための工夫
一貫性
◮ 属性へのマッピングは一箇所で定義
◮ 同じ型には同じ方法で要求/許可が決まる
def requestOf(user: User): Request = user.accountId match {
case AccountId.Guest => Request(Attribute.Public)
case _ => Request(
Attribute.Public,
Attribute.User(user.id)) }
def permissionOf(user: User): Permission = user.status match {
case User.Status.Private => Permission(
Attribute.User(user.id) +:
user.allowedUsers.map(u => Attribute.User(u.id)): _*)
case User.Status.Public => Permission(
Attribute.Public,
Attribute.User(user.id)) }
整合性のための工夫
完全性
◮ 許可の可否のための完全な情報を使用
◮ (例) ブックマークの閲覧にはユーザの閲覧許可も必要
// ユーザ閲覧可否なしにブックマーク閲覧可否だけ調べるのは禁止
private def permissionOf(bookmark: Bookmark): Permission = ...
// ブックマーク閲覧可否は以下の 2 つの合成
// - 持ち主のユーザ閲覧可否
// - ブックマークアイテムそのものの閲覧可否
def permissionOf(pair: (User, Bookmark)): Permission =
permissionOf(user = pair._1) & // ユーザ
permissionOf(bookmark = pair._2) // ブックマークそのもの
検索クエリとの対応
クエリとの対応
◮ インフラ層での MySQLや Elasticsearch のクエリ
◮ 許可されないレコードは除いて効率化
◮ 要求 → クエリ断片への変換を用意すればよい
val r = requestOf(visitor)
// => Request(Attribute.User(u))
val user: Option[User] = db.run { sql"""
SELECT * FROM user
LEFT JOIN allowing
ON user.id = allowing.user_id
WHERE user.status = 'public'
OR user.id = $u
OR allowing.allowed_user_id = $u
""".as[User] }.headOption
完全 vs. テーブルごと
permissionOf(user)& permissionOf(bookmark)
◮ JOIN が必要
◮ user テーブルと bookmarkテーブル
◮ 条件が複雑
◮ AND 条件と OR 条件
テーブルごとにチェック
◮ bookmarkテーブルの検索時は
permissionOf(bookmark)だけチェック
◮ permissionOf(user)は別の層でチェック
◮ 準同型定理が活かされる
その他の効率化
和積形
許可は和積形 p′
でも表せる
◮ user : 本人 ⊕ 閲覧許可ユーザ
◮ bookmark : 本人 (非公開の場合)
◮ 全体: (本人 ⊕ 閲覧許可ユーザ) ⊗ (本人)
和積形のままチェック
◮ p′
allows r ⇔ ∀q ∈ p′
. q ∩ r = ∅
◮ 積和形のチェックと同値
p′
allows r ⇔ p allows r
和積形
許可は和積形 p′
でも表せる
◮ user : 本人 ⊕ 閲覧許可ユーザ
◮ bookmark : 本人 (非公開の場合)
◮ 全体: (本人 ⊕ 閲覧許可ユーザ) ⊗ (本人)
和積形のままチェック
◮ p′
allows r ⇔ ∀q ∈ p′
. q ∩ r = ∅
◮ 積和形のチェックと同値
p′
allows r ⇔ p allows r
⊗時に⋒を計算する必要はない
まとめ
モデル化
◮ AND/OR 条件を属性の半環で表現
◮ チェック関数はブール代数への準同型写像
実装戦略
◮ 準同型定理を利用してチェック処理を分離
◮ 要求/許可は一元管理
◮ 完全性の担保はドメインロジックに集中
効率化
◮ 要求をテーブルへのクエリ条件にしてフィルタ
◮ 和積形の利用で無駄な計算をしないように

More Related Content

What's hot

待ち事象から考える、Sql server の改善ポイント
待ち事象から考える、Sql server の改善ポイント待ち事象から考える、Sql server の改善ポイント
待ち事象から考える、Sql server の改善ポイント
Masayuki Ozawa
 
Dalvik仮想マシンのアーキテクチャ 改訂版
Dalvik仮想マシンのアーキテクチャ 改訂版Dalvik仮想マシンのアーキテクチャ 改訂版
Dalvik仮想マシンのアーキテクチャ 改訂版
Takuya Matsunaga
 

What's hot (20)

Innodb Deep Talk #2 でお話したスライド
Innodb Deep Talk #2 でお話したスライドInnodb Deep Talk #2 でお話したスライド
Innodb Deep Talk #2 でお話したスライド
 
Ormとの付き合い方
Ormとの付き合い方Ormとの付き合い方
Ormとの付き合い方
 
5.6 以前の InnoDB Flushing
5.6 以前の InnoDB Flushing5.6 以前の InnoDB Flushing
5.6 以前の InnoDB Flushing
 
導入から 10 年、PHP の trait は滅びるべきなのか その適切な使いどころと弱点、将来について
導入から 10 年、PHP の trait は滅びるべきなのか その適切な使いどころと弱点、将来について導入から 10 年、PHP の trait は滅びるべきなのか その適切な使いどころと弱点、将来について
導入から 10 年、PHP の trait は滅びるべきなのか その適切な使いどころと弱点、将来について
 
react-scriptsはwebpackで何をしているのか
react-scriptsはwebpackで何をしているのかreact-scriptsはwebpackで何をしているのか
react-scriptsはwebpackで何をしているのか
 
Java ORマッパー選定のポイント #jsug
Java ORマッパー選定のポイント #jsugJava ORマッパー選定のポイント #jsug
Java ORマッパー選定のポイント #jsug
 
PHP と SAPI と ZendEngine3 と
PHP と SAPI と ZendEngine3 とPHP と SAPI と ZendEngine3 と
PHP と SAPI と ZendEngine3 と
 
モダン PHP テクニック 12 選 ―PsalmとPHP 8.1で今はこんなこともできる!―
モダン PHP テクニック 12 選 ―PsalmとPHP 8.1で今はこんなこともできる!―モダン PHP テクニック 12 選 ―PsalmとPHP 8.1で今はこんなこともできる!―
モダン PHP テクニック 12 選 ―PsalmとPHP 8.1で今はこんなこともできる!―
 
マルチテナント化で知っておきたいデータベースのこと
マルチテナント化で知っておきたいデータベースのことマルチテナント化で知っておきたいデータベースのこと
マルチテナント化で知っておきたいデータベースのこと
 
RDB技術者のためのNoSQLガイド NoSQLの必要性と位置づけ
RDB技術者のためのNoSQLガイド NoSQLの必要性と位置づけRDB技術者のためのNoSQLガイド NoSQLの必要性と位置づけ
RDB技術者のためのNoSQLガイド NoSQLの必要性と位置づけ
 
なかったらINSERTしたいし、あるならロック取りたいやん?
なかったらINSERTしたいし、あるならロック取りたいやん?なかったらINSERTしたいし、あるならロック取りたいやん?
なかったらINSERTしたいし、あるならロック取りたいやん?
 
待ち事象から考える、Sql server の改善ポイント
待ち事象から考える、Sql server の改善ポイント待ち事象から考える、Sql server の改善ポイント
待ち事象から考える、Sql server の改善ポイント
 
Cassandra における SSD の活用
Cassandra における SSD の活用Cassandra における SSD の活用
Cassandra における SSD の活用
 
Fluentdのお勧めシステム構成パターン
Fluentdのお勧めシステム構成パターンFluentdのお勧めシステム構成パターン
Fluentdのお勧めシステム構成パターン
 
スケールアウトするPostgreSQLを目指して!その第一歩!(NTTデータ テクノロジーカンファレンス 2020 発表資料)
スケールアウトするPostgreSQLを目指して!その第一歩!(NTTデータ テクノロジーカンファレンス 2020 発表資料)スケールアウトするPostgreSQLを目指して!その第一歩!(NTTデータ テクノロジーカンファレンス 2020 発表資料)
スケールアウトするPostgreSQLを目指して!その第一歩!(NTTデータ テクノロジーカンファレンス 2020 発表資料)
 
Spring Cloud Data Flow で構成される IIJ IoTサービス
Spring Cloud Data Flow で構成される IIJ IoTサービスSpring Cloud Data Flow で構成される IIJ IoTサービス
Spring Cloud Data Flow で構成される IIJ IoTサービス
 
PHP-FPM の子プロセス制御方法と設定をおさらいしよう
PHP-FPM の子プロセス制御方法と設定をおさらいしようPHP-FPM の子プロセス制御方法と設定をおさらいしよう
PHP-FPM の子プロセス制御方法と設定をおさらいしよう
 
クラウド環境下におけるAPIリトライ設計
クラウド環境下におけるAPIリトライ設計クラウド環境下におけるAPIリトライ設計
クラウド環境下におけるAPIリトライ設計
 
MongoDBが遅いときの切り分け方法
MongoDBが遅いときの切り分け方法MongoDBが遅いときの切り分け方法
MongoDBが遅いときの切り分け方法
 
Dalvik仮想マシンのアーキテクチャ 改訂版
Dalvik仮想マシンのアーキテクチャ 改訂版Dalvik仮想マシンのアーキテクチャ 改訂版
Dalvik仮想マシンのアーキテクチャ 改訂版
 

Similar to はてなブックマークにおけるアクセス制御 - 半環構造に基づくモデル化

日本 GNU AWK ユーザー会チラシ - OSC2012 Tokyo/Fall
日本 GNU AWK ユーザー会チラシ - OSC2012 Tokyo/Fall日本 GNU AWK ユーザー会チラシ - OSC2012 Tokyo/Fall
日本 GNU AWK ユーザー会チラシ - OSC2012 Tokyo/Fall
博文 斉藤
 
Rails初心者レッスン lesson1 3rd edition
Rails初心者レッスン lesson1 3rd editionRails初心者レッスン lesson1 3rd edition
Rails初心者レッスン lesson1 3rd edition
Goh Matsumoto
 
GNU awk (gawk) を用いた Apache ログ解析方法
GNU awk (gawk) を用いた Apache ログ解析方法GNU awk (gawk) を用いた Apache ログ解析方法
GNU awk (gawk) を用いた Apache ログ解析方法
博文 斉藤
 
エコなWebサーバー
エコなWebサーバーエコなWebサーバー
エコなWebサーバー
emasaka
 
Chefを利用した運用省力化とDevOpsの取り組みについて
Chefを利用した運用省力化とDevOpsの取り組みについてChefを利用した運用省力化とDevOpsの取り組みについて
Chefを利用した運用省力化とDevOpsの取り組みについて
Yuuki Namikawa
 

Similar to はてなブックマークにおけるアクセス制御 - 半環構造に基づくモデル化 (20)

RESTful APIとしてのRailsとクライアントとしてのJavaScript
RESTful APIとしてのRailsとクライアントとしてのJavaScriptRESTful APIとしてのRailsとクライアントとしてのJavaScript
RESTful APIとしてのRailsとクライアントとしてのJavaScript
 
DEV-010_エンプラ系業務 Web アプリ開発に効く! 実践的 SPA 型モダン Web アプリ開発の選択手法
DEV-010_エンプラ系業務 Web アプリ開発に効く! 実践的 SPA 型モダン Web アプリ開発の選択手法DEV-010_エンプラ系業務 Web アプリ開発に効く! 実践的 SPA 型モダン Web アプリ開発の選択手法
DEV-010_エンプラ系業務 Web アプリ開発に効く! 実践的 SPA 型モダン Web アプリ開発の選択手法
 
AWS は形式手法の夢を見るか? - モデル検査器 Alloy によるインフラ設計
AWS は形式手法の夢を見るか? - モデル検査器 Alloy によるインフラ設計AWS は形式手法の夢を見るか? - モデル検査器 Alloy によるインフラ設計
AWS は形式手法の夢を見るか? - モデル検査器 Alloy によるインフラ設計
 
PHP 2大 web フレームワークの徹底比較!
PHP 2大 web フレームワークの徹底比較!PHP 2大 web フレームワークの徹底比較!
PHP 2大 web フレームワークの徹底比較!
 
20101018 JJUG CCC10 WindowsAzure
20101018 JJUG CCC10 WindowsAzure20101018 JJUG CCC10 WindowsAzure
20101018 JJUG CCC10 WindowsAzure
 
Okinawa.rb 第2回勉強会
Okinawa.rb 第2回勉強会Okinawa.rb 第2回勉強会
Okinawa.rb 第2回勉強会
 
Ruby で扱う LDAP のススメ
Ruby で扱う LDAP のススメRuby で扱う LDAP のススメ
Ruby で扱う LDAP のススメ
 
JavaScript Tips 2015(PDF 版)
JavaScript Tips 2015(PDF 版)JavaScript Tips 2015(PDF 版)
JavaScript Tips 2015(PDF 版)
 
Scala on Hadoop
Scala on HadoopScala on Hadoop
Scala on Hadoop
 
日本 GNU AWK ユーザー会チラシ - OSC2012 Tokyo/Fall
日本 GNU AWK ユーザー会チラシ - OSC2012 Tokyo/Fall日本 GNU AWK ユーザー会チラシ - OSC2012 Tokyo/Fall
日本 GNU AWK ユーザー会チラシ - OSC2012 Tokyo/Fall
 
Rails初心者レッスン lesson1 3rd edition
Rails初心者レッスン lesson1 3rd editionRails初心者レッスン lesson1 3rd edition
Rails初心者レッスン lesson1 3rd edition
 
MoteMote Compiler Plugin
MoteMote Compiler PluginMoteMote Compiler Plugin
MoteMote Compiler Plugin
 
DTraceによるMySQL解析ことはじめ
DTraceによるMySQL解析ことはじめDTraceによるMySQL解析ことはじめ
DTraceによるMySQL解析ことはじめ
 
GNU awk (gawk) を用いた Apache ログ解析方法
GNU awk (gawk) を用いた Apache ログ解析方法GNU awk (gawk) を用いた Apache ログ解析方法
GNU awk (gawk) を用いた Apache ログ解析方法
 
Inside mobage platform
Inside mobage platformInside mobage platform
Inside mobage platform
 
Haikara
HaikaraHaikara
Haikara
 
RedmineとGitとスクラム
RedmineとGitとスクラムRedmineとGitとスクラム
RedmineとGitとスクラム
 
エコなWebサーバー
エコなWebサーバーエコなWebサーバー
エコなWebサーバー
 
第8回KPF発表資料
第8回KPF発表資料第8回KPF発表資料
第8回KPF発表資料
 
Chefを利用した運用省力化とDevOpsの取り組みについて
Chefを利用した運用省力化とDevOpsの取り組みについてChefを利用した運用省力化とDevOpsの取り組みについて
Chefを利用した運用省力化とDevOpsの取り組みについて
 

More from Lintaro Ina (7)

Gradual Typing for Generics
Gradual Typing for GenericsGradual Typing for Generics
Gradual Typing for Generics
 
Emacs上のターミナルを最強に
Emacs上のターミナルを最強にEmacs上のターミナルを最強に
Emacs上のターミナルを最強に
 
論理と計算のしくみ 5.3 型付きλ計算 (前半)
論理と計算のしくみ 5.3 型付きλ計算 (前半)論理と計算のしくみ 5.3 型付きλ計算 (前半)
論理と計算のしくみ 5.3 型付きλ計算 (前半)
 
HTMLからの本文抽出
HTMLからの本文抽出HTMLからの本文抽出
HTMLからの本文抽出
 
はてなブックマーク in Scala
はてなブックマーク in Scalaはてなブックマーク in Scala
はてなブックマーク in Scala
 
『BrandSafe はてな』のアドベリフィケーションのしくみ
『BrandSafe はてな』のアドベリフィケーションのしくみ 『BrandSafe はてな』のアドベリフィケーションのしくみ
『BrandSafe はてな』のアドベリフィケーションのしくみ
 
『BrandSafe はてな』のアドベリフィケーションのしくみ
『BrandSafe はてな』のアドベリフィケーションのしくみ『BrandSafe はてな』のアドベリフィケーションのしくみ
『BrandSafe はてな』のアドベリフィケーションのしくみ
 

はてなブックマークにおけるアクセス制御 - 半環構造に基づくモデル化