diff --git a/queries/sample-requests.rest b/queries/sample-requests.rest index ad3082fd5dec0b7aec7142b401c088a48d5bff47..bfbf655972055a7acf1cd1aeed2d4a0e14c82c6a 100644 --- a/queries/sample-requests.rest +++ b/queries/sample-requests.rest @@ -41,6 +41,10 @@ Content-type: application/json GET http://localhost:9998/myapp/biblio/auteurs/1000 Accept: application/json +### If a resource doesn't exist an exception is raised, and the 404 http status code is returned +GET http://localhost:9998/myapp/biblio/auteurs/1000 +Accept: text/xml + ### Filter resources with query parameters : GET http://localhost:9998/myapp/biblio/auteurs/filter?nom=Durand&prenomā¼Marie Accept: application/json @@ -58,6 +62,11 @@ GET http://localhost:9998/myapp/biblio/auteurs/page?pageSize=10&page=3 Accept: application/json sortKey: prenom +### Returns the context of the query (without authentication). +GET http://localhost:9998/myapp/biblio/context +biblio-demo-header-1: myvalue +biblio-demo-header-2: anothervalue + ### Authorization by token, part 1. Retrieve and save token with Basic Authentication # TOKEN=$(curl -v --user "john.doe@nowhere.com:admin" "http://localhost:9998/myapp/biblio/login") GET http://localhost:9998/myapp/biblio/login @@ -88,4 +97,5 @@ Authorization: Bearer {{auth_token}} ### Authorization by token, part 2. Use token to authorize. Admin KO. GET http://localhost:9998/myapp/biblio/secured/admin -Authorization: Bearer {{auth_token}} \ No newline at end of file +Authorization: Bearer {{auth_token}} + diff --git a/src/main/java/fr/univtln/bruno/samples/jaxrs/client/BiblioClient.java b/src/main/java/fr/univtln/bruno/samples/jaxrs/client/BiblioClient.java index 4ed40ebd2d73ab60a8767815f570a1c2a2ff90f8..6bdaf72af1ebd4695329856ba219b142083f171f 100644 --- a/src/main/java/fr/univtln/bruno/samples/jaxrs/client/BiblioClient.java +++ b/src/main/java/fr/univtln/bruno/samples/jaxrs/client/BiblioClient.java @@ -35,7 +35,7 @@ public class BiblioClient { .get(Auteur.class); log.info(auteur.toString()); - //Log in to get the token + //Log in to get the token with basci authentication String email = "john.doe@nowhere.com"; String password = "admin"; String token = webResource.path("biblio/login") diff --git a/src/main/java/fr/univtln/bruno/samples/jaxrs/exceptions/BusinessException.java b/src/main/java/fr/univtln/bruno/samples/jaxrs/exceptions/BusinessException.java index ed7138b016b48f1ddd03e93ae8515bc772395bf8..a0020b2a73f52bd38baa8febc6c0b5e324bb8ee0 100644 --- a/src/main/java/fr/univtln/bruno/samples/jaxrs/exceptions/BusinessException.java +++ b/src/main/java/fr/univtln/bruno/samples/jaxrs/exceptions/BusinessException.java @@ -1,12 +1,32 @@ package fr.univtln.bruno.samples.jaxrs.exceptions; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; import jakarta.ws.rs.core.Response; +import jakarta.xml.bind.annotation.XmlRootElement; import lombok.Getter; +import java.io.Serializable; + +/** + * The type Business exception, used add HTTP (HATEOS) capacities to exceptions. + */ @Getter -public class BusinessException extends Exception { - final Response.Status status; +@JsonIgnoreProperties({"stackTrace"}) +@JsonInclude(JsonInclude.Include.NON_EMPTY) + +@XmlRootElement +public class BusinessException extends Exception implements Serializable { + /** + * The Status. + */ + Response.Status status; + /** + * Instantiates a new Business exception. + * + * @param status the status + */ public BusinessException(Response.Status status) { super(status.getReasonPhrase()); this.status = status; diff --git a/src/main/java/fr/univtln/bruno/samples/jaxrs/exceptions/IllegalArgumentException.java b/src/main/java/fr/univtln/bruno/samples/jaxrs/exceptions/IllegalArgumentException.java index 7a8e69d1bb7286cfb36119731c6b9838e7aabb9e..deae099b7181c328ecf1bdccf0857166e424c4f5 100644 --- a/src/main/java/fr/univtln/bruno/samples/jaxrs/exceptions/IllegalArgumentException.java +++ b/src/main/java/fr/univtln/bruno/samples/jaxrs/exceptions/IllegalArgumentException.java @@ -1,6 +1,6 @@ package fr.univtln.bruno.samples.jaxrs.exceptions; -import static jakarta.ws.rs.core.Response.*; +import static jakarta.ws.rs.core.Response.Status; public class IllegalArgumentException extends BusinessException { public IllegalArgumentException() { diff --git a/src/main/java/fr/univtln/bruno/samples/jaxrs/exceptions/NotFoundException.java b/src/main/java/fr/univtln/bruno/samples/jaxrs/exceptions/NotFoundException.java index 64f65a1fd75ebcf230ae4bbc71f3da0eca79fd1d..f28fc2544258ebce1852ec5dbcf668989ae01892 100644 --- a/src/main/java/fr/univtln/bruno/samples/jaxrs/exceptions/NotFoundException.java +++ b/src/main/java/fr/univtln/bruno/samples/jaxrs/exceptions/NotFoundException.java @@ -1,7 +1,9 @@ package fr.univtln.bruno.samples.jaxrs.exceptions; import jakarta.ws.rs.core.Response; +import jakarta.xml.bind.annotation.XmlRootElement; +@XmlRootElement public class NotFoundException extends BusinessException { public NotFoundException() { super(Response.Status.NOT_FOUND); diff --git a/src/main/java/fr/univtln/bruno/samples/jaxrs/mappers/BusinessExceptionMapper.java b/src/main/java/fr/univtln/bruno/samples/jaxrs/mappers/BusinessExceptionMapper.java index 8ddb6787412b73453c99851ae21b9fe9500c0691..eacbcd5dddfec20d50ad2206554d425363a7b973 100755 --- a/src/main/java/fr/univtln/bruno/samples/jaxrs/mappers/BusinessExceptionMapper.java +++ b/src/main/java/fr/univtln/bruno/samples/jaxrs/mappers/BusinessExceptionMapper.java @@ -1,22 +1,24 @@ package fr.univtln.bruno.samples.jaxrs.mappers; import fr.univtln.bruno.samples.jaxrs.exceptions.BusinessException; +import jakarta.ws.rs.core.Context; +import jakarta.ws.rs.core.HttpHeaders; import jakarta.ws.rs.core.MediaType; import jakarta.ws.rs.core.Response; import jakarta.ws.rs.ext.ExceptionMapper; import jakarta.ws.rs.ext.Provider; import lombok.AccessLevel; import lombok.experimental.FieldDefaults; +import lombok.extern.java.Log; @SuppressWarnings("unused") @Provider @FieldDefaults(level = AccessLevel.PRIVATE) +@Log public class BusinessExceptionMapper implements ExceptionMapper<BusinessException> { - public Response toResponse(BusinessException ex) { return Response.status(ex.getStatus()) - .entity(ex.getMessage()) - .type(MediaType.APPLICATION_JSON) + .entity(ex) .build(); } } diff --git a/src/main/java/fr/univtln/bruno/samples/jaxrs/mappers/GenericExceptionMapper.java b/src/main/java/fr/univtln/bruno/samples/jaxrs/mappers/GenericExceptionMapper.java index 6902906eb8f458dba24a1d4034470eee5e4bb148..554394ad53ee603c1dc9867a5914e7cc077b3c7a 100755 --- a/src/main/java/fr/univtln/bruno/samples/jaxrs/mappers/GenericExceptionMapper.java +++ b/src/main/java/fr/univtln/bruno/samples/jaxrs/mappers/GenericExceptionMapper.java @@ -6,10 +6,12 @@ import jakarta.ws.rs.ext.ExceptionMapper; import jakarta.ws.rs.ext.Provider; import lombok.AccessLevel; import lombok.experimental.FieldDefaults; +import lombok.extern.java.Log; @SuppressWarnings("unused") @Provider @FieldDefaults(level = AccessLevel.PRIVATE) +@Log public class GenericExceptionMapper implements ExceptionMapper<Exception> { public Response toResponse(Exception ex) { return Response.status(Response.Status.INTERNAL_SERVER_ERROR) diff --git a/src/main/java/fr/univtln/bruno/samples/jaxrs/model/BiblioModel.java b/src/main/java/fr/univtln/bruno/samples/jaxrs/model/BiblioModel.java index 5df3f2b3e0112414adb71a74bf3e10a9ddd48b8b..ff787698d1e8fa944a70ac3e659936b5bf855078 100644 --- a/src/main/java/fr/univtln/bruno/samples/jaxrs/model/BiblioModel.java +++ b/src/main/java/fr/univtln/bruno/samples/jaxrs/model/BiblioModel.java @@ -8,7 +8,6 @@ import jakarta.xml.bind.annotation.XmlAccessorType; import jakarta.xml.bind.annotation.XmlAttribute; import jakarta.xml.bind.annotation.XmlRootElement; import lombok.*; -import lombok.experimental.Delegate; import lombok.experimental.FieldDefaults; import lombok.extern.java.Log; import org.eclipse.collections.api.map.primitive.MutableLongObjectMap; @@ -26,18 +25,15 @@ import static fr.univtln.bruno.samples.jaxrs.model.BiblioModel.Field.valueOf; /** - * The type Biblio model. + * The type Biblio model. A in memory instance of a Library model. Kind of a mock. */ @Log @Getter @FieldDefaults(level = AccessLevel.PRIVATE) @NoArgsConstructor(staticName = "of") public class BiblioModel { - public enum Field {NOM, PRENOM, BIOGRAPHIE} - private static final AtomicLong lastId = new AtomicLong(0); - - @Delegate + //@Delegate final MutableLongObjectMap<Auteur> auteurs = LongObjectMaps.mutable.empty(); /** @@ -55,7 +51,7 @@ public class BiblioModel { } /** - * Update auteur auteur. + * Update auteur auteur by id and data contains in a author instance (except the id). * * @param id the id * @param auteur the auteur @@ -72,7 +68,7 @@ public class BiblioModel { } /** - * Remove auteur. + * Remove one auteur by id. * * @param id the id * @throws NotFoundException the not found exception @@ -83,7 +79,7 @@ public class BiblioModel { } /** - * Gets auteur. + * Gets one auteur id. * * @param id the id * @return the auteur @@ -95,7 +91,7 @@ public class BiblioModel { } /** - * Gets auteur size. + * Gets the number of authors. * * @return the auteur size */ @@ -103,7 +99,6 @@ public class BiblioModel { return auteurs.size(); } - /** * Returns a sorted, filtered and paginated list of authors. * @@ -120,11 +115,11 @@ public class BiblioModel { })); //The add filters according to parameters - if (paginationInfo.getNom()!=null) + if (paginationInfo.getNom() != null) auteurStream = auteurStream.filter(auteur -> auteur.getNom().equalsIgnoreCase(paginationInfo.getNom())); - if (paginationInfo.getPrenom()!=null) + if (paginationInfo.getPrenom() != null) auteurStream = auteurStream.filter(auteur -> auteur.getPrenom().equalsIgnoreCase(paginationInfo.getPrenom())); - if (paginationInfo.getBiographie()!=null) + if (paginationInfo.getBiographie() != null) auteurStream = auteurStream.filter(auteur -> auteur.getBiographie().contains(paginationInfo.getBiographie())); //Finally add pagination instructions. @@ -137,13 +132,31 @@ public class BiblioModel { return auteurStream.collect(Collectors.toList()); } + /** + * Removes all authors. + */ public void supprimerAuteurs() { auteurs.clear(); lastId.set(0); } /** - * The type Auteur. + * The list of fields of author that can used in filters. + */ + public enum Field { + NOM, + /** + * Prenom field. + */ + PRENOM, + /** + * Biographie field. + */ + BIOGRAPHIE + } + + /** + * The type Author. */ @Builder @Getter diff --git a/src/main/java/fr/univtln/bruno/samples/jaxrs/resources/BiblioResource.java b/src/main/java/fr/univtln/bruno/samples/jaxrs/resources/BiblioResource.java index a1fef79cd22cfdba3227dfe3b9911c27ad95a97c..8cafd62722b53e0a344f08d651dc57478c7e933b 100644 --- a/src/main/java/fr/univtln/bruno/samples/jaxrs/resources/BiblioResource.java +++ b/src/main/java/fr/univtln/bruno/samples/jaxrs/resources/BiblioResource.java @@ -5,10 +5,10 @@ import fr.univtln.bruno.samples.jaxrs.exceptions.IllegalArgumentException; import fr.univtln.bruno.samples.jaxrs.exceptions.NotFoundException; import fr.univtln.bruno.samples.jaxrs.model.BiblioModel; import fr.univtln.bruno.samples.jaxrs.model.BiblioModel.Auteur; +import fr.univtln.bruno.samples.jaxrs.security.InMemoryLoginModule; +import fr.univtln.bruno.samples.jaxrs.security.User; import fr.univtln.bruno.samples.jaxrs.security.annotations.BasicAuth; import fr.univtln.bruno.samples.jaxrs.security.annotations.JWTAuth; -import fr.univtln.bruno.samples.jaxrs.security.User; -import fr.univtln.bruno.samples.jaxrs.security.InMemoryLoginModule; import fr.univtln.bruno.samples.jaxrs.status.Status; import io.jsonwebtoken.Jwts; import jakarta.annotation.security.RolesAllowed; @@ -25,15 +25,26 @@ import java.util.Collection; import java.util.Date; import java.util.List; +/** + * The Biblio resource. + * A demo JAXRS class, that manages authors and offers a secured access. + */ @Log // The Java class will be hosted at the URI path "/biblio" @Path("biblio") @Produces({MediaType.APPLICATION_JSON, MediaType.TEXT_XML}) public class BiblioResource { + //A in memory instance of a Library model. Kind of a mock. private static final BiblioModel modeleBibliotheque = BiblioModel.of(); + //A random number generator private static final SecureRandom random = new SecureRandom(); + /** + * The simpliest method that just return "hello" in plain text with GET on the default path "biblio". + * + * @return the string + */ @SuppressWarnings("SameReturnValue") @GET @Produces(MediaType.TEXT_PLAIN) @@ -41,6 +52,12 @@ public class BiblioResource { return "hello"; } + /** + * An init method that add two authors with a PUT on the default path. + * + * @return the number of generated authors. + * @throws IllegalArgumentException the illegal argument exception + */ @PUT @Path("init") public int init() throws IllegalArgumentException { @@ -50,6 +67,15 @@ public class BiblioResource { return modeleBibliotheque.getAuteurSize(); } + /** + * An init method that add a given number of random authors whose names are just random letters on PUT. + * The number of authors if given in the path avec bound to the name size. The needed format (an integer) is checked with a regular expression [0-9]+ + * The parameter is injected with @PathParam + * + * @param size the number of authors to add + * @return the int number of generated authors. + * @throws IllegalArgumentException the illegal argument exception + */ @PUT @Path("init/{size:[0-9]+}") public int init(@PathParam("size") int size) throws IllegalArgumentException { @@ -62,17 +88,30 @@ public class BiblioResource { return modeleBibliotheque.getAuteurSize(); } + /** + * A random string generator + * + * @param targetStringLength the length of the String + * @return + */ private String randomString(int targetStringLength) { int letterA = 97; int letterZ = 122; - - return random.ints(letterA, letterZ + 1) .limit(targetStringLength) .collect(StringBuilder::new, StringBuilder::appendCodePoint, StringBuilder::append) .toString(); } + /** + * Update an author with an given id. + * + * @param id the id injected from the path param "id" + * @param auteur a injected author made from the JSON data (@Consumes) from body of the request. This author is forbidden to havce an Id. + * @return The resulting author with its id. + * @throws NotFoundException is returned if no author has the "id". + * @throws IllegalArgumentException is returned if an "id" is also given in the request body. + */ @PUT @Path("auteurs/{id}") @Consumes(MediaType.APPLICATION_JSON) @@ -81,6 +120,7 @@ public class BiblioResource { } /** + * Adds an new author to the data. * Status annotation is a trick to fine tune 2XX status codes (see the status package). * * @param auteur The author to be added without its id. @@ -95,30 +135,61 @@ public class BiblioResource { return modeleBibliotheque.addAuteur(auteur); } + /** + * Removes an author by id from the data. + * + * @param id the id of the author to remove + * @throws NotFoundException is returned if no author has the "id". + */ @DELETE @Path("auteurs/{id}") public void supprimerAuteur(@PathParam("id") final long id) throws NotFoundException { modeleBibliotheque.removeAuteur(id); } + /** + * Removes every authors + */ @DELETE @Path("auteurs") public void supprimerAuteurs() { modeleBibliotheque.supprimerAuteurs(); } + /** + * Find and return an author by id with a GET on the path "biblio/auteurs/{id}" where {id} is the needed id. + * The path parameter "id" is injected with @PathParam. + * + * @param id the needed author id. + * @return the auteur with id. + * @throws NotFoundException is returned if no author has the "id". + */ @GET @Path("auteurs/{id}") public Auteur getAuteur(@PathParam("id") final long id) throws NotFoundException { return modeleBibliotheque.getAuteur(id); } + /** + * Gets auteurs. + * + * @return the auteurs + */ @GET @Path("auteurs") public Collection<Auteur> getAuteurs() { return modeleBibliotheque.getAuteurs().values(); } + /** + * Gets a list of "filtered" authors. + * + * @param nom an optional exact filter on the name. + * @param prenom an optional exact filter on the firstname. + * @param biographie an optional contains filter on the biography. + * @param sortKey the sort key (prenom or nom). + * @return the filtered auteurs + */ @GET @Path("auteurs/filter") public List<Auteur> getFilteredAuteurs(@QueryParam("nom") String nom, @@ -135,23 +206,50 @@ public class BiblioResource { return modeleBibliotheque.getWithFilter(paginationInfo); } + /** + * Gets a page of authors after applying a sort. + * + * @param paginationInfo the pagination info represented as a class injected with @BeanParam. + * @return the page of authors. + */ @GET @Path("auteurs/page") public List<Auteur> getAuteursPage(@BeanParam PaginationInfo paginationInfo) { return modeleBibliotheque.getWithFilter(paginationInfo); } + /** + * A GET method to access the context of the request : The URI, the HTTP headers, the request and the security context (needs authentication see below). + * + * @param uriInfo the uri info + * @param httpHeaders the http headers + * @param request the request + * @param securityContext the security context + * @return A string representation of the available data. + */ @GET @Path("context") - @RolesAllowed("ADMIN") public String getContext(@Context UriInfo uriInfo, @Context HttpHeaders httpHeaders, @Context Request request, @Context SecurityContext securityContext) { - return "UriInfo: (" + uriInfo.getRequestUri().toString() - + ")\n HttpHeaders(" + httpHeaders.getRequestHeaders().toString() - + ")\n SecurityContext(Auth.scheme: [" + securityContext.getAuthenticationScheme() - + "] user: [" + securityContext.getUserPrincipal().getName() - + "] secured: [" + securityContext.isSecure() + "] )"; + String result = "UriInfo: (" + uriInfo.getRequestUri().toString() + ")\n" + + "Method: ("+request.getMethod()+")\n" + + "HttpHeaders(" + httpHeaders.getRequestHeaders().toString() + ")\n"; + + if (securityContext != null) { + result += " SecurityContext(Auth.scheme: [" + securityContext.getAuthenticationScheme() + "] \n"; + if (securityContext.getUserPrincipal() != null) + result += " user: [" + securityContext.getUserPrincipal().getName() + "] \n"; + result += " secured: [" + securityContext.isSecure() + "] )"; + } + return result; } + /** + * A GET restricted to ADMIN role with basic authentication. + * @see fr.univtln.bruno.samples.jaxrs.security.filter.BasicAuthenticationFilter + * + * @param securityContext the security context + * @return the restricted to admins + */ @GET @Path("adminsonly") @RolesAllowed("ADMIN") @@ -160,6 +258,13 @@ public class BiblioResource { return "secret for admins !" + securityContext.getUserPrincipal().getName(); } + /** + * A GET restricted to USER role with basic authentication (and not ADMIN !). + * @see fr.univtln.bruno.samples.jaxrs.security.filter.BasicAuthenticationFilter + * + * @param securityContext the security context + * @return the restricted to users + */ @GET @Path("usersonly") @RolesAllowed("USER") @@ -168,6 +273,13 @@ public class BiblioResource { return "secret for users ! to " + securityContext.getUserPrincipal().getName(); } + /** + * A GET restricted to USER & ADMIN roles, secured with a JWT Token. + * @see fr.univtln.bruno.samples.jaxrs.security.filter.JsonWebTokenFilter + * + * @param securityContext the security context + * @return the string + */ @GET @Path("secured") @RolesAllowed({"USER", "ADMIN"}) @@ -178,6 +290,12 @@ public class BiblioResource { return "Access with JWT ok for " + securityContext.getUserPrincipal().getName(); } + /** + * A GET restricted to ADMIN roles, secured with a JWT Token. + * + * @param securityContext the security context + * @return the string + */ @GET @Path("secured/admin") @RolesAllowed({"ADMIN"}) @@ -188,6 +306,12 @@ public class BiblioResource { return "Access with JWT ok for " + securityContext.getUserPrincipal().getName(); } + /** + * a GET method to obtain a JWT token with basic authentication for USER and ADMIN roles. + * + * @param securityContext the security context + * @return the base64 encoded JWT Token. + */ @GET @Path("login") @RolesAllowed({"USER", "ADMIN"}) diff --git a/src/main/java/fr/univtln/bruno/samples/jaxrs/resources/PaginationInfo.java b/src/main/java/fr/univtln/bruno/samples/jaxrs/resources/PaginationInfo.java index 40801ab75d644aebdf5a9f1a93a12ec7b613931f..bc9c399dccbe71390b404529edbe4d86edbba419 100644 --- a/src/main/java/fr/univtln/bruno/samples/jaxrs/resources/PaginationInfo.java +++ b/src/main/java/fr/univtln/bruno/samples/jaxrs/resources/PaginationInfo.java @@ -6,6 +6,10 @@ import jakarta.ws.rs.QueryParam; import lombok.*; import lombok.experimental.FieldDefaults; +/** + * The Pagination information to be injected with @BeanPararm Filter Queries. + * Each field is annotated with a JAX-RS parameter injection. + */ @FieldDefaults(level = AccessLevel.PRIVATE) @Getter @ToString diff --git a/src/main/java/fr/univtln/bruno/samples/jaxrs/security/InMemoryLoginModule.java b/src/main/java/fr/univtln/bruno/samples/jaxrs/security/InMemoryLoginModule.java index 6ba281c3b92b05fc470ad098fe575ea4dbee4468..6245c8bd9bf73e31dae4c22c6a515006692d5e97 100644 --- a/src/main/java/fr/univtln/bruno/samples/jaxrs/security/InMemoryLoginModule.java +++ b/src/main/java/fr/univtln/bruno/samples/jaxrs/security/InMemoryLoginModule.java @@ -13,7 +13,8 @@ import java.security.spec.InvalidKeySpecException; import java.util.*; /** - * The type User database. + * this class model a simple in memory role based authentication database (RBAC). + * Password are salted and hashed. */ @Log @ToString diff --git a/src/main/java/fr/univtln/bruno/samples/jaxrs/security/MySecurityContext.java b/src/main/java/fr/univtln/bruno/samples/jaxrs/security/MySecurityContext.java index 300894cb462197ec35c6d3f84078ec0571280fdd..1ab16f818c33ef4d37e0317160dfdd3929bb9fbc 100644 --- a/src/main/java/fr/univtln/bruno/samples/jaxrs/security/MySecurityContext.java +++ b/src/main/java/fr/univtln/bruno/samples/jaxrs/security/MySecurityContext.java @@ -7,27 +7,37 @@ import lombok.experimental.FieldDefaults; import java.security.Principal; +/** + * This class define a specific security context after an authentication with either the basic or the JWT filters. + * + * @see fr.univtln.bruno.samples.jaxrs.security.filter.BasicAuthenticationFilter + * @see fr.univtln.bruno.samples.jaxrs.security.filter.JsonWebTokenFilter + */ @FieldDefaults(level = AccessLevel.PRIVATE) @AllArgsConstructor(staticName = "newInstance") public class MySecurityContext implements SecurityContext { private final String authenticationScheme; private final String username; + //the authenticated user @Override public Principal getUserPrincipal() { return InMemoryLoginModule.USER_DATABASE.getUser(username); } + //A method to check if a user belongs to a role @Override public boolean isUserInRole(String role) { return InMemoryLoginModule.USER_DATABASE.getUserRoles(username).contains(InMemoryLoginModule.Role.valueOf(role)); } + //Say the access has been secured @Override public boolean isSecure() { return true; } + //The authentication scheme (Basic, JWT, ...) that has been used. @Override public String getAuthenticationScheme() { return authenticationScheme; diff --git a/src/main/java/fr/univtln/bruno/samples/jaxrs/security/annotations/BasicAuth.java b/src/main/java/fr/univtln/bruno/samples/jaxrs/security/annotations/BasicAuth.java index d61e29aec135533a41da0aff596d348e381e455e..f09c007d5d6f86a0c9881997be131835f43f599c 100644 --- a/src/main/java/fr/univtln/bruno/samples/jaxrs/security/annotations/BasicAuth.java +++ b/src/main/java/fr/univtln/bruno/samples/jaxrs/security/annotations/BasicAuth.java @@ -9,6 +9,10 @@ import static java.lang.annotation.ElementType.METHOD; import static java.lang.annotation.ElementType.TYPE; import static java.lang.annotation.RetentionPolicy.RUNTIME; +/** + * A annotation for method to be secured with Basic Auth + * @see fr.univtln.bruno.samples.jaxrs.security.filter.BasicAuthenticationFilter + */ @NameBinding @Retention(RUNTIME) @Target({TYPE, METHOD}) diff --git a/src/main/java/fr/univtln/bruno/samples/jaxrs/security/annotations/JWTAuth.java b/src/main/java/fr/univtln/bruno/samples/jaxrs/security/annotations/JWTAuth.java index ed69c43ef952d063180796e86d3dd2322cbf4870..d7834fcb1b341ebe37d09d72a2f66cb5599ac77d 100644 --- a/src/main/java/fr/univtln/bruno/samples/jaxrs/security/annotations/JWTAuth.java +++ b/src/main/java/fr/univtln/bruno/samples/jaxrs/security/annotations/JWTAuth.java @@ -9,6 +9,10 @@ import static java.lang.annotation.ElementType.METHOD; import static java.lang.annotation.ElementType.TYPE; import static java.lang.annotation.RetentionPolicy.RUNTIME; +/** + * A annotation for method to be secured with Java Web Token (JWT) + * @see fr.univtln.bruno.samples.jaxrs.security.filter.JsonWebTokenFilter + */ @NameBinding @Retention(RUNTIME) @Target({TYPE, METHOD}) diff --git a/src/main/java/fr/univtln/bruno/samples/jaxrs/security/filter/BasicAuthenticationFilter.java b/src/main/java/fr/univtln/bruno/samples/jaxrs/security/filter/BasicAuthenticationFilter.java index 4cc921a0ac07b60626bb2a7320f9cbaf4bc3c23d..a431005f235f14cd30c731e1281cb16ece95671d 100644 --- a/src/main/java/fr/univtln/bruno/samples/jaxrs/security/filter/BasicAuthenticationFilter.java +++ b/src/main/java/fr/univtln/bruno/samples/jaxrs/security/filter/BasicAuthenticationFilter.java @@ -22,7 +22,7 @@ import java.util.*; import java.util.stream.Collectors; /** - * The type Authentication filter is a JAX-RS filter (@Provider with implements ContainerRequestFilter) is applied to every request whose method is annotated with @BasicAuth + * Authentication filter is a JAX-RS filter (@Provider with implements ContainerRequestFilter) is applied to every request whose method is annotated with @BasicAuth * as it is itself annotated with @BasicAuth (a personal annotation). * It performs authentication and check permissions against the acceded method with a basic authentication. */