我无法通过Twitter验证用户身份。我已经开发了一个Scala代码,负责处理到Twitter的所有服务器端连接,以及一个Angular 5+应用程序作为前端。因此,当用户单击HTML-Twitter按钮时,此Angular函数将激活:
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_token。然后,它获取request_token和token_secret并执行GET请求以进行oauth / authenticate,以获取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登录。
为了避免这种情况,我尝试将HTTP 302直接重定向到/ oauth / authenticate,以便我的前端导航到Twitter身份验证页面。当然,由于CORS限制,这没有帮助。
我该怎么做才能使我的用户无缝访问身份验证页面?
答案 0 :(得分:0)
我做到了! ...实现此目的最无缝的方法是将URL返回到我的Angular前端应用程序。然后,我将简单地将popUp重定向到带有window.location.href的URL,并创建一个EventListener来等待服务器发送的消息。
这是我的网络应用代码:
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);
});
}
我的服务器代码将包含2条路由。第二个将处理oauth_verifier并将PostMessage发送到我的Web应用程序。
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))
}
})
}
}