07. Authentication. Filters. Basic Authentication.
Java Brains tutorial shows several ways of authentication.
In the tutorial videos, it is shown how to use Postman to see the headers
To send authentication is:
Authorization: Basic xxxxxxxxxxxxxxxxx
where xxxxxxxxxxxxxxxxx is username:password (user name and password separated by a colon) in base64 encoding
Here is a "Basic Authentication" that Postman lets you use:
You can see how user and password are supplied. But also the conversion
Nothing is special unless we add a filter. There are some things to consider:
In order to execute this code, we should deactivate other filters that we have created before or else we can get into trouble.
If we run the code we get no success as we haven't provided user and password.
But from Postman we can
1. Filters
First introduces the concept of filters that have methods to implement from the interfaces:- ContainerRequestFilter
- ContainerResponseFilter
In the response, the given example, a parameter is added to the header ("MyHeaderParam" with value "Ximo Dante"). Notice the @Provider annotation
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | package org.ximodante.jaxrs.client; import java.io.IOException; import javax.ws.rs.container.ContainerRequestContext; import javax.ws.rs.container.ContainerRequestFilter; import javax.ws.rs.container.ContainerResponseContext; import javax.ws.rs.container.ContainerResponseFilter; import javax.ws.rs.ext.Provider; @Provider public class RestFilter implements ContainerRequestFilter, ContainerResponseFilter{ //01. Method from ContainerRequestFilter interface. Notice it has only one parameter @Override public void filter(ContainerRequestContext requestContext) throws IOException { //Shows headers in the System.out.println("Request filter"); System.out.println("Headers: " + requestContext.getHeaders()); } //02. Method from ContainerResponseFilter interface. Notice it has 2 parameters @Override public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) throws IOException { // Add a header to the response responseContext.getHeaders().add("MyHeaderParam", "Ximo Dante"); System.out.println("Response filter"); System.out.println("Headers: " + responseContext.getHeaders()); } } |
In the tutorial videos, it is shown how to use Postman to see the headers
2. Authentication Mechanisms
2.1 Session authentication:
In the session authentication, the user and password is provided and the server returns a session id that should be supplied at every request to the server. This session id is saved in the client by means of a cookie. But REST is STATELESS, so no sessiñon is stored. This is not valid for REST services2.2 Classic User-password authentication
As REST is stateless, the credentials should be passed in every request. They are normally in the header. You must use HTTPS or else this credential may be sniffed.To send authentication is:
Authorization: Basic xxxxxxxxxxxxxxxxx
where xxxxxxxxxxxxxxxxx is username:password (user name and password separated by a colon) in base64 encoding
2.3 Digest access authentication
A secret key is encripted and is used.2.4 Asymmetric cryptography
The classic use of a private key and a public key to encrypt and decrypt information2.5 OAuth version 1 and 2
Are 2 different protocols2.6 JSON Web Tokens
...3. Basic Authentication
Here is a "Basic Authentication" that Postman lets you use:
You can see how user and password are supplied. But also the conversion
3.1 Secure API
First, let's create a secure resource class1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | package org.ximodante.jaxrs; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.core.MediaType; @Path("secured") public class MySecureResource { @GET @Produces (MediaType.TEXT_PLAIN) public String securedMethod() { return "You need basic login to use this API! But you have been loogged in!,Cheers!"; } } |
Nothing is special unless we add a filter. There are some things to consider:
- Line 18: The secure API is restricted only to the prefix "secured"
- Lines 14 & 15: For "Base authorization" only the header marked with "Authorization" with "Basic" has user and password in Base64 code which is decoded in line 36
- Line 51: A response to an unauthorized request is supplied.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 | package org.ximodante.jaxrs; import java.io.IOException; import java.util.List; import javax.ws.rs.container.ContainerRequestContext; import javax.ws.rs.container.ContainerRequestFilter; import javax.ws.rs.core.Response; import javax.ws.rs.ext.Provider; import org.glassfish.jersey.internal.util.Base64; @Provider public class SecureFilter implements ContainerRequestFilter { private static String AUTH_HEADER_KEY = "Authorization"; private static String AUTH_HEADER_PREFIX = "Basic"; //00. If no secure prefix is supplied then all the request will be secured private static String SECURED_URL_PREFIX = "secured"; @Override public void filter(ContainerRequestContext requestContext) throws IOException { boolean noAuth=true; // 00. Select the path to secure if(requestContext.getUriInfo().getPath().contains(SECURED_URL_PREFIX)) { //01. Get the header key List<String> authHeader =requestContext.getHeaders().get(AUTH_HEADER_KEY); if (authHeader !=null && authHeader.size() >0) { //02. Remove the "Basic" prefix String authToken=authHeader.get(0) .replaceFirst(AUTH_HEADER_PREFIX, ""); System.out.println(authToken); //03. Decode from Base64 String decodedString=Base64.decodeAsString(authToken.trim()); System.out.println(decodedString); String[] s=decodedString.split("\\:"); String userName="kkkkkk"; String password="qqqqqq"; if (s!=null && s.length==2) { userName=s[0]; password=s[1]; } // 04. Check user & pasword values if ("Ximo".equals(userName) && "Dante".equals(password)) noAuth=false; } } // 05. Unauthorized response if (noAuth) { Response unAuthStatus= Response .status(Response.Status.UNAUTHORIZED) .entity("User cannot access the resource") .build(); // 06. Abort the request requestContext.abortWith(unAuthStatus); } } } |
In order to execute this code, we should deactivate other filters that we have created before or else we can get into trouble.
If we run the code we get no success as we haven't provided user and password.
But from Postman we can
Comentarios
Publicar un comentario