Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Handling a basic/base64 security 401 exception in RestEasy and Tomcat

There many ways to get a good security for REST(easy) services. I tried already. In this case only is a Basic Authentication needed. So, not based on login, RequestFilters, etc. Please focus on this example.

While adding security to one RestEasy 'post' method, I keep on getting 401 exceptions. How can I get secure access to the 'post'? I used the the Authenticator code of Adam Bien / Atjem König.

Without the security settings in the web.xml I get normal access, so that part of the code is working fine. I don't need/want any login-screen in between.

Tomcat users: conf/tomcat-users.xml:

 <user username="wineuser" password="winepass" roles="winer"/>

Web.xml file:

<security-constraint>
    <web-resource-collection>
        <web-resource-name>wine secret</web-resource-name>
        <url-pattern>/rest/wines/secret</url-pattern>
        <http-method>POST</http-method>
    </web-resource-collection>
    <auth-constraint>
        <role-name>winer</role-name>
    </auth-constraint>
</security-constraint>
<login-config>
    <auth-method>BASIC</auth-method>
</login-config>
<security-role>
    <role-name>winer</role-name>
</security-role>

Application class:

@ApplicationPath("/rest")
public class RestEasyWineServices extends Application {
}

Authenticator utils:

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import javax.ws.rs.client.ClientRequestContext;
import javax.ws.rs.client.ClientRequestFilter;
import javax.ws.rs.core.MultivaluedMap;
import javax.xml.bind.DatatypeConverter;

public class Authenticator implements ClientRequestFilter {
    private final String user;
    private final String password;
    public Authenticator(String user, String password) {
        this.user = user;
        this.password = password;
    }
    public void filter(ClientRequestContext requestContext) throws IOException {
        MultivaluedMap<String, Object> headers = requestContext.getHeaders();
        final String basicAuthentication = getBasicAuthentication();
        headers.add("Authorization", basicAuthentication);
    }
    private String getBasicAuthentication() {
        String token = this.user + ":" + this.password;
        try {
            return "Basic " +
                 DatatypeConverter.printBase64Binary(token.getBytes("UTF-8"));
        } catch (UnsupportedEncodingException ex) {
            throw new IllegalStateException("Cannot encode with UTF-8", ex);
        }
    }
}

Resource class and method:

@Path("/wines")
public class WineResource {
    ...
    @POST @Path("secret")
    @Produces({ MediaType.APPLICATION_JSON })
    @Consumes({ MediaType.APPLICATION_JSON})
    public Wine echoPostWineSecret( Wine inputWine2) {
        System.out.println( "Server: **SECRET** post (" + inputWine2 + ")");
        inputWine2 = dao.create(inputWine2);
        return inputWine2;
    }
}

Client class:

Client clientSecret = ClientBuilder.newClient().register(new Authenticator( "wineuser", "winepass"));
WebTarget targetSecret = clientSecret.target("http://localhost:8080").path("/RestRestEasyJquerySqlite2Hibernate/rest/wines");

wine.setId( 1231);
wine.setName( "secret wine name_" + dateKey);
wine.setCountry( "secret wine country_" + dateKey);
wine.setGrapes( "secret wine grapes_" + dateKey);
wine.setRegion( "secret wine region_" + dateKey);
try { 
    wine = targetSecret.path( "secret").request( MediaType.APPLICATION_JSON_TYPE).post( Entity.entity( wine, MediaType.APPLICATION_JSON_TYPE), Wine.class);
    System.out.println( "SECRET created wine: " + wine);
} catch( Exception e) {
    System.out.println( "ERROR: Back on the client: exception");
    e.printStackTrace();
}
like image 224
tm1701 Avatar asked Dec 07 '16 20:12

tm1701


1 Answers

The quoted software was correct. The deployment was wrong.

The problem of getting the 401 exception was that the software was deployed on the Eclipse linked private Tomcat server. On that server no configuration was made with users.

The solution of the problem was to export the WAR file to the separate Tomcat server. On this Tomcat server I configured the users via the tomcat-users config file.

like image 107
tm1701 Avatar answered Oct 09 '22 16:10

tm1701