[英]Decode Cookie String with Scala/Play Framework 2.7.x
好。
因此,在scala / play框架中解码Cookie的正常方法是这样的:
def admin_scrape[T]:Action[AnyContent] = Action.async {request: Request[AnyContent] => Future {
println("****************************")
println("inside admin_scrape")
println("****************************")
val body: AnyContent = request.body
val jsonBody: Option[JsValue] = body.asJson
var texts_update: String = "";
var article_url_update: String = "";
jsonBody
.map{json =>
println("value of json")
println(json)
request.session
.get("access_rights") //access_rights is the token name in the cookie string I set
.map{access_rights =>
<...>
但是,我想在Play中使用套接字。
不幸的是,播放框架的Web套接字支持( https://www.playframework.com/documentation/2.7.x/ScalaWebSockets )明确支持类似于流的结构,并且数据流在前端启动。 不敲它们,也许这是一个设计选择,但是我也希望在套接字中插入能够在后端实例化的请求。 所以我使用了这个( https://github.com/TooTallNate/Java-WebSocket )获得惯用的套接字支持。
这可行。
但是,请考虑以下因素(它可以正常工作):
override def onOpen(conn: WebSocket, handshake: ClientHandshake): Unit = {
conn.send("Welcome to the server client!")
broadcast("new connection everyone: " + handshake.getResourceDescriptor)
var cookie = "no cookie"
if(handshake.hasFieldValue("Cookie")){
println("We found a cookie")
var cookie = handshake.getFieldValue("Cookie");
println("value of cookie")
println(cookie)
// the following CODE_BLOCK does not work
// and gives the error:
// [error] /Users/patientplatypus/Documents/platypusNEST/the_daily_blech/scala_blech_blog/blog/app/sockets/SocketServer.scala:86:32: value decode is not a member of object play.api.mvc.Cookies
// [error] val decode_val = Cookies.decode(cookie)
// [error] ^
// *CODE_BLOCK*
// val decode_val = play.api.mvc.Cookies.decode(cookie)
// println("value of decode_val")
// println(decode_val)
// *CODE_BLOCK*
// reasoning - I need a way to get the cookie string into a mapping and this seemed likely.
}else{
println("We did not find a cookie")
}
<...>
当我从具有客户端Cookie的应用程序运行此程序时,我成功在服务器上打印了:
We found a cookie
value of cookie
PLAY_SESSION=SUPERDUPERLONGHASHSTRING
我需要能够像处理请求一样将此哈希字符串转换回映射,但是我无法找到正确的解码。 上面进行了尝试,但我意识到我已经在阅读Play框架2.0的文档( https://www.playframework.com/documentation/2.0/api/scala/play/api/mvc/Cookies $ .html)。 我想知道当前的2.7.x版本中是否存在某种解码功能,或者如何将该哈希字符串转换回cookie映射。
编辑:
目前,最相关的文件似乎是https://www.playframework.com/documentation/2.7.x/api/scala/play/api/mvc/Cookies $ html的,特别是decodeCookieHeader
或decodeSetCookieHeader
,因为他们有一个字符串和根据每种方法的类型签名,返回一个Cookies序列。 但是,跑步
var cookiesDecodeCookieHeader = Cookies.decodeCookieHeader(cookie)
println("value of cookiesDecodeCookieHeader: ")
println(cookiesDecodeCookieHeader)
var cookiesDecodeSetCookieHeader = Cookies.decodeSetCookieHeader(cookie)
println("value of cookiesDecodeSetCookieHeader: ")
println(cookiesDecodeSetCookieHeader)
给我
value of cookiesDecodeCookieHeader:
List()
value of cookiesDecodeSetCookieHeader:
List()
因此,这是不正确的。
编辑编辑:
同样
var cookiesFromCookieHeader = Cookies.fromCookieHeader(Some(cookie.toString))
println("value of cookiesFromCookieHeader: ")
println(cookiesFromCookieHeader)
var cookiesFromSetCookieHeader = Cookies.fromSetCookieHeader(Some(cookie.toString))
println("value of cookiesFromSetCookieHeader: ")
println(cookiesFromSetCookieHeader)
结果为空地图。 此时,我的解决方案似乎集中于随机浏览手册页( https://www.playframework.com/documentation/2.7.x/api/scala/play/api ),因此我打开了一个有关在游戏github上进行澄清的问题:( https://github.com/playframework/playframework/issues/9837 )。
如果有人有任何想法,请告诉我。 谢谢!
编辑编辑编辑:
我已经到了研究其他JWT库的地步,因为显然play不能按我需要的方式工作:<。 我看过https://github.com/pauldijou/jwt-scala/ ,但它似乎不适用于最新版本的播放器(请参阅此处: https : //github.com/pauldijou/jwt- scala / issues / 153 )。 我也看过像这样的东西(看起来很好,很整洁) https://dzone.com/articles/jwt-authentication-with-play-framework ,但是它们使用的库已被弃用。
哇,这不应该那么难。 任何建议,将不胜感激。
我设法通过在此处找到的play framework
备份Cookies.scala
文件来弄清楚( https://github.com/playframework/playframework/blob/2.7.x/core/play/src/main/scala/play /api/mvc/Cookie.scala )。 这比我认为仅应该解析会话cookie数据(主要是要知道在哪里查找)要困难得多,因此我不必导入随机库。 这也是使用java-websocket
包的示例,它比play framework
方法更为习惯。 我正在发布整个文件(很小),以便可以看到所有导入和逻辑。
如果您尝试自己实现此目的,则应该找到以下输出:
value of jws.getBody.asScala.toMap:
Map(data -> {your_cookie_key=your_cookie_value, csrfToken=SUPER-SECRET-LONGHASH},
nbf -> SECRETNUM, iat -> SECRETNUM)
在您的终端中。
再次感谢所有愿意提供帮助的人。
package sockets
import play.api.libs.json._
import java.io.BufferedReader
import java.io.IOException
import java.io.InputStreamReader
import java.net.InetSocketAddress
import java.net.UnknownHostException
import java.nio.ByteBuffer
import org.java_websocket.WebSocket
import org.java_websocket.WebSocketImpl
import org.java_websocket.framing.Framedata
import org.java_websocket.handshake.ClientHandshake
import org.java_websocket.server.WebSocketServer
import javax.inject._
import play.api.libs.json._
import play.api._
import play.api.mvc._
import play.api.http._
import scala.collection.JavaConverters._
import io.jsonwebtoken.Jwts
import io.jsonwebtoken._
import java.nio.charset.StandardCharsets
import java.time.Clock
import java.util.{ Base64, Date, Locale }
@Singleton
class SocketServer @Inject()() extends WebSocketServer(new InetSocketAddress(8887)){
def parse(encodedString: String): Map[String, AnyRef] = {
println("inside parse def and value of encodedString: ", encodedString)
println("***************")
println("***************")
println("***************")
var newEncodedString = encodedString.slice(13, encodedString.length)
println("value of newEncodedString")
println(newEncodedString)
println("***************")
println("***************")
println("***************")
def jwtConfiguration = new JWTConfiguration();
val jwtClock = new io.jsonwebtoken.Clock {
val clock = Clock.systemDefaultZone().instant()
override def now(): Date = java.util.Date.from(clock)
}
val base64EncodedSecret: String = {
Base64.getEncoder.encodeToString(
"hellotheresailor".getBytes(StandardCharsets.UTF_8) //note that this secret should ideally be set in your application.conf file and imported via injection
)
}
val jws: Jws[Claims] = Jwts.parser()
.setClock(jwtClock)
.setSigningKey(base64EncodedSecret)
.setAllowedClockSkewSeconds(jwtConfiguration.clockSkew.toSeconds)
.parseClaimsJws(newEncodedString)
val headerAlgorithm = jws.getHeader.getAlgorithm
if (headerAlgorithm != jwtConfiguration.signatureAlgorithm) {
val id = jws.getBody.getId
val msg = s"Invalid header algorithm $headerAlgorithm in JWT $id"
throw new IllegalStateException(msg)
}
println("value of jws.getBody.asScala.toMap: ")
println(jws.getBody.asScala.toMap)
jws.getBody.asScala.toMap
}
override def onOpen(conn: WebSocket, handshake: ClientHandshake): Unit = {
conn.send("Welcome to the server!")
broadcast("new connection: " + handshake.getResourceDescriptor)
var cookie = "no cookie"
if(handshake.hasFieldValue("Cookie")){
println("We found a cookie")
var cookie = handshake.getFieldValue("Cookie");
println("value of cookie")
println("parsedCookie: ")
val parsedCookie = parse(cookie)
println(parsedCookie)
}else{
println("We did not find a cookie")
}
println(
conn.getRemoteSocketAddress.getAddress.getHostAddress +
" entered the room!")
}
override def onClose(conn: WebSocket,
code: Int,
reason: String,
remote: Boolean): Unit = {
broadcast(conn + " has left the room!")
println(conn + " has left the room!")
}
override def onMessage(conn: WebSocket, message: String): Unit = {
broadcast(message)
println(conn + "we heard: " + message)
}
override def onMessage(conn: WebSocket, message: ByteBuffer): Unit = {
broadcast(message.array())
println(conn + "we heard: " + message)
}
override def onError(conn: WebSocket, ex: Exception): Unit = {
ex.printStackTrace()
if (conn != null) {}
}
override def onStart(): Unit = {
println("Server started!")
setConnectionLostTimeout(0)
setConnectionLostTimeout(100)
}
}
因此,在您从Cookie检索值的示例中,您似乎实际上是在谈论检索会话值( request.session.get(...)
)。
不幸的是,播放框架的Web套接字支持( https://www.playframework.com/documentation/2.7.x/ScalaWebSockets )明确支持类似于流的结构,并且数据流在前端启动。
我不确定您的意思,Play绝对有可能在Websocket通信中发送第一条消息。
import play.api.mvc._
import akka.stream.scaladsl._
def socket = WebSocket.accept[String, String] { request =>
// Just ignore the input
val in = Sink.ignore
// Send a single 'Hello!' message and close
val out = Source.single("Hello!")
Flow.fromSinkAndSource(in, out)
}
这是一个非常简单的示例,它将返回"Hello!"
建立连接后,将消息发送给websocket客户端。
此处理代码还可以直接访问request: RequestHeader
,这意味着您可以直接从那里直接从会话中获取内容,而无需解码任何cookie:
def ws = WebSocket.accept { request =>
request.session.get("access_rights") match {
case Some(value) =>
println("We found access_rights!")
println("value of access_rights")
println(value)
case None =>
println("We did not find access_rights!")
}
val in = Sink.ignore
val out = Source.single("Welcome to the server client!")
Flow.fromSinkAndSource(in, out)
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.