2009/12/03

TwitterはRESTなAPIを備えているので、httpの通信ができれば基本的にどんな言語でもクライアントを作ることができるのがいいです。そこで私もPSTweetsというPowerShell版Twitterクライアントを作っているのですが、認証周りで問題が発生しています。

Twitterの認証には標準認証とOAuthが使えるのですが、現在はセキュリティ上の理由で標準認証は非推奨です。標準認証がなぜまずいかというと、マッシュアップサービスでTwitterに対して認証が必要な操作をする場合、ユーザーがその第三者のサービスにTwitterのIDとパスワードを送らなければならないためです。そのサービスがユーザーの認証情報を安全に保持してくれる保証はありません。

そこで考えられたのがOAuthという認証方法です。OAuthはとてもややこしいプロセスを含んでいますが、実質はそんなに難しいものではないです。要は、Twitterというサービス(これをサービスプロバイダという)にアクセスするための権限を、マッシュアップやクライアントを提供する第三者(これをコンシューマという)に委譲する仕組みです。ユーザーが「コンシューマを使いたい!」と思ったら、コンシューマは「じゃあついったーのページに飛ばしますから、あなたのアカウントを私が自由に使うことを許可してね」と言います。それでユーザーがTwitterのOAuth承認ページで「許可」すると、コンシューマはユーザーのアカウント情報を使ってTwitterのAPIを叩けるようになり、ユーザーはコンシューマにTwitterのパスワードを知らせることなくコンシューマの提供するサービスを利用することができるわけです。

さて、このOAuthをコンシューマが利用するには、Twitterにあらかじめ申請する必要があります。といっても登録ページでクライアント/サービス名などを入力するだけです。そうすると、コンシューマキーとコンシューマシークレットという文字列をもらえます。これはクライアントを特定するためのユーザー名とパスワードみたいなものです。ちなみにこの情報はコンシューマを提供する人のTwitterのユーザーアカウントに紐づいています。

コンシューマを通じてユーザーがTwitterのサービスを使うには、コンシューマを通じてTwitterからアクセストークンというものを貰う必要があります。このとき、コンシューマはTwitterに毎回コンシューマキーとコンシューマシークレットを送らなければなりません。

ここでコンシューマが独立したサーバーで運営されているサービスならば何も問題ありません。ユーザーがコンシューマキーとコンシューマシークレットを知る必要もユーザーに知られる危険性もありません。ところが、デスクトップクライアントだとどうなるかというと、コンシューマはデスクトップクライアントそのものです。なので、デスクトップクライアントはコンシューマキーとシークレットを何らかの方法で取得し、Twitterに送る機構が必要になります。

ここで、いくつかの方法があると思います。コンシューマキーとシークレットをデスクトップクライアントに暗号化して埋め込むのも一つの方法でしょう。ですが、結局は復号してTwitterに送らなければならないので、その通信をキャプチャすればユーザーは知ることができます。

なぜコンシューマキーとシークレットをユーザーに知られるとまずいかというと、それらを使うとまったく別のクライアントやサービスを、そのサービス名を詐称して作ることができてしまうからです。これがどうして問題なのかというと、そうなるとOAuthの承認が有名無実化してしまうためです。ユーザーがOAuthの承認ページで承認するサービスが本物かどうか調べるすべがありません。

メール登録制にしてコンシューマキーとシークレットを配布するとか考えましたが、なんだか大昔のシェアウェアのようで、なんとかシリアル集がはびこったように誰かが漏らしてしまう危険性を考えると難しいです。

コンシューマキーとシークレットを自分で取得してもらうというのも考えましたが、それはユーザーにとってかなり敷居が高いうえ、クライアント名がみんなバラバラになってしまいます(Twitterクライアント名はユニークであるため)。

コンシューマキーとシークレットを保持し、ユーザーからのリクエストに応じてアクセストークンを発行するサーバーを立てるというのも考えましたが、それってもうデスクトップTwitterクライアントじゃなくて、Twitterマッシュアップのデスクトップクライアントになってしまいます。

なので、デスクトップクライアントでOAuthを使うのは事実上無理なんじゃないかというのが私の結論です。

標準認証でもいいんですが、現在は標準認証は非推奨であり、そのため今からクライアントを作る場合は標準認証だとクライアント名をTwitterに登録することができなくなっています(タイムラインには「APIで」という表示になってしまう)。昔はメールでクライアント名を申請できたんですが、今はできません(この体制になる前に申請されたクライアントなら、今でも標準認証でもクライアント名を名乗れます)。これから作るクライアントで、クライアント名を名乗るにはOAuth必須です。ボット作者など、コンシューマ=ユーザーの場合はそれでもいいんですが…。これはぜひなんとか改善してもらいたいところですね。といっても、Twitter側からみると、それがコンシューマからのアクセスなのか、ユーザーからのアクセスなのか、区別をするのは難しいでしょうから、デスクトップアプリに限り標準認証でもクライアント名を名乗れるようにする、というのは難しいんじゃないかという気はします。

最近、新しいデスクトップクライアントがあまり登場せず、一方でやたらTwitterのマッシュアップサイトが増えたと思いませんか?中には、それデスクトップアプリでいいじゃないというものもちらほら。もしかして、この制限ができたためなんじゃないかと邪推までしています。うーむ、なんとかならないですかねー?

元記事:http://blogs.wankuma.com/mutaguchi/archive/2009/12/03/183506.aspx

2008/12/03

Outlook2007は、メールアドレスに.の連続(hoge...hoge@example.com)や@の前に.がある場合(hoge.hoge.@example.com)にはメールを送信することができません。受信トレイに「システム管理者」から送信不能と通知メッセージが入ります。

これは別にOutlook2007が悪いんじゃなくて、RFCに準拠しているためです。でもDocomoやauなど、このRFCに準拠していないキャリアがあって、結構、よく見ます。その辺の詳しい事情はこちらなどをどうぞ。

で、Outlookユーザーはじゃあこれらのメアドにはメールを送れないのか、と言うとそうではなく、実は裏技があって、@の前の部分を""(ダブルクォーテーション)でくくることで送信可能になります。

"hoge...hoge"@example.comや"hoge.hoge."@example.comなどのようにします。これはOKとRFCで規定されてるらしいですね。

でも毎回これを手で入力するのはメンドイ!

ということでなんとかしてみました。

Private Sub Application_ItemSend(ByVal Item As Object, Cancel As Boolean)
    Dim oMailItem As MailItem
    Dim bExistInvalidAddress As Boolean
    
    If TypeName(Item) = "MailItem" Then
        Set oMailItem = Item
        
        Dim reAddress As New RegExp
        reAddress.Pattern = "([a-zA-Z0-9\-\_\.]+)\@([a-zA-Z0-9\-\_\.]+)"
        reAddress.Global = True
            
        sMailAddresses = Split(oMailItem.To, ";")
        
        For I = 0 To UBound(sMailAddresses)
            If (InStr(sMailAddresses(I), "..") Or InStr(sMailAddresses(I), ".@")) And _
            InStr(sMailAddresses(I), """") = 0 Then
                sMailAddresses(I) = reAddress.Replace(sMailAddresses(I), """$1""@$2")
                bExistInvalidAddress = True
            End If

        Next
        
        If bExistInvalidAddress Then
            oMailItem.To = Join(sMailAddresses, ";")
            Cancel = True
        End If
        
    End If
End Sub

このようなコードをThisOutlookSessionに埋め込みます。VBエディタでF2キーを押してMicrosoft VBScript Regular Expression 1.0と5.5を参照設定してください。ただしマクロなんで毎回起動時にマクロを有効にするか聞かれます。(以上の意味が分からない方は使わないほうが無難です)

すると、問題あるメールアドレスのメールを送信しようとすると、正しくクォーテーションがつけられたメールアドレスに変換します。ただしTo:だけです。Cc:やBcc:にも対応してもよかったんですがそれは宿題ということで。

Cancel=Trueは要らないと思ったんですが、これを取るとなんかさらに''でクォートされて送信トレイに残骸が残ってしまいます。ので、一度メール編集画面に戻るようにしています。

元記事:http://blogs.wankuma.com/mutaguchi/archive/2008/12/03/162596.aspx

2008/11/22

ご無沙汰してます。牟田口です。近況は省略(えー mixiついったーブログその他などを。

さて、最近、spamコメントが鬱陶しくて色々対策を考えてるんですが、手っ取り早く効果的なのはBBQを使うことですね。某巨大掲示板群サイトで荒らしに使われた、おもに公開プロキシのリストをDNSを引いて持ってくるというものです。Perlの実装はこのページにあります。PHPの実装も見かけました

意外と.NET,C#な実装を見かけないので、最近覚えたC#でさくっとかいてみました。

using System;
using System.Net;
using System.Net.Sockets;

namespace CheckBBQ
{
    class Program
    {
        static void Main(string[] args)
        {
            if (args.Length == 0)
            {
                Console.WriteLine("BBQ判定プログラムの使い方:\r\ncheckbbq.exe IPAddressもしくはHostName\r\n戻り値:\r\n-1:失敗\r\n0:串ではない\r\n1:串である");
                return;
            }
            IPAddress[] addresses= Dns.GetHostAddresses(args[0]);
            if (addresses.Length == 0)
            {
                Console.WriteLine("-1");
                return;
            }
            string ipAddress = addresses[0].ToString();
            string[] ipAddressParts = ipAddress.Split('.');
            Array.Reverse(ipAddressParts);

            string hostName = string.Join(".", ipAddressParts) + ".niku.2ch.net";
            try
            {
                addresses = Dns.GetHostAddresses(hostName);
            }
            catch (SocketException ex)
            {
                Console.WriteLine("0");
                return;
            }
            catch (Exception ex)
            {
                Console.WriteLine("-1");
                return;
            }

            if (addresses.Length == 0)
            {
                Console.WriteLine("-1");
                return;
            }

            ipAddress = addresses[0].ToString();
            if (ipAddress == "127.0.0.2")
            {
                Console.WriteLine("1");
            }
            else
            {
                Console.WriteLine("-1");
            }
        }
    }
}

使い方はコードを見てください。これは単に引数のホストをBBQにかけ、結果を標準出力に出すコンソールアプリですが、メソッド化してもaspxに組み込んでもWebサービスにしてもまぁ好きなように使ってくださいませ。

でも、BBQは万能選手じゃありません。本来書き込めるべき人が書き込めないことも多々あります。なので、BBQをまず通してOKならOK、NGならCAPTCHA認証をやってもらう、とかがいいと思います。

トラックバックspam対策もいろいろ考えたんですが、まだ国産のは少ないので、送信データが英字のみをはじく、でも効果は結構あります。このへんmixiでメモったのでコピペ。

トラックバックって
2008年10月11日20:04

黒歴史になるんだろうか
オートディスカバリーはないと微妙だしあるとspamの温床になるし。
何らかの認証の共通規格を設ける?
RSSは2.0で一応落ち着いたけどトラックバックは発展しないままだなー
私はいま、現行規格のまま、オートディスカバリーを有効にしてかつspamトラックバックが送られないようにする方法を考え中
送り元を見に行くというはてな方式も一つの方法論であるんだけど、なんかこう納得できないものがある

コメント
むたぐち 2008年10月11日 20:07
送信元ホワイトリスト方式もなんだか微妙です
むたぐち 2008年10月11日 20:18
excerpt,titleなどの文字列で弾くのはよくある対策だけど根治法じゃない
いたちごっこだー
BBQは使えない。理由は少し考えれば分かりますので略。
やっぱりはてな方式なんかな。urlの先をまず見に行って、そこにこちらへのリンクがなければまず速効NG。
あとはお好みで、引用がなければNGとか。
でもこれって莫大なコストがかかるし送り元を見に行くというのがそもそもなんか根本的にどうなんっておもう。
むたぐち 2008年10月11日 20:38
トラックバックは性善説ベースで作られた規格
引用元を見に行くのは性悪説ベースの対処
両極端すぎる
むたぐち 2008年10月11日 21:08
送り元を見に行く方式の問題はまだあって、A→Bにトラックバックを送信された場合、B→Aに「AにBのURLが存在するか」を確認しに行く。
一見合理的だけど、このトラックバックって誰でも送れるんだよねー。Aを書いた人じゃなくても。つまり、AともBとも関係ない悪意を持つxがいて、A→Bへのトラックバックを乱射した場合どうなるか。B→AのDoS攻撃みたいなんが成立しちゃう。同ドメインへの確認間隔を制御する必要がでてくる。でもそれはもちろん正しくサービスを利用する人にとっては不便になるわけで。
むたぐち 2008年10月11日 21:28
送信元を見に行く方式で、トラックバックを送った人のリモートホストと、urlに指定されたWebサイトのドメインが一致するかまず調べるという方法もあるけど(たぶんはてなではこれをやっている)、これは正しい使い方をしていても一致しないことも当然あるわけで(手動でトラックバック打つときとかね)。だけどこの辺が確かに手の打ちどころではあるようには思う。手動で打つ時はオートディスカバリー関係ないしな。ただ、私のようにDNSの逆引きができないというか正逆で結果が異なるようなサーバーの場合は泣いてもらうしかないかなー。
むたぐち 2008年10月11日 21:32
つまり、オートディスカバリー用(Blog提供サービスが見に行く用)のtrackback ping URLと、手動で打つ場合のtrackback ping URLをまず分ける。
前者は、トラックバックを送った人のリモートホストと、urlに指定されたWebサイトのドメインが一致するかまず調べ、一致しない場合ははじく。一致した場合は送信元を見に行って、こちらへのリンクがある場合は通す。それ以外ははじく。
後者は、trackback ping URLを用意するがあるところまではコピペできるが、それに数文字、画像にかかれた文字をつけたすようにする(認証の代わり)。
この辺が落としどころかなー。
むたぐち 2008年10月11日 21:35
追加文字列は定期的に変わるようにする。
むたぐち 2008年10月11日 21:37
オートディスカバリーのほうはチェック間隔に制限を設ける。
JZ5 2008年10月11日 22:38
SPAM温床はメールと同じようなもんじゃないだろか。
バーベキューってなんですか?
手動のトラックバックURL(使わないけど)は、JavaScriptなんかで生成するのはどう? Server側とClient側で共通のアドレス作れるけど、直接ファイル読み込んでJavaScript実行してないと正しいURLがない。
http://katamari.jp/blog/index.php?UID=1163941454
むたぐち 2008年10月11日 22:54
いえねー、トラックバックってわりと新しい規格なのになんでspam温床になることを考えて規格作らなかったのかと。
eメールは昔々作られたものだから仕方ないとして。
JavaScriptいいですねー。やってみます。
トラックバックspam対策って結局同じところに辿りつくのねw>URL
むたぐち 2008年10月11日 22:55
BBQについてはこちら
http://bbq.uso800.net/

JZ5さん事後承諾でごめんなさいだけどコピペさせていただきました。

あと、BBXを使うのも一つの案かな。こっちは広告爆撃ブラックリストなので近いものがあるかと。

元記事:http://blogs.wankuma.com/mutaguchi/archive/2008/11/22/161939.aspx

2007/05/25

pstファイル(メールや連絡先などが含まれるファイル)が壊れた際、scanpst.exeというツールで修復できますが、その際RSSフィードフォルダがただのフォルダになってしまい壊れてしまいます。それを修復する方法について。

Outlook2007の「ファイル」-「インポートとエクスポート」で、「OPMLファイルからのRSSフィードのインポート」で適当なOPML(*.xml)ファイルをインポートします。じゃんぬさん作成のわんくまブログのOPMLでも使うとよいですね。

それだけで修復できます。Outlook2007を再起動すればアイコンもちゃんとRSSのものに戻ります。すばらしいですね。困った時はぜひどうぞ。

元記事:http://blogs.wankuma.com/mutaguchi/archive/2007/05/25/78352.aspx

2006/12/18

12/16、わんくま大阪勉強会#4でPowerShellのセッションをさせていただきました。
いろいろと拙いところがありましたが、ご静聴いただきありがとうございました。

いくつかフィードバックやご質問をいただきました。

・PPTに書いてること以外をしゃべってほしい
→資料だけを読まれる方のためにPPTだけを見ても分かるようにしたのですが、せっかく参加された方のためにもそれ以外のことをしゃべったほうがいいですね。今回は時間がなくてなかなか難しかったのですが次回は改善させていただきたいです。

・デモが少ないので増やしてほしい
→これも時間の関係で今回ちょっとしかやれなかったのですが、次回1/12(金)はたっぷりやれると思います。シェルを叩くだけでなくスクリプトをその場で書いていくのもいいですね(今回他の方のセッションを見て思ったのですが)。ネタを仕込んでおかなければ…。

・実際に使える実用的なスクリプトサンプルが見たい
→時間の関係でスクリプトに関してはほとんど取り上げられなかったのですが、これも次回きちっとやります。PowerShellならではのスクリプトを鋭意研究中です。あまり運用系のことがわからないので、「こんなスクリプトがあったら嬉しい」などのご意見をお待ちしております。メールやここのコメント欄などでいただきたいと思います。

・IronPythonとの住み分けは?
→申し訳ありませんが、まだIronPythonを弄るところまでは行っていません。おいおい、研究していきたいと思います。現時点では個人的にはPowerShellは運用系、IronPythonは開発系なのかなと思います。

・安定性は?
→少し重いというのがありますが、安定性はまずまずなんじゃないでしょうか。

・仕組みは?
→現時点では正直なところ、なぜ動作するのか?なぜ.NETのクラスが動的に呼び出せるのか?というところまでは追い切れていません。
Windows PowerShell in Actionという書籍に詳しい解説があるそうなので、これから読んで、みなさんにお伝えできたらいいなと思っています(購入してるのですが積読状態です(汗)。

あと中さんからエイリアスを使う上では注意が必要というコメントをいただきました。これまでのコマンドプロンプトと同名のエイリアスがあるが、それらを書くときは、オプションなどは従来とは異なるということを言っておかないと混乱する…ということですよね?>中さん
エイリアスはシェルを叩く際はデフォルトで定義されている分には積極的に使っていってもいいと思いますが(コマンドプロンプトと混同しないように、との前提が必要ですが)、スクリプトで使うときはあえてエイリアスを使うこともないかなぁと思います。
?や%などはエイリアスというか文法チックなので、こちらのほうが分かりやすいような気もします。
エイリアスとは少し離れますが、パイプを多用したスクリプトの分かりやすい記法というのも研究中です。PowerShellはやはりオブジェクトが渡るパイプが肝なので、スクリプトでも活用していきたいのですが、多用するとどうしても読みにくくなってしまいます。そのあたりをうまく解消できればいいですね。

次回(1/12(金))はまたよろしくお願いします。まだまだ勉強中なのでなかなか講演、執筆ともに拙かったり進捗が遅かったりして申し訳ありません。取り上げてほしいこと、スクリプトのネタなどがありましたらぜひフィードバックをお寄せください。

元記事:http://blogs.wankuma.com/mutaguchi/archive/2006/12/18/51695.aspx


Copyright © 2005-2018 Daisuke Mutaguchi All rights reserved
mailto: mutaguchi at roy.hi-ho.ne.jp
プライバシーポリシー

Twitter

Books