Created
November 3, 2012 17:15
-
-
Save kenmazaika/4007979 to your computer and use it in GitHub Desktop.
Jetty + Akka + Scala Basic Auth
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.pandemic.recommendation_core.web | |
import akka.actor._ | |
import akka.actor.Actor.actorOf | |
import akka.http._ | |
import org.eclipse.jetty.server.Server | |
import org.eclipse.jetty.servlet.ServletHolder | |
import org.eclipse.jetty.servlet.ServletContextHandler | |
import org.eclipse.jetty.http.security.Constraint; | |
import org.eclipse.jetty.http.security.Credential; | |
import org.eclipse.jetty.security.ConstraintMapping; | |
import org.eclipse.jetty.security.ConstraintSecurityHandler; | |
import org.eclipse.jetty.security.HashLoginService; | |
import org.eclipse.jetty.security.SecurityHandler; | |
import scala.collection.mutable.HashMap | |
import com.pandemic.recommendation_core.common._ | |
import com.pandemic.recommendation_core.common.config.ProjectConfig | |
/** | |
* This class manually embeds Jetty (see http://wiki.eclipse.org/Jetty/Tutorial/Embedding_Jetty) | |
* and forwards requests from it to Akka HTTP. There are many other ways to set things up, | |
* for example you could use the Akka Microkernel, or use the standard Jetty distribution's | |
* prebuilt servlet container. Whatever you are used to. See also: | |
* http://akka.io/docs/akka/1.2/scala/http.html | |
* | |
* You don't have to use Akka HTTP either of course, you could just write a subclass of | |
* AbstractHandler and handle requests yourself. One advantage of Akka HTTP is that it | |
* automatically suspends the Jetty requests so they are truly async (they don't tie | |
* up a thread). | |
*/ | |
class WebServer(config: ProjectConfig) { | |
// to use Akka HTTP, we need a RootEndpoint which is an actor that | |
// comes with Akka | |
private val rootEndpoint = actorOf[RootEndpoint] | |
// we register this bootstrap actor with the RootEndpoint, and have | |
// it dispatch requests for us | |
private val bootstrap = actorOf(new WebActor(rootEndpoint, config)) | |
private var maybeServer: Option[Server] = None | |
def start(): Unit = { | |
if (maybeServer.isDefined) | |
throw new IllegalStateException("can't start http server twice") | |
rootEndpoint.start | |
bootstrap.start | |
val server = new Server(config.port.getOrElse(8080)) | |
// here we pull in the servlet container; if we didn't want to use AkkaMistServlet, | |
// we could just subclass AbstractHandler and skip this dependency. | |
val handler = new ServletContextHandler(ServletContextHandler.SESSIONS) | |
val users = new HashMap[String, String] | |
users += "user1" -> "omg" | |
users += "user2" -> "lol" | |
handler.setSecurityHandler(basicAuth(users, "Private!")); | |
handler.setContextPath("/") | |
// AkkaMistServlet forwards requests to the rootEndpoint which | |
// in turn forwards them to our bootstrap actor. | |
handler.addServlet(new ServletHolder(new AkkaMistServlet()), "/*") | |
server.setHandler(handler) | |
server.start() | |
maybeServer = Some(server) | |
} | |
def run(): Unit = { | |
maybeServer foreach { _.join() } | |
} | |
def stop() = { | |
maybeServer foreach { server => | |
server.stop() | |
} | |
maybeServer = None | |
bootstrap.stop | |
rootEndpoint.stop | |
} | |
//TODO remove basic auth | |
// lifted from: https://github.com/jesperfj/jetty-secured-sample/blob/master/src/main/java/HelloWorld.java | |
// then converted to scala and modified | |
def basicAuth(users: HashMap[String, String], realm: String): SecurityHandler = { | |
var l = new HashLoginService(); | |
users.foreach { | |
case(username, password) => | |
l.putUser(username, Credential.getCredential(password), List("user").toArray) | |
} | |
l.setName(realm) | |
var constraint = new Constraint() | |
constraint.setName(Constraint.__BASIC_AUTH); | |
constraint.setRoles(List("user").toArray); | |
constraint.setAuthenticate(true); | |
var cm = new ConstraintMapping() | |
cm.setConstraint(constraint) | |
// add basic auth to the following endpoints | |
cm.setPathSpec("/api/v1/omgs") | |
var csh = new ConstraintSecurityHandler() | |
csh.setAuthenticator(new BasicAuthenticator()) | |
csh.setRealmName("myrealm") | |
csh.addConstraintMapping(cm) | |
csh.setLoginService(l) | |
return csh | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hi could you share "AkkaMistServlet" code?