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:
parent
c0d8243016
commit
855bf817e1
5
pom.xml
5
pom.xml
@ -40,6 +40,11 @@
|
|||||||
<artifactId>pippo-jetty</artifactId>
|
<artifactId>pippo-jetty</artifactId>
|
||||||
<version>1.13.1</version>
|
<version>1.13.1</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.auth0</groupId>
|
||||||
|
<artifactId>java-jwt</artifactId>
|
||||||
|
<version>3.10.3</version>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package net.mindoverflow.comments;
|
package net.mindoverflow.comments;
|
||||||
|
|
||||||
|
import net.mindoverflow.comments.webapp.WebServer;
|
||||||
import ro.pippo.core.Pippo;
|
import ro.pippo.core.Pippo;
|
||||||
|
|
||||||
public class CommentingServer
|
public class CommentingServer
|
||||||
|
@ -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
|
|
||||||
}
|
|
||||||
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
@ -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
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
12
src/main/resources/templates/comment.ftl
Normal file
12
src/main/resources/templates/comment.ftl
Normal 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>
|
@ -4,11 +4,11 @@
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<h1>Login Form</h1>
|
<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">
|
<form accept-charset="UTF-8" role="form" method="post" action="/login">
|
||||||
<input placeholder="Username" name="username">
|
<input placeholder="Username" name="username">
|
||||||
<input placeholder="Password" name="password" type="password">
|
<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>
|
</form>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
14
src/main/resources/templates/register.ftl
Normal file
14
src/main/resources/templates/register.ftl
Normal 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>
|
Loading…
Reference in New Issue
Block a user