Reputation: 637
I am working on an authentication filter for my REST service.
Can some one please explain why this name binding not works.
When I make a post request, I can receive the String "Tokenized", but log does not print "Inside the filter".
import java.io.IOException;
import java.lang.annotation.Retention;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.FormParam;
import javax.ws.rs.NameBinding;
import javax.ws.rs.Produces;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.TYPE;
import java.lang.annotation.Target;
import javax.annotation.Priority;
import javax.ws.rs.NotAuthorizedException;
import javax.ws.rs.Priorities;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerRequestFilter;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.ext.Provider;
import org.apache.log4j.Logger;
@Path("/authentication")
public class AuthenticationHandler {
final static Logger log = Logger.getLogger(AuthenticationHandler.class);
@NameBinding
@Retention(RUNTIME)
@Target({TYPE, METHOD})
public @interface Secured {
}
@Secured
@Provider
@Priority(Priorities.AUTHENTICATION)
public class AuthenticationFilter implements ContainerRequestFilter {
@Override
public void filter(ContainerRequestContext requestContext) throws IOException {
log.info("Inside the filter");
// Get the HTTP Authorization header from the request
String authorizationHeader
= requestContext.getHeaderString(HttpHeaders.AUTHORIZATION);
// Check if the HTTP Authorization header is present and formatted correctly
if (authorizationHeader == null || !authorizationHeader.startsWith("Bearer ")) {
throw new NotAuthorizedException("Authorization header must be provided");
}
// Extract the token from the HTTP Authorization header
String token = authorizationHeader.substring("Bearer".length()).trim();
try {
// Validate the token
validateToken(token);
} catch (Exception e) {
requestContext.abortWith(
Response.status(Response.Status.UNAUTHORIZED).build());
}
}
private void validateToken(String token) throws Exception {
// Check if it was issued by the server and if it's not expired
// Throw an Exception if the token is invalid
}
}
@POST
@Secured
@Path("/request_token")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public Response authenticateUser(@FormParam("username") String username,
@FormParam("password") String password) {
try {
// Authenticate the user using the credentials provided
authenticate(username, password);
// Issue a token for the user
String token = issueToken(username);
// Return the token on the response
return Response.ok(token).build();
} catch (Exception e) {
return Response.status(Response.Status.UNAUTHORIZED).build();
}
}
private boolean authenticate(String username, String password) throws Exception {
return true;
}
private String issueToken(String username) {
return "Tokenized";
}
}
Upvotes: 4
Views: 4259
Reputation: 637
Thanks for the tip peeskillet.
It is now working fine after creating separate classes for Name Bind and Filter. I'm posting the solution below if anyone required.
My problem now is, is there a way to keep this two classes in a separate package, because I tried by putting it on my Util package and it didn't work properly.
peeskillet : Thanks for the tip again.
AuthenticationFilter.java
import com.binosaurs.sf.backend.handler.Secured;
import com.binosaurs.sf.backend.util.*;
import java.io.IOException;
import javax.annotation.Priority;
import javax.ws.rs.NotAuthorizedException;
import javax.ws.rs.Priorities;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerRequestFilter;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.Response;
import javax.ws.rs.ext.Provider;
import org.apache.log4j.Logger;
@Secured
@Provider
@Priority(Priorities.AUTHENTICATION)
public class AuthenticationFilter implements ContainerRequestFilter {
// Get Log4j Logger
final static Logger log = Logger.getLogger(AuthenticationFilter.class);
@Override
public void filter(ContainerRequestContext requestContext) throws IOException {
log.info("Inside the filter");
// Get the HTTP Authorization header from the request
String authorizationHeader
= requestContext.getHeaderString(HttpHeaders.AUTHORIZATION);
// Check if the HTTP Authorization header is present and formatted correctly
if (authorizationHeader == null || !authorizationHeader.startsWith("Bearer ")) {
throw new NotAuthorizedException("Authorization header must be provided");
}
// Extract the token from the HTTP Authorization header
String token = authorizationHeader.substring("Bearer".length()).trim();
try {
// Validate the token
validateToken(token);
} catch (Exception e) {
requestContext.abortWith(
Response.status(Response.Status.UNAUTHORIZED).build());
}
}
private void validateToken(String token) throws Exception {
// Check if it was issued by the server and if it's not expired
// Throw an Exception if the token is invalid
}
}
Secured.java
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.binosaurs.sf.backend.handler;
import com.binosaurs.sf.backend.util.*;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.TYPE;
import java.lang.annotation.Retention;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Target;
import javax.ws.rs.NameBinding;
@NameBinding
@Retention(RUNTIME)
@Target({TYPE, METHOD})
public @interface Secured {
}
AuthenticationHandler.java
package com.binosaurs.sf.backend.handler;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.FormParam;
import javax.ws.rs.Produces;
import org.apache.log4j.Logger;
@Path("/authentication")
public class AuthenticationHandler {
final static Logger log = Logger.getLogger(AuthenticationHandler.class);
@POST
@Secured
@Path("/request_token")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public Response authenticateUser(@FormParam("username") String username,
@FormParam("password") String password) {
try {
// Authenticate the user using the credentials provided
authenticate(username, password);
// Issue a token for the user
String token = issueToken(username);
// Return the token on the response
return Response.ok(token).build();
} catch (Exception e) {
return Response.status(Response.Status.UNAUTHORIZED).build();
}
}
private boolean authenticate(String username, String password) throws Exception {
return true;
}
private String issueToken(String username) {
return "Tokenized";
}
}
Upvotes: 4