Every page for logged-in users starts the same way: find the user from the token, and answer 401 when there is none. Copying those lines into every route works until the day you forget them on one route, and that route is open to everybody. A guard method writes the check once, and one line puts it in front of any route.
The guard receives the route's own work as a lambda: a small function written in place, like user -> user. Its type, Function<Map<String, Object>, Object>, says it takes one value and gives back an answer, and view.apply(...) runs it. Here is a small guard that has nothing to do with logins: it prints the path of each request before running the route's work.
Object logCalls(HttpServletRequest request, Function<String, Object> view) {
String path = request.getRequestURI();
System.out.println("calling " + path);
return view.apply(path);
}
@GetMapping("/hello")
Object hello(HttpServletRequest request) {
return logCalls(request, path -> "Hello from " + path + "!");
}
Passing a lambda doesn't run it: only apply does, so the guard decides whether the route's work runs at all. A lambda can also use the variables around it, like a route's @PathVariable values, so one guard fits every route.
Ana (id 1) signs up and logs in first; <token> is the token that login answered:
POST /register {"email": "ana@example.com", "password": "secret123"} → 201 {"email": "ana@example.com", "id": 1}
POST /login {"email": "ana@example.com", "password": "secret123"} → 200 {"token": "<token>"}
GET /me Authorization: Bearer <token> → 200 {"email": "ana@example.com", "id": 1}
GET /me (no header) → 401 {"error": "Login required"}
GET /welcome Authorization: Bearer <token> → 200 Welcome back, ana@example.com!
GET /welcome (no header) → 401 {"error": "Login required"}
GET /welcome Authorization: Bearer 0123456789abcdef0123456789abcdef → 401 {"error": "Login required"}
Your task: below currentUser, write loginRequired(request, view): it answers 401 "Login required" when currentUser finds nobody, and otherwise runs the view with the user. Make /me return loginRequired with a view that gives back the user, and add a protected GET /welcome that answers the text Welcome back, <email>!.
Assignment
Follow the Coding Tutorial to write the loginRequired guard and protect /me and /welcome with it.
Hint
The check comes before view.apply(user): inside the if, the 401 returns early, so the view never runs without a user. Each route then needs one line, return loginRequired(request, …);, with its own lambda.
Free plan: 30 tutor messages. PRO is unlimited.
