force.comでは、Sitesがポータルログインのフロントとしてよく使われます。

Salesforceが提供するカスタマーポータルの標準画面はアレだからね…。

 

で、Sitesを入り口にするということはVF、Apexでログイン処理をするわけで

ログインのメソッドとしてSite.Login(username, password, startUrl)というのがあって、

ここにバインドしたユーザ名やパスワードを入れたらSitesに紐付けたポータルにログインできます。

 

が、ここで注意しておきたいのが、Site.Loginメソッドが以下の手順でログイン処理を実装していること。

 

1. エンドユーザがユーザ名とパスワードを入力してログインボタンを押下する。(htmlのformタグによるPOST)

2. Apex側でSite.Loginを呼び出し、セッションを発行する。

※発行するだけで、エンドユーザのブラウザのCookieに保存するわけではないことに注意!

3. Site.Loginのreturn値であるPageReferenceをメソッドの戻り値としてreturnする。

4. エンドユーザはSite.Loginのreturn値のURL(https://[site-domain]/secur/frontdoor.jsp)にリダイレクトする。

5. frontdoor.jspにsidパラメータ付きで渡されると、sid値をセッションIDとしてレスポンスのSet-Cookieによって

ブラウザにCookieが設定されて、認証完了となる。

6. 認証後の画面(Site.LoginのstartUrl値)にリダイレクトする。

 

実際のレスポンス(HTTPヘッダ)はこんな感じ(firebug)

Site.Loginのレスポンス↓
Site.loginのレスポンス

 

frontdoor.jspのレスポンス↓(ドメイン名やSessionIDや組織IDを隠そうとしたら、Cookieのほとんどが黒塗りw)

frontdoor.jspのレスポンス

 

重要なのは、2の時点ではセッションを発行しているだけで、ブラウザにSet-Cookieを発行しているわけではなく、

frontdoor.jspに発行したセッションIDをパラメータで渡すことで

初めてブラウザにSet-Cookieが発行されるということ。

 

つまり、Site.Loginのreturn値を返さずに別のPageReference値を返すと

セッションが発行されるだけで、認証が完了しないということになります。

 

ただし、

のように、frontdoor.jspへのリダイレクトURLからセッションIDを取得して保持しておき

ログインするときにはfrontdoor.jsp?sid=[セッションID]のURLにリダイレクトさせてあげれば

Site.Loginを発行した直後ではない任意のタイミングでログインを実行させることも可能です。

 

また、上記でリダイレクトと書きましたが、これは301とかのステータスコードによるリダイレクトではなくて

JavaScript(location.href)によるオートリダイレクトになります。

 

つまり3でPOSTに対するレスポンスはlocation.href=[frontdoor.jspのurl]が書かれたhtmlで、

5のfrontdoor.jspに対するGETリクエストのレスポンスはlocation.href=[startUrl]が書かれたhtmlということ。

 

基本的にApexのPageReferenceでポストバックじゃない場合は、全部このリダイレクト方法っす。

 

ちなみに、Site.LoginでカスタマーポータルにログインしたときのドメインはSitesのドメインですが

デフォルトの/secur/login_portal.jspでログインしたり、login_portal.jspのformをハックする方法でログインすると

Salesforce組織のドメイン(csとかapとかnaとか)になります。

 

後者の方法でもPOSTすると、frontdoor.jspに飛ばされてCookieをセットするフローになります。

 

この後、/_nc_external/identity/legacylogin/server/PortalDoorっていうURLに飛ばされて

さらにリダイレクトしてstartUrlに遷移します。(legacyloginって思いっきり書いてあるw)