play2.0新浪OAuth 2を実現する.0

2469 ワード

最近、マイクロブログを使ってログインするプロジェクトがあります.java版のsdkを見て、面倒です.もともとjavaをよく知らないので、人が混乱しています.oauth 2のライセンスの流れは複雑ではありません.自分で書いて実現しましょう.練習の手になります.
ライブラリコード
package libs.oauth2

import play.api.libs.concurrent._

import play.api.libs.ws._
import play.core.parsers._
import play.api.libs.json._

case class OAuthKey(key:String, secret:String)
case class AccessToken(token:String)
case class AccessTokenError(error:String, errorCode:Int, request:String)
case class OAuth2(authorizationUrl: String, accessToken: String, redirectUri: String, key:OAuthKey){
  def authorization(responseType:String, params:Map[String, String]) = {
    val ism = if(authorizationUrl.indexOf("?") > 0) "&" else "?"
    authorizationUrl+ism+"client_id="+key.key+"&response_type="+responseType+"&redirect_uri="+java.net.URLEncoder.encode(redirectUri, "utf-8")
  }
  
  def getAccessToken(code:String):Either[AccessToken, AccessTokenError] = {
    val rs = WS.url(accessToken).withQueryString(
         ("client_id", key.key)
        ,("client_secret", key.secret)
        ,("grant_type", "authorization_code")
        ,("redirect_uri", redirectUri)
        ,("code", code)).post("content").value.get.body
    var jsonRs = Json.parse(rs)
    if(rs.indexOf("error") > 0){
      Right(AccessTokenError((jsonRs \ "error").as[String],(jsonRs \ "error_code").as[Int], (jsonRs \ "request").as[String]  ))
    }else{
      Left(AccessToken((jsonRs \ "access_token").as[String]))
    }
  }
    
}

用例を添付する
object login extends Controller {
val oauth2 = OAuth2(
      "https://api.weibo.com/oauth2/authorize",
      "https://api.weibo.com/oauth2/access_token",
      "http://xx.com/login/sinare",
      OAuthKey("key", "secret")
      );
def sina = Action{
    Redirect(oauth2.authorization("code",Map()))
  }
def sinare = Action{ implicit request => 
    request.queryString.getOrElse("code", "".toSeq).mkString match {
      case code:String if !code.isEmpty => {
        oauth2.getAccessToken(code) match{
          case Left(t) => {
             Ok("token:"+t.token)
          }
          case Right(error) => Ok("error"+error.error)
        }
      }
      case _ => Ok("error")
    }
  }
}