Implement JWT, registration, login and comment posting

This is still a demo, to learn the framework. Most of this will probably we rewritten more elengantly.
This commit is contained in:
Bea 2021-08-03 17:55:45 +02:00
parent c0d8243016
commit 855bf817e1
12 changed files with 318 additions and 65 deletions

View File

@ -40,6 +40,11 @@
<artifactId>pippo-jetty</artifactId>
<version>1.13.1</version>
</dependency>
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.10.3</version>
</dependency>
</dependencies>
<build>

View File

@ -1,5 +1,6 @@
package net.mindoverflow.comments;
import net.mindoverflow.comments.webapp.WebServer;
import ro.pippo.core.Pippo;
public class CommentingServer

View File

@ -1,63 +0,0 @@
package net.mindoverflow.comments;
import ro.pippo.core.Application;
import ro.pippo.core.route.TrailingSlashHandler;
import java.awt.*;
import java.util.*;
public class WebServer extends Application
{
String username = "lollo";
String userpass = "password";
@Override
public void onInit()
{
POST("/login", routeContext -> {
System.out.println("POST");
String name = routeContext.getParameter("username").toString();
System.out.println(name);
String password = routeContext.getParameter("password").toString();
System.out.println(password);
Map<String, Object> model = new HashMap<>();
if(name.isEmpty())
{
model.put("errorMessage", "Empty username!");
}
else if (password.isEmpty())
{
model.put("errorMessage", "Empty password!");
}
else if(!name.equals(username) || !password.equals(userpass))
{
model.put("errorMessage", "Wrong username or password!");
}
else
{
model.put("errorMessage", "Logged in!");
}
routeContext.render("login", model);
});
GET("/login", routeContext ->
{
System.out.println("GET");
routeContext.render("login");
});
ANY("/.*", new TrailingSlashHandler(false)); // remove trailing slash
}
}

View File

@ -0,0 +1,30 @@
package net.mindoverflow.comments.utils;
import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import java.nio.charset.StandardCharsets;
import java.time.ZonedDateTime;
import java.util.Date;
public class SecurityUtil
{
public static final int JWT_EXPIRY_MINUTES = 60;
public static String generateJWT(String claimName, String claimValue, Date expiry)
{
Algorithm algorithm = Algorithm.HMAC256("minafewnf0928f392".getBytes(StandardCharsets.UTF_8));
return JWT.create()
.withIssuer("CommentingServer")
.withClaim(claimName, claimValue)
.withExpiresAt(expiry)
.sign(algorithm);
}
public static String generateJWT(String claimName, String claimValue)
{
Date expiry = Date.from(ZonedDateTime.now().plusMinutes(JWT_EXPIRY_MINUTES).toInstant());
return generateJWT(claimName, claimValue, expiry);
}
}

View File

@ -0,0 +1,28 @@
package net.mindoverflow.comments.webapp;
import net.mindoverflow.comments.webapp.controllers.CommentController;
import net.mindoverflow.comments.webapp.controllers.CommentsController;
import net.mindoverflow.comments.webapp.controllers.LoginController;
import net.mindoverflow.comments.webapp.controllers.RegisterController;
import ro.pippo.controller.ControllerApplication;
import ro.pippo.core.route.TrailingSlashHandler;
import java.util.HashMap;
public class WebServer extends ControllerApplication
{
public static final HashMap<String, String> userAndPassword = new HashMap<>();
public static final HashMap<String, String> jwtAndUser = new HashMap<>();
public static final HashMap<String, String> userAndComment = new HashMap<>();
@Override
public void onInit()
{
addControllers(new LoginController(), new RegisterController(), new CommentsController(), new CommentController());
ANY("/.*", new TrailingSlashHandler(false)); // remove trailing slash
}
}

View File

@ -0,0 +1,59 @@
package net.mindoverflow.comments.webapp.controllers;
import com.auth0.jwt.JWT;
import net.mindoverflow.comments.webapp.WebServer;
import ro.pippo.controller.Controller;
import ro.pippo.controller.GET;
import ro.pippo.controller.POST;
import ro.pippo.controller.Path;
import ro.pippo.controller.extractor.Param;
import javax.servlet.http.Cookie;
import java.util.HashMap;
import java.util.Map;
@Path("/comment")
public class CommentController extends Controller
{
@GET
public void getCommentPage()
{
Map<String, Object> model = new HashMap<>();
getRouteContext().render("comment", model);
}
@POST
public void addComment(@Param("comment") String comment, @Param("commentbtn") String commentbtn)
{
Cookie session = getRequest().getCookie("session");
if(session == null)
{
System.out.println("null cookie");
return;
}
String jwtFromCookie = session.getValue();
if(jwtFromCookie == null)
{
System.out.println("null jwt");
return;
}
String username = WebServer.jwtAndUser.get(jwtFromCookie);
if(username == null)
{
System.out.println("null user");
return;
}
// check if jwt is null, if saved in hashmap, and finally verify it with JWT.verify()
if(commentbtn != null)
{
WebServer.userAndComment.put(username, comment);
}
}
}

View File

@ -0,0 +1,31 @@
package net.mindoverflow.comments.webapp.controllers;
import net.mindoverflow.comments.webapp.WebServer;
import ro.pippo.controller.Controller;
import ro.pippo.controller.GET;
import ro.pippo.controller.Path;
import java.util.ArrayList;
import java.util.List;
@Path("/comments")
public class CommentsController extends Controller
{
@GET
public void getComments()
{
List<String> lines = new ArrayList<>();
lines.add("Comments:");
for(String user : WebServer.userAndComment.keySet())
{
String comment = WebServer.userAndComment.get(user);
if(comment != null) lines.add(user + ": " + comment);
}
getRouteContext().text().send(lines);
}
}

View File

@ -0,0 +1,75 @@
package net.mindoverflow.comments.webapp.controllers;
import net.mindoverflow.comments.utils.SecurityUtil;
import net.mindoverflow.comments.webapp.WebServer;
import ro.pippo.controller.Controller;
import ro.pippo.controller.GET;
import ro.pippo.controller.POST;
import ro.pippo.controller.Path;
import ro.pippo.controller.extractor.Param;
import java.util.HashMap;
import java.util.Map;
@Path("/login")
public class LoginController extends Controller
{
@GET
public void getLogin()
{
getRouteContext().render("login");
}
@POST
public void handleLogin(
@Param("loginbtn") String loginbtn,
@Param("username") String username,
@Param("password") String password)
{
Map<String, Object> model = new HashMap<>();
if(username == null || username.isEmpty())
{
model.put("message", "Empty username!");
}
else if (password == null || password.isEmpty())
{
model.put("message", "Empty password!");
} else if(loginbtn != null)
{
System.out.println(loginbtn);
if(!WebServer.userAndPassword.containsKey(username))
{
model.put("message", "Unknown user!");
}
else
{
String gottenPass = WebServer.userAndPassword.get(username);
if(!gottenPass.equals(password))
{
model.put("message", "Wrong password!");
}
else
{
model.put("message", "Valid data!");
// generate JWT
String jwt = SecurityUtil.generateJWT("username", username);
// set JWT as cookie
getResponse().cookie("session", jwt, SecurityUtil.JWT_EXPIRY_MINUTES * 60 /* in seconds */);
// store JWT in RAM
WebServer.jwtAndUser.put(jwt, username);
}
}
}
System.out.println("User: " + username);
System.out.println("Pass: " + password);
getRouteContext().render("login", model);
}
}

View File

@ -0,0 +1,61 @@
package net.mindoverflow.comments.webapp.controllers;
import net.mindoverflow.comments.webapp.WebServer;
import ro.pippo.controller.Controller;
import ro.pippo.controller.GET;
import ro.pippo.controller.POST;
import ro.pippo.controller.Path;
import ro.pippo.controller.extractor.Param;
import java.util.HashMap;
import java.util.Map;
@Path("/register")
public class RegisterController extends Controller
{
@GET
public void getLogin()
{
getRouteContext().render("register");
}
@POST
public void handleLogin(
@Param("registerbtn") String registerbtn,
@Param("username") String username,
@Param("password") String password)
{
Map<String, Object> model = new HashMap<>();
if(username == null || username.isEmpty())
{
model.put("message", "Empty username!");
}
else if (password == null || password.isEmpty())
{
model.put("message", "Empty password!");
}
else if(registerbtn != null)
{
System.out.println(registerbtn);
if(WebServer.userAndPassword.containsKey(username))
{
model.put("message", "User already exists!");
}
else
{
WebServer.userAndPassword.put(username, password);
model.put("message", "User created!");
}
}
System.out.println("User: " + username);
System.out.println("Pass: " + password);
getRouteContext().render("register", model);
}
}

View File

@ -0,0 +1,12 @@
<htmml>
<head>
<title>Send Comment</title>
</head>
<body>
<h1>Send Comment</h1>
<form accept-charset="UTF-8" role="form" method="post" action="/comment">
<input placeholder="Comment" name="comment">
<input class="btn btn-success btn-block" type="submit" name="commentbtn" value="Comment">
</form>
</body>
</htmml>

View File

@ -4,11 +4,11 @@
</head>
<body>
<h1>Login Form</h1>
<div><#if errorMessage??>${errorMessage}</#if></div>
<div><#if message??>${message}</#if></div>
<form accept-charset="UTF-8" role="form" method="post" action="/login">
<input placeholder="Username" name="username">
<input placeholder="Password" name="password" type="password">
<input class="btn btn-success btn-block" type="submit" value="Login">
<input class="btn btn-success btn-block" type="submit" name="loginbtn" value="Login">
</form>
</body>
</html>

View File

@ -0,0 +1,14 @@
<html>
<head>
<title>Register</title>
</head>
<body>
<h1>Registration Form</h1>
<div><#if message??>${message}</#if></div>
<form accept-charset="UTF-8" role="form" method="post" action="/register">
<input placeholder="Username" name="username">
<input placeholder="Password" name="password" type="password">
<input class="btn btn-success btn-block" type="submit" name="registerbtn" value="Register">
</form>
</body>
</html>