Angular Twitter登录-将用户重定向到身份验证

Angular Twitter登录-将用户重定向到身份验证,angular,scala,twitter,akka,twitter-oauth,Angular,Scala,Twitter,Akka,Twitter Oauth,我无法向Twitter验证用户身份。我开发了一个Scala代码,处理所有与Twitter的服务器端连接,并将Angular 5+应用程序作为前端。因此,当用户单击HTML Twitter按钮时,此角度函数将激活: callTwLogin(): void{ // StepOne var win = window.open('','_blank','height=500,width=800'); // I open a blank popup window const ca

我无法向Twitter验证用户身份。我开发了一个Scala代码,处理所有与Twitter的服务器端连接,并将Angular 5+应用程序作为前端。因此,当用户单击HTML Twitter按钮时,此角度函数将激活:

callTwLogin(): void{
    // StepOne
    var win = window.open('','_blank','height=500,width=800'); // I open a blank popup window 
    const callback2 = 'http://127.0.0.1:8081/TwitterRedirect'; 
    this.http.get(url1+callback2, {responseType: 'text'}).subscribe(data =>{
      console.log(data); //Just for testing purposes. 
    });
   }
现在,我的Scala/Akka服务器端代码处理这个GET请求,并从Twitter获取request_令牌。然后,它获取请求令牌和令牌密钥,并向oauth/authenticate发出GET请求,以获取HTML

val route = cors(settings){
      path("requestToken"){
        get {
          parameters('callback.as[String])(cb => {
            val callback = this.encodeUriComp(cb)
            val url = "https://api.twitter.com/oauth/request_token"
            this.oauth_timestamp = this.createTimestamp()
            this.oauth_nonce = this.randomString(32)
            val authorization = headers.RawHeader("Authorization",
              """OAuth oauth_callback="""" + callback +
                """", oauth_consumer_key="""" + this.consumerKey +
                """", oauth_nonce="""" + this.oauth_nonce +
                """", oauth_signature="""" + this.encodeUriComp(this.createSignature(callback)) +
                """", oauth_signature_method="HMAC-SHA1", oauth_timestamp="""" + this.oauth_timestamp +
                """", oauth_version="1.0"""")
            val params = ByteString(callback)
            val responseFuture: Future[HttpResponse] = Http().singleRequest(HttpRequest(HttpMethods.POST, url,
              headers = List(authorization),
              entity = HttpEntity(ContentTypes.`text/plain(UTF-8)`, params)))

            implicit val timeout = Timeout(5, TimeUnit.SECONDS)
            try {
              val result = Await.result(responseFuture, timeout.duration)
              val uri = "http://localhost:4200"
              val Str = result.entity.httpEntity.toString()
              val response = Str.substring(Str.indexOf("o"),Str.indexOf(")")) //This is the final response.
              println(response)
              val arr = setRequestTokenRSP(response)
              this.oauth_token = arr(0)
              this.oauth_token_secret = arr(1)
              if(arr(2)=="true"){ // if oauth_callback_confirmed == true
                val uri = "https://api.twitter.com/oauth/authenticate?oauth_token="+arr(0)
                val rspFuture: Future[HttpResponse] = Http().singleRequest(HttpRequest(HttpMethods.GET, uri))
                implicit val to = Timeout(5, TimeUnit.SECONDS)
                try{
                  val res = Await.result(rspFuture,to.duration)
                  complete(HttpEntity(ContentTypes.`text/html(UTF-8)`,res.entity.dataBytes))
                }
                catch{
                  case e: TimeoutException => complete(HttpEntity(ContentTypes.`text/plain(UTF-8)`,"Couldn't access authentication"))
                }
               // complete(HttpResponse(status = StatusCodes.PermanentRedirect,headers = headers.Location(uri) :: Nil))
              }
              else complete("Error recieving Request Token")
              //complete(HttpEntity(ContentTypes.`text/plain(UTF-8)`,result.entity.dataBytes))
            }
            catch{
              case e: TimeoutException => complete(HttpEntity(ContentTypes.`text/plain(UTF-8)`,"Couldn't process request"))
            }
          })
        }
      }
现在这就是它变得棘手的地方。我得到了整个HTML,但当将它传递到我的前端时,它将无法识别Twitter会话。因此,每次我执行此步骤时,我都需要使用我的Twitter用户/pass登录

为了避免这种情况,我尝试直接将HTTP302重定向到/oauth/authenticate,这样我的前端就可以导航到Twitter身份验证页面。当然,这没有帮助,因为CORS的限制


我应该怎么做才能让我的用户无缝地访问身份验证页面

我做到了。。。实现这一点最无缝的方法是将URL返回到我的Angular前端应用程序。然后,我将使用window.location.href将弹出窗口重定向到URL,并创建一个EventListener,等待服务器发送的消息

这是我的web应用程序代码:

callTwLogin(): void{
    // StepOne
    var win = window.open('','_blank','height=500,width=800'); //Open a Blank PopUp.
    /** Add a listener so Scala can send a PostMessage when completing Authorization */
    window.addEventListener("message", recieveMessage, false);
    function recieveMessage(event){
      if (~event.origin.indexOf("http://127.0.0.1:8081")) {
        console.log(event.data);
      }
      else console.log("Error");
    }
    /** Making a call to backend, specifying callback URL */
    const url = 'http://127.0.0.1:8081/requestToken?callback=';
    const callback = 'http://127.0.0.1:8081/TwitterRedirect';
    this.http.get(url+callback, {responseType: 'text'}).subscribe(data =>{
      console.log(data);
      win.location.replace(data);   
    });
   }
我的服务器代码将包含两条路由。第二个将处理oauth_验证器,并向我的web应用程序发送PostMessage

path("requestToken"){
        get {
          parameters('callback.as[String])(cb => {
            /**
              * I NEED TO CHANGE AWAIT TO ONCOMPLETE!!!!
              */
              val callback = this.encodeUriComp(cb)
              val url = "https://api.twitter.com/oauth/request_token"
              this.oauth_timestamp = this.createTimestamp()
              this.oauth_nonce = this.randomString(32)
              val authorization = headers.RawHeader("Authorization",
                """OAuth oauth_callback="""" + callback +
                  """", oauth_consumer_key="""" + this.consumerKey +
                  """", oauth_nonce="""" + this.oauth_nonce +
                  """", oauth_signature="""" + this.encodeUriComp(this.createSignature(callback)) +
                  """", oauth_signature_method="HMAC-SHA1", oauth_timestamp="""" + this.oauth_timestamp +
                  """", oauth_version="1.0"""")
              val params = ByteString(callback)
              val responseFuture: Future[HttpResponse] = Http().singleRequest(HttpRequest(HttpMethods.POST, url,
                headers = List(authorization),
                entity = HttpEntity(ContentTypes.`text/plain(UTF-8)`, params)))

              implicit val timeout = Timeout(5, TimeUnit.SECONDS)
              try {
                val result = Await.result(responseFuture, timeout.duration)
                val uri = "http://localhost:4200"
                val Str = result.entity.httpEntity.toString()
                val response = Str.substring(Str.indexOf("o"), Str.indexOf(")")) //This is the final response.
                println(response)
                val arr = setRequestTokenRSP(response)
                this.oauth_token = arr(0)
                this.oauth_token_secret = arr(1)
                if (arr(2) == "true") { // if oauth_callback_confirmed == true
                  val uri = "https://api.twitter.com/oauth/authenticate?oauth_token=" + arr(0)
                  complete(HttpEntity(ContentTypes.`text/plain(UTF-8)`, uri))
                }
                else complete("Error recieving Request Token")
                //complete(HttpEntity(ContentTypes.`text/plain(UTF-8)`,result.entity.dataBytes))
              }
              catch {
                case e: TimeoutException => complete(HttpEntity(ContentTypes.`text/plain(UTF-8)`, "Couldn't process request"))
              }
            })
        }

      }~
      path("TwitterRedirect"){
        get{
          parameters('oauth_verifier.as[String], 'oauth_token.as[String])((verifier, token) => {
            val url = "http://127.0.0.1:8081/getVerifier?verifier="+verifier
            if(this.oauth_token==token) { // Check whether token recieved in authorization equals the previous one.
              this.oauth_verifier = verifier
              val rspToAngular = verifier + "|" + token
              val html =
                "<!doctype html>" +
                  "<html lang='en'>" +
                  "<head>" +
                  "<meta charset='UTF-8'> <title>Popup</title> </head>" +
                  "<body> <script type='text/javascript'>" +
                  "window.opener.postMessage('" + rspToAngular + "', 'http://localhost:4200');" +
                  "</script></body></html>"
              complete(HttpEntity(ContentTypes.`text/html(UTF-8)`, html))
            }
            else {
              val html =
                "<!doctype html>" +
                  "<html lang='en'>" +
                  "<head>" +
                  "<meta charset='UTF-8'> <title>Popup</title> </head>" +
                  "<body> <script type='text/javascript'>" +
                  "window.opener.postMessage('Error: Token Mismatch', 'http://localhost:4200');" +
                  "</script></body></html>"
              complete(HttpEntity(ContentTypes.`text/html(UTF-8)`,html))
            }
          })
        }
      }
路径(“请求令牌”){ 得到{ 参数('callback.as[String])(cb=>{ /** *我需要改变等待完成!!!! */ val callback=this.encodeUriComp(cb) val url=”https://api.twitter.com/oauth/request_token" this.oauth_timestamp=this.createTimestamp() this.oauth\u nonce=this.randomString(32) val authorization=headers.RawHeader(“授权”, “OAuth OAuth\u回调=”“”+回调+ “”,oauth_consumer_key=“”+this.consumerKey+ “”,oauth\u nonce=“”+this.oauth\u nonce+ “”,oauth_signature=“”+this.encodeUriComp(this.createSignature(回调))+ “”,oauth_签名方法=“HMAC-SHA1”,oauth_时间戳=“”+this.oauth_时间戳+ “”,oauth_version=“1.0”) val params=ByteString(回调) val responseFuture:Future[HttpResponse]=Http().singleRequest(HttpRequest(HttpMethods.POST,url, 标题=列表(授权), entity=HttpEntity(ContentTypes.`text/plain(UTF-8)`,params))) 隐式val超时=超时(5,时间单位为秒) 试一试{ val result=Await.result(responseFuture、timeout.duration) val uri=”http://localhost:4200" val Str=result.entity.httpEntity.toString() val response=Str.substring(Str.indexOf(“o”),Str.indexOf(“)”)//这是最终的响应。 println(响应) val arr=setRequestTokenRSP(响应) this.oauth_令牌=arr(0) this.oauth_token_secret=arr(1) if(arr(2)=“true”){//if oauth\u callback\u confirm==true val uri=”https://api.twitter.com/oauth/authenticate?oauth_token=“+arr(0) 完整(HttpEntity(ContentTypes.`text/plain(UTF-8)`,uri)) } else complete(“接收请求令牌时出错”) //完成(HttpEntity(ContentTypes.`text/plain(UTF-8)`,result.entity.dataBytes)) } 抓住{ 案例e:TimeoutException=>complete(HttpEntity(ContentTypes.`text/plain(UTF-8)`,“无法处理请求”)) } }) } }~ 路径(“TwitterRedirect”){ 得到{ 参数('oauth_-verifier.as[String],'oauth_-token.as[String])((verifier,token)=>{ val url=”http://127.0.0.1:8081/getVerifier?verifier=“+验证者 如果(this.oauth_token==token){//检查在授权中接收的token是否等于上一个。 this.oauth\u验证器=验证器 val rspToAngular=验证器+“|”+令牌 val html= "" + "" + "" + “弹出窗口”+ " " + “window.opener.postMessage('”+rsptoranger+“,”http://localhost:4200');" + "" 完整(HttpEntity(ContentTypes.`text/html(UTF-8)`,html)) } 否则{ val html= "" + "" + "" + “弹出窗口”+ " " + window.opener.postMessage('错误:令牌不匹配','http://localhost:4200');" + "" 完整(HttpEntity(ContentTypes.`text/html(UTF-8)`,html)) } }) } }
对于您的特定问题,我没有答案,但注意到您正在服务器处理程序中阻塞。您不应在Akka HTTP服务器路由中使用
wait.result
,它将阻塞整个流部分,并可能导致服务器中的线程不足。使用未来合成(
map
/
flatMap
)和各种未来相关指令(
onComplete
onSuccess
等)。@johanandren谢谢!我回家后会更改密码。不知道服务器可能会饿死。