VKontakte、Facebook、My World、Yandex、Odnoklassniki、Google、Twitter、LinkedInネットワークのユーザーの認証をJSF2を使用して整理する例を紹介します。 これは完全にオーサリング開発であり、最も一般的なOAuth runetプロバイダーを対象としています。 サードパーティのライブラリ、サーブレット、jsp、およびスプリングを使用せずに記述されています-JSF2およびCDIのみ。
これらはすべて、トレーニングサービスを提供する有料サイトの開発で生まれました。 当然、人々が「苦労して稼いだ」ものの少なくとも一部を手放すためには、本当に一生懸命努力する必要があります。 パスワード、電子メール、キャプチャ、タイムゾーンを使用した複雑な登録は、これに大きく貢献しません。 したがって、決定はユーザー名とパスワード(2回)のみに限定され、追加の質問はありません! 実際には、これにより複数回の登録が行われ、パスワードを忘れてしまいます。多くの場合、支払い後(通常、誰も自分のアカウントを覚えていない)や同様のトラブルが発生します。 アンケートに記入する人もほとんどいませんでした-サポートサービスは甘くありませんでした。
ソリューションは、「ワンクリック」でユーザーの登録とその後の認証を提供することを提案しました。 OAuthテクノロジーを使用したソーシャルネットワークは完全に適合します。 すでに承認があり、一意の識別子を取得するだけで済みました。 それが行われました。
私たちのサイトのメインページには、「ログイン」と「登録」の2つのボタンがあります。 技術的には、ユーザーは間違いを犯す方法がないため、これらを組み合わせることができます。ユーザーは手動でデータを入力しません。 データベースにまだないOAuthを介して識別子を受け取った場合、新しいユーザーを登録しています。それ以外の場合は、システムにそれを許可します。 新しいユーザーに対しては、あいさつを引き続き表示できます。
各ソーシャルネットワークには、すべての機能を実装する既製のライブラリがすでに存在するため、細心の注意を払った読者が、なぜ独自のソリューションを開発する必要があったのかと尋ねます。 はい、あります。 しかし、この「すべて」、この場合は冗長な機能のために、余分なボリューム、多数の依存関係、および異なる(ライブラリごとに)異なるアプローチを統合およびサポートする必要があります。 外国のバグや脆弱性も割り引く必要はありません。
それでは、すべてがどのように機能するかを詳しく見てみましょう
Habréの記事では、デモプロジェクトが開発されました-作業システムから部品が噛まれ、余分なものはすべて削除され、作業モデルのみが残りました。 記事の下部には、プロジェクトとデモへのリンクがあります。
すべてlogin.xhtmlで始まり、次のようになります。

Habrapakから取られたアイコン。 各アイコンにはメソッドコールが割り当てられ、リクエストが生成され、リダイレクトを通じてユーザーがOAuthプロバイダーのWebサイトに送信されます。
Yandexのサンプルコード:
String plainUrl = "https://oauth.yandex.ru/authorize?" +"client_id="+ yaId +"&response_type=code"; FacesContext.getCurrentInstance().getExternalContext().redirect(plainUrl);
ユーザーが自分のデータへのアクセスを提供する申し出に同意した後、彼は私たちのサイトに戻ります。ホスト側はyaLogin.xhtmlページです
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core" xmlns:ui="http://java.sun.com/jsf/facelets"> <h:head></h:head> <f:metadata> <f:viewParam id="code" name="code" value="#{yalogin.code}" /> <f:viewParam id="error" name="error" value="#{yalogin.error}" /> <f:viewParam id="state" name="state" value="#{yalogin.state}" /> <f:event type="preRenderView" listener="#{yalogin.phase2()}" /> </f:metadata> <body> </body> </html>
ご覧のとおり、受信したパラメーターコード、エラー、および状態がクラス変数に渡され、phase2()メソッドが起動され、実際にさらに処理が行われます。
エラーが返されたかどうかを確認します。
if (error!=null) { logger.info("error="+error); try { FacesContext.getCurrentInstance().getExternalContext().redirect("error.jsf"); } catch (Exception e) { logger.log(Level.SEVERE, "phase2() Error: redirect failed!", e); } return ""; }
すべてが正常である場合、トークンのリクエストを作成します。
Properties props = new Properties(); props.put("grant_type", "authorization_code"); props.put("code", code); props.put("client_id", yaId); props.put("client_secret", yaSecret); String ret1 = HttpURL.httpsPost("https://oauth.yandex.ru/token", props, "UTF-8");
そして、parsimの結果:
class YA{ String access_token; String token_type; } YA ya = (YA) XStreamFactory.get(YA.class, ret1);
アクセストークンを取得すると、ユーザーに関する情報をリクエストできます。
String ret2 = HttpURL.httpsGet("https://login.yandex.ru/info?format=json&oauth_token="+ya.access_token); class PersonData { public String birthday; public String display_name; public String sex; public String id; public String default_email; public String real_name; } PersonData personData = (PersonData) XStreamFactory.get(PersonData.class, ret2);
これで、受信したデータをCoreオブジェクト(ディスパッチャー)に転送できます。
core.getUserAutoReqProps().setEmail(personData.default_email); String[] fname = personData.real_name.split(" "); core.getUserAutoReqProps().setLastName(fname[0]); core.getUserAutoReqProps().setFirstName(fname[1]); core.getUserAutoReqProps().setSex("male".equalsIgnoreCase(personData.sex)); DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd"); core.getUserAutoReqProps().setBorn(dateFormat.parse(personData.birthday));
一意のユーザーIDを覚えて、サイトの保護された部分に移動します。
core.setValidatedId("http://my.ya.ru/"+personData.id); FacesContext.getCurrentInstance().getExternalContext().redirect("welcome.jsf");
認証されたユーザーがいます! 当然、まだ承認が必要ですが、これは記事の範囲外です。
ご覧のとおり、1つのOAuthプロバイダーで作業するには、1つのjavaクラスと1つのxhtmlページで十分です。 Yandexの場合、これはYALogin.javaとyaLogin.xhtmlになり、VKontakteの場合はVKLogin.javaとvkLogin.xhtmlになります。
アプリケーションの登録中に取得したIDとシークレットを保存する場所の問題は、次のように解決されました。アプリケーションサーバーのファイルシステム上の外部ファイルで。 これにより、次の利点が得られます。開発者はファイルにテストアプリケーションデータがあり、サーバー上の実際のデータがあるため、展開中に変更する必要はなく、機密性が尊重されます。 oauth.propertiesファイルの例はプロジェクトにあります。
ファイルパスはweb.xmlに保存されます。
<context-param> <param-name>OAuthPropertiesPath</param-name> <param-value>/opt/oauth/oauth.properties</param-value> </context-param>
アプリケーションが起動すると、アクションBeanが開き、このファイルを解析します。
@Named @ApplicationScoped public class OAuthDAO implements Serializable { private static final long serialVersionUID = 1L; private Properties prop; private static Logger logger = Logger.getLogger(OAuthDAO.class.getName()); public OAuthDAO() { load(); } public boolean load(){ try (FileInputStream fis = new FileInputStream(FacesContext.getCurrentInstance().getExternalContext().getInitParameter("OAuthPropertiesPath"))){ prop = new Properties(); prop.load(fis); if (prop.isEmpty()) { return false; } } catch (Exception ex) { return false; } return true; } public String getProperty(String key) { return prop.getProperty(key); } }
提示されたテストアプリケーションでは、認証が完了すると、アプリケーションの保護された部分を象徴するwelcome.xhtmlページが表示されます。 権限のないユーザーがこのページにアクセスするのを防ぐために、core.fiscal()メソッドがpreRenderViewイベントによって呼び出され、イベントがチェックされます。
<f:metadata> <f:event listener="#{core.fiscal()}" type="preRenderView" /> </f:metadata>
デモではGlassFishアプリケーションサーバーを実行しています。 JSONとXMLの解析には、XStreamライブラリが使用されました。
こちらのアプリケーションをご覧ください 。
Eclipse でプロジェクトをダウンロードしてください 。