Note that our project was based on the linked in the reference below, we just made some modifications so that it will work on a newer version of jboss.
Tech Stack
- JavaEE6 / 7
- JBoss EAP 6.2
Things to remember
- Download resteasy-jaxrs-3.0.6.Final-all.zip
- Extract the zipped file and inside it find the folder: resteasy-jboss-modules-3.0.6.Final
- Copy all the folders inside it and paste into JBOSS_HOME/modules.
- In web.xml, we don't add any resteasy related parameters, instead it should look like this.
- Create a web service activator.
- And finally the rest request interceptor:
- To test if the filter will really be triggered when there is a rest web service request, I've provided an action bean and a jersey client that sends a request with username and password
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
<display-name>JAX-RS 2.0 Security Demo</display-name>
</web-app>
package com.kalidadbiz;
import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;
/**
* @author Edward P. Legaspi
**/
@ApplicationPath("/api/rest")
public class JaxRsActivator extends Application {
}
package com.kalidadbiz;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.StringTokenizer;
import javax.annotation.security.DenyAll;
import javax.annotation.security.PermitAll;
import javax.annotation.security.RolesAllowed;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response;
import javax.ws.rs.ext.ExceptionMapper;
import javax.ws.rs.ext.Provider;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jboss.resteasy.core.Headers;
import org.jboss.resteasy.core.ResourceMethodInvoker;
import org.jboss.resteasy.core.ServerResponse;
import org.jboss.resteasy.util.Base64;
/**
* @author Edward P. Legaspi
*
* http://java.dzone.com/articles/java-ee-7-and-jax-rs-20
**/
@Provider
public class RESTSecurityInterceptor implements
javax.ws.rs.container.ContainerRequestFilter,
ExceptionMapper<Exception> {
private Log log = LogFactory.getLog(RESTSecurityInterceptor.class);
private static final String AUTHORIZATION_PROPERTY = "Authorization";
private static final String AUTHENTICATION_SCHEME = "Basic";
private static final ServerResponse ACCESS_DENIED = new ServerResponse(
"Access denied for this resource", 401, new Headers<Object>());;
private static final ServerResponse ACCESS_FORBIDDEN = new ServerResponse(
"Nobody can access this resource", 403, new Headers<Object>());;
private static final ServerResponse SERVER_ERROR = new ServerResponse(
"INTERNAL SERVER ERROR", 500, new Headers<Object>());
@Override
public void filter(ContainerRequestContext requestContext) {
log.info("filter");
ResourceMethodInvoker methodInvoker = (ResourceMethodInvoker) requestContext
.getProperty("org.jboss.resteasy.core.ResourceMethodInvoker");
Method method = methodInvoker.getMethod();
// Access allowed for all
if (!method.isAnnotationPresent(PermitAll.class)) {
// Access denied for all
if (method.isAnnotationPresent(DenyAll.class)) {
requestContext.abortWith(ACCESS_FORBIDDEN);
return;
}
// Get request headers
final MultivaluedMap<String, String> headers = requestContext
.getHeaders();
// Fetch authorization header
final List<String> authorization = headers
.get(AUTHORIZATION_PROPERTY);
// If no authorization information present; block access
if (authorization == null || authorization.isEmpty()) {
requestContext.abortWith(ACCESS_DENIED);
return;
}
// Get encoded username and password
final String encodedUserPassword = authorization.get(0)
.replaceFirst(AUTHENTICATION_SCHEME + " ", "");
// Decode username and password
String usernameAndPassword = null;
try {
usernameAndPassword = new String(
Base64.decode(encodedUserPassword));
} catch (IOException e) {
requestContext.abortWith(SERVER_ERROR);
return;
}
// Split username and password tokens
final StringTokenizer tokenizer = new StringTokenizer(
usernameAndPassword, ":");
final String username = tokenizer.nextToken();
final String password = tokenizer.nextToken();
// Verifying Username and password
log.info(username);
log.info(password);
// Verify user access
if (method.isAnnotationPresent(RolesAllowed.class)) {
RolesAllowed rolesAnnotation = method
.getAnnotation(RolesAllowed.class);
Set<String> rolesSet = new HashSet<String>(
Arrays.asList(rolesAnnotation.value()));
// Is user valid?
if (!isUserAllowed(username, password, rolesSet)) {
requestContext.abortWith(ACCESS_DENIED);
return;
}
}
}
}
private boolean isUserAllowed(final String username, final String password,
final Set<String> rolesSet) {
boolean isAllowed = false;
// Step 1. Fetch password from database and match with password in
// argument
// If both match then get the defined role for user from database and
// continue; else return isAllowed [false]
// Access the database and do this part yourself
// String userRole = userMgr.getUserRole(username);
String userRole = "ADMIN";
// Step 2. Verify user role
if (rolesSet.contains(userRole)) {
isAllowed = true;
}
return isAllowed;
}
@Override
public Response toResponse(Exception exception) {
// TODO Auto-generated method stub
return null;
}
}
package com.kalidadbiz;
import java.util.Properties;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.WebResource;
import com.sun.jersey.api.client.filter.HTTPBasicAuthFilter;
/**
* @author Edward P. Legaspi
**/
public class RestClient {
private Log log = LogFactory.getLog(RestClient.class);
private String host;
private String api;
private Properties properties = new Properties();
public RestClient() {
}
public RestClient(String host, String api) {
this.host = host;
this.api = api;
}
public void addParam(String key, String value) {
properties.put(key, value);
}
public String execute() {
try {
Client client = Client.create();
client.addFilter(new HTTPBasicAuthFilter("edward", "edward"));
String params = "";
if (properties != null) {
for (String key : properties.stringPropertyNames()) {
String value = properties.getProperty(key);
if (params != null) {
params += "&";
}
params += key + "=" + value;
}
}
String apiUrl = host + "/" + api;
if (params != null && params.length() > 0) {
apiUrl = apiUrl + "?" + params;
}
WebResource webResource = client.resource(apiUrl);
ClientResponse response = webResource.accept("application/json")
.get(ClientResponse.class);
if (response.getStatus() != 200) {
throw new RuntimeException("Failed : HTTP error code : "
+ response.getStatus());
}
return response.getEntity(String.class);
} catch (Exception e) {
log.error(e.getMessage());
return "";
}
}
public String getHost() {
return host;
}
public void setHost(String host) {
this.host = host;
}
public String getApi() {
return api;
}
public void setApi(String api) {
this.api = api;
}
}
And lastly, don't forget to encrypt your password :-).
0 nhận xét:
Đăng nhận xét