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();
}
::and|separator devices to introduce home-made tags - use the tagging system for that. - halfer