scala import javax.crypto.Mac import javax.crypto.spec.SecretKeySpec import org.apache.commons.codec.binary.Base64 class Authenticator(secretKey: String) { private val algorithm = "HmacSHA256" def generateToken(username: String): String = { val key = new SecretKeySpec(secretKey.getBytes, algorithm) val mac = Mac.getInstance(algorithm) mac.init(key) val signature = Base64.encodeBase64URLSafeString(mac.doFinal(username.getBytes)) s"$username:$signature" } def validateToken(token: String): Boolean = { val Array(username, signature) = token.split(":") val key = new SecretKeySpec(secretKey.getBytes, algorithm) val mac = Mac.getInstance(algorithm) mac.init(key) val calculatedSignature = Base64.encodeBase64URLSafeString(mac.doFinal(username.getBytes)) calculatedSignature == signature } } scala import org.scalatra.auth.{ScentryConfig, ScentrySupport} import org.scalatra.{ScalatraBase, ScentryStrategy} import org.slf4j.LoggerFactory trait AuthenticationSupport extends ScalatraBase with ScentrySupport[User] { protected val logger = LoggerFactory.getLogger(getClass) protected def scentryConfig = new ScentryConfig {}.asInstanceOf[ScentryConfiguration] protected def fromSession = { case id: String => User(id) } protected def toSession = { case user: User => user.id } protected val authenticator = new Authenticator("secretKey") protected def requireAuth(): Unit = { if (!isAuthenticated) { redirect("/login") } } override def authenticate()(implicit request: HttpServletRequest, response: HttpServletResponse): Option[User] = { val token = request.getHeader("Authorization") if (token != null && authenticator.validateToken(token)) { val Array(username, _) = token.split(":") Some(User(username)) } else { None } } override protected def registerAuthStrategies: Unit = { scentry.register("Token", app => new TokenAuthenticationStrategy(app, authenticator)) } override protected def configureScentry() = { scentry.unauthenticated { scentry.strategies("Token").unauthenticated() } } } case class User(id: String) scala trait AuthorizationSupport extends ScalatraBase { self: AuthenticationSupport => before() { requireAuth() } get("/adminOnly") { requireRole("admin") } def requireRole(role: String): Unit = { if (userRoles.get(user.id).contains(role)) { pass() } else { } } private val userRoles: Map[String, List[String]] = Map( "admin" -> List("admin"), "user" -> List("user") ) } sbt libraryDependencies += "org.scalatra" %% "scalatra" % "2.7.1" libraryDependencies += "org.scalatra" %% "scalatra-auth" % "2.7.1" libraryDependencies += "org.scalatra" %% "scalatra-json" % "2.7.1" libraryDependencies += "org.json4s" %% "json4s-jackson" % "4.0.3" scala import org.scalatra.json.JacksonJsonSupport import org.scalatra.{ScalatraServlet, BaseScalatraServlet} import org.json4s.DefaultFormats import org.scalatra.auth.{LoginSupport, ScentrySupport} class MyApiServlet extends ScalatraServlet with JacksonJsonSupport with AuthenticationSupport with AuthorizationSupport { protected implicit val jsonFormats = DefaultFormats post("/login") { val username = params("username") val password = params("password") val user = authenticateUser(username, password) if (user.nonEmpty) { val token = authenticator.generateToken(user.get.id) Ok(token) } else { } } }


上一篇:
下一篇:
切换中文